; Calaym - Media player GUI for sound systems
; Copyright (C) 2002-2014 Jan Vorel
;
; You can redistribute the official software packages under the terms of the
; User-friendly Distribution License Version 2.00, published by Jan Vorel
;
; You can use this software under the terms of the
; User-friendly Open-source License Version 1.00, published by Jan Vorel
;
; You should have received copies of the licenses along with this program. If
; not, contact the author.
;
; If you want to use or distribute this software under a different license, ask
; the author.
;
; The software is provided "as is" without warrenty of any kind. The Licensor
; cannot be held responsible for any damage caused by using, extracting or
; installing the software.

EnableExplicit

Macro GrabError()
  ;GrabErrorVar = Timer
  EndMacro

Macro CopyStructureEx(PLIS, PLID, tPlaylistItem)
  ;Debug "Before: " + PLIS\Filename
  ;CopyStructure(PLIS, PLID, tPlaylistItem)
  PLID\Filename = PLIS\Filename
  PLID\Caption = PLIS\Caption
  PLID\DirDepthFlags = PLIS\DirDepthFlags
  PLID\pxWidthLg = PLIS\pxWidthLg
  PLID\pxWidthSm = PLIS\pxWidthSm
  ;Debug "After: " + PLID\Filename
  EndMacro

#DirectSSLayer = #False
#DragExtText = #False
#UseFileLogging = #True
#UseIRPlugins = #False
#ShowRegKeyStuff = 0
#FlatCastCF17 = 0
#BoldDirs = 98
#NewKeyMode = #True ;also mod & teardown
#TimeTestDebug = #False
#LockWinUpd = 0
#BlockTimeOutHandle = #False

IncludeFile "Calaym_Monolythics.pb"
#IncludePath = "..\shared\"
IncludeFile #IncludePath + "Commons.pb"
Commons_Add("Shell_NotifyIcon")
Commons_Add("LoadResEx_WindowIcon_MultiOS")        ; *** GUIConstsTooltips ***
Commons_Add("WindowToCursorPos")        ; *** GUIConstsTooltips ***
Commons_Add("LoadResString")            ; *** KeyConsts ***
Commons_Add("GetKeyNameText")           ;     KeyConsts
Commons_Add("TxtFileWriter_Main")       ;     KeyConsts
Commons_Add("TxtFileReader_FromRes")    ;     KeyConsts
Commons_Add("TxtFileReader_ParseLines") ;     KeyConsts
Commons_Add("GetTickCountAPI")          ; *** TearDown ***
CompilerIf #DirectSSLayer
  Structure ctSSLayerSongInfoBase
    FormatOK.l ; Boolean
    Format_Frequency.l
    Format_BitRate.l
    Format_Channels.l
    Format_VBR.l ; Boolean
    Format_QualityMulti.f
    TagOK.l ;Boolean
    Tag_Year.l
    Tag_TrackID.l
    EndStructure
  Structure ctSSLayerSongInfoReal Extends ctSSLayerSongInfoBase
    Tag_Artist.i
    Tag_Title.i
    Tag_Album.i
    IR_Name.i
    IR_URL.i
    EndStructure
  Structure ctSSLayerSongInfoNeat Extends ctSSLayerSongInfoBase
    Tag_Artist.s
    Tag_Title.s
    Tag_Album.s
    IR_Name.s
    IR_URL.s
    EndStructure

  #ctSSLayer_CompiledFeature_RefreshDeviceList = 1
  #ctSSLayer_CompiledFeature_MusicPatternBased = 2 ;1 enables SetPanning, 2 enables all
  #ctSSLayer_CompiledFeature_Spectrum = 1
  #ctSSLayer_CompiledFeature_CD_AndOr_CDDA = 1
  #ctSSLayer_CompiledFeature_EndCallBack = 1
  #ctSSLayer_CompiledFeature_InetStreams = 1
  #ctSSLayer_CompiledFeature_SetLoops = 0

  #ctSSLayer_CompiledFeature_NoNeedUnicodeConversion_AtoW = #False
  #ctSSLayer_CompiledFeature_NoNeedUnicodeConversion_WtoA = #True
  #ctSSLayer_CompiledFeature_ReadTags = #True
  #ctSSLayer_CompiledFeature_GetDeviceFromSSLID = #True
  #ctSSLayer_CompiledFeature_GetDeviceSSLID = #True
  CompilerIf #PB_Compiler_Unicode

    #ctSSLayer_CompiledFeature_ReadTagsW = #True
    #ctSSLayer_CompiledFeature_LoadSongW = #True
    #ctSSLayer_CompiledFeature_GetDeviceNameW = #True
    #ctSSLayer_CompiledFeature_GetDeviceSSLIDW = #True
    #ctSSLayer_CompiledFeature_GetDeviceFromSSLIDW = #True
    #ctSSLayer_CompiledFeature_GetInfoStringW = #True
    #ctSSLayer_CompiledFeature_ReadTagsA = #False
    #ctSSLayer_CompiledFeature_LoadSongA = #False
    #ctSSLayer_CompiledFeature_GetDeviceNameA = #False
    #ctSSLayer_CompiledFeature_GetDeviceSSLIDA = #False
    #ctSSLayer_CompiledFeature_GetDeviceFromSSLIDA = #False
    #ctSSLayer_CompiledFeature_GetInfoStringA = #False
    CompilerElse
    #ctSSLayer_CompiledFeature_ReadTagsW = #True
    #ctSSLayer_CompiledFeature_LoadSongW = #True
    #ctSSLayer_CompiledFeature_GetDeviceNameW = #True
    #ctSSLayer_CompiledFeature_GetDeviceSSLIDW = #True
    #ctSSLayer_CompiledFeature_GetDeviceFromSSLIDW = #True
    #ctSSLayer_CompiledFeature_GetInfoStringW = #True
    #ctSSLayer_CompiledFeature_ReadTagsA = #False
    #ctSSLayer_CompiledFeature_LoadSongA = #False
    #ctSSLayer_CompiledFeature_GetDeviceNameA = #False
    #ctSSLayer_CompiledFeature_GetDeviceSSLIDA = #False
    #ctSSLayer_CompiledFeature_GetDeviceFromSSLIDA = #False
    #ctSSLayer_CompiledFeature_GetInfoStringA = #False
    CompilerEndIf


  XIncludeFile("ctSSLayer_FModEx.pb")
  CompilerElse
  Commons_Add("ctSSLayer")                ;     TearDown
  CompilerEndIf
Commons_Add("DoEventsEx_Sleep")         ;     TearDown
Commons_Add("TaskBarProgress")          ;     TearDown / DoAnimateReadDirIcon
Commons_Add("LoadResEx_Image_MultiOS")  ;     TearDown / DoAnimateReadDirIcon
Commons_Add("ThemingAPI")               ; *** Main ***
Commons_Add("Ellipsis_PathSmartStart")
Commons_Add("GetAPIPopupMenu")
Commons_Add("TxtFileWriter_AppendFile")
Commons_Add("ChangeWindowMessageFilterEx")
Commons_Add("RegisterDeviceNotification_RegisterAll")
Commons_Add("RegisterDeviceNotification_UnregisterAll")
Commons_Add("ExitWindowsDialog")
Commons_Add("SoundSchemes_ReadAll")
Commons_Add("SoundSchemes_Write")
Commons_Add("SoundSchemes_ClearAll")
Commons_Add("RegisterFileTypes")
Commons_Add("TxtFileWriter_Main")
Commons_Add("HtmlHelp")
CompilerIf Not #PB_Compiler_Processor = #PB_Processor_x64
  Commons_Add("WinHelp")
  CompilerEndIf
Commons_Add("ShutdownWindowsEx")
Commons_Add("GetSpecialFolderPath")
CompilerIf #UseFileLogging
  Commons_Add("SizeToXiBString")
  CompilerEndIf
Commons_Add("GlobalMemoryStatusEx")
Commons_Add("SetProcessDPIAware")
Commons_Add("GetStrippedCommandLine")
Commons_Add("GetFileVersionField")
Commons_Add("GetDlgItemText")
Commons_Add("MakePopupMenu")
Commons_Add("DragQueryFile")
Commons_Add("LoadResEx_Menu_GetCaption")
Commons_Add("LoadResEx_Menu_SetCaption")
Commons_Add("GetFullFromRelativeFilename")
Commons_Add("DoEventsEx_SleepPeriodical")
Commons_Add("TxtFileReader_GetEncoding")
Commons_Add("TxtFileReader_SetEncodingReset")
Commons_Add("URLEncode")
Commons_Add("URLDecode")
Commons_Add("DoEventsEx")
Commons_Add("GetWindowText")
Commons_Add("TrackListBox")
Commons_Add("BinaryBuffer_GetMemPtr")
Commons_Add("RegisterClassEx")
Commons_Add("BinaryBuffer_GetMemSize")
Commons_Add("GetSaveFileName")
;Commons_Add("HyperLinkList_InfoDialog")
;Commons_Add("PropertySheetCollection")
;Commons_Add("ThemingAPI")
;Commons_Add("RegisterDeviceNotificationAPI")
;Commons_Add("AppBase")
Commons_Add("BitmapStretchCopyEx") ; info dialog
Commons_Add("LoadStringExML") ; info dialog
Commons_Add("LoadIconExML") ; info dialog
Commons_Add("HyperLinkList_InfoDialog") ; info dialog
Commons_Add("PropertySheetCollection") ; setup dialog
IncludeFile "Calaym_Prelythics.pb"
IncludeFile "Calaym_GUIConsts.pb"

























Declare MainForm_ctConsoleA_AddLog(MsgString.s)
IncludeFile "Calaym_KeyConsts.pb"
Declare MainForm_TearIconChance()
Declare DoAnimateReadDir(xStep.i)
Declare ShowIRI()
Declare MainForm_ProcessKey(Index.i, xKioskModeParam = #True)
Declare MainForm_HideIRWin()

IncludeFile "Calaym_TearDown.pb"
; declare multi-function-depending callers
Declare MainForm_MenuEvent(MenuID.i)
Declare MainForm_IconsMouseUp(Index.i)
Declare.i SplitterProcTH(hWnd.i, Message.i, wParam.i, lParam.i)
Declare.i SplitterProcLW(hWnd.i, Message.i, wParam.i, lParam.i)
Declare.i ProcClassWnd(hWnd.i, Message.i, wParam.i, lParam.i)
Declare.i PlayerFormProc(hWnd.i, Message.i, wParam.i, lParam.i)
Declare.i ListsHook(hWnd.i, Message.i, wParam.i, lParam.i)
Declare.i BARHook(hWnd.i, Message.i, wParam.i, lParam.i)
Declare.i ToggleInterface(NewID.i)
Declare MainForm_MenuEventPlaylist(Index.i)
Declare MainForm_LockMe(vBool1.i)
Declare.i PLWriter_Save(Filename.s, OverWriteDef.i)
Declare MainForm_UpdateMyFont()
Declare MainForm_xBuildDirs()
Declare.i xPlayItem(CanFade.i, PlaySilent.i, DoCrossFade.i, NoSFXWait.i, ResumePaused.i, ManualURL.s)
Declare MainForm_UpdateMainIcon()
Declare.i xFindNextItem(xStep.i, DontPlay.i, CanFade.i, FindPLOnly.i, DoCrossFade.i)
Declare MainForm_eTimerTime()
Declare MainForm_CheckAfter(CanFade.i, NoStopSong.i, UserDoes.i, EnforceUserDoes.i)
Declare.i ProcessTimerEvent(EventID.i, Filename.s)



Declare SearchForm_Resize(xRight.i, xBottom.i, xTop.i)
Declare SearchForm_CheckBoxTxtChange()
Declare TimerListForm_ApplyLockState()
Declare TimerListForm_ListUpdate()
Declare TimerListForm_Resize(xRight.i, xBottom.i, xTop.i)
Declare TimerListForm_TrySCommandEx(hWndOwner.i, Index.i)
Declare TimerListForm_TryAccel(wParam.i)
Declare TimerListForm_UpdateTimerListWinFont(xFont.i)
Declare TimerForm_PrePreset()
Declare RadioForm_AddRadioEx(Caption.s, URL.s, Homepage.s, ShowInterface.i)
Declare RadioForm_PrePreset()
Declare RadioForm_ReListRadios(ReSelect.i)
Declare RadioForm_Resize(xRight.i, xBottom.i, xTop.i)
Declare RadioForm_TrySCommand(hWnd.i)
Declare RadioForm_UpdateFont(HWndFont.i, UpdateFlag.i)
Declare RadioForm_UpdateRadioVals()

Declare WizardForm_Resize(xRight.i, xBottom.i, xTop.i)

Declare AutoRefresh_ShowDialog()
Declare ShowSetup()
Declare ShowInfo()
Declare ShowTimerEditor()
Declare RadioForm_ShowRadioEditor(*DialogID)

Declare.i PLWriter_Save(Filename.s, OverWriteDef.i)
Declare.i LoadPList(Filename.s, AddOnly.i, InitialDontApplySettings.i)



Macro PrivateDimLong(VarName)
  Global VarName.i
  EndMacro

Macro PublicDimLong(VarName)
  Global VarName.i
  EndMacro

Macro PrivateDimBoolean(VarName)
  Global VarName.i
  EndMacro

Macro PublicDimBoolean(VarName)
  Global VarName.i
  EndMacro

Macro PrivateDimSingle(VarName)
  Global VarName.f
  EndMacro

Macro PublicDimSingle(VarName)
  Global VarName.f
  EndMacro

#LoadShellDriveIcons = #True
#LoudestSongMethode = #True
#AutoDirPosOnTop = #False
#XPDeviceRemoveDetect = #True
#XPDeviceRemoveDetectPST = #False
#TrayXFadeIcon = #True
#NewRemove = #False
#CanEnumComputerShares = #False ;also frmautorefresh!

#FailSaveTest = #False ; skips save settings on quitting so failsave occurs on next start
;#UseFileLogging = 1 ;Set 1 to enable log file handling; set in compiler options!
    ; affects modCalaym.bas, CallBackAddLog
    #UseFileLoggingIDE = #True
    #UseFileLoggingKernel = #True
    #DetailLog = #False
    ; Always english text !!!
#PresetBinded = #True
; Enable / Disable at your own risk; Some features may not work
#AutoHideDropDown = #True ; Check current active window to automatically hide dropdown-lists
;#AlternateCallback = #True
;#CallBackAddLog = #True
#NoClearSpectrum = #False
#MultiGUITimer = #True
#ListFocusedLists = #False




;CompilerIf #False
Global Dim RndPLPattern.b(0)
Global Dim sCharA1.s(0)
Global Dim xDirPath.i(0) ; At least 1 song
CompilerIf #BoldDirs = 98
  Structure tPlaylistItem
    Filename.s
    Caption.s
    DirDepthFlags.w
    pxWidthLg.w
    pxWidthSm.w
    EndStructure
  Global Dim PLI.tPlaylistItem(0)
  CompilerElse
  Global Dim PLIFile.s(0)
  Global Dim PLICap.s(0)
  Global Dim PLIDF.w(0)
  Global Dim PLIPxLg.w(0)
  Global Dim PLIPxSm.w(0)
  CompilerEndIf
;CompilerEndIf
Global GenericMessageHandler_Param.i


PrivateDimLong(xDirListEffDirs)
CompilerIf #AutoDirPosOnTop
  #xDirListEffMax1 = 1
  CompilerEndIf
#xDirListEffMax2 = 4

Global Dim MainForm_XMenuRefresherDevicesIIDs.i(25)
Global hwndShutDownProgress.i
Global ShutDownInitTime.i
#ShutDownTimerMax = 32000
#ShutDownTimerMaxDiv = #ShutDownTimerMax / 100


CompilerIf #LoadShellDriveIcons
  Global Dim ShellDrvIcons.i(2)
  Global Dim ShellDrvDCap.s(25)
  Global Dim ShellDrvDIco.b(25)
  PrivateDimLong(ShellDrvInited)
  CompilerEndIf
#m3uIString = "#Calaym100m3u"
#xTimerIDString = "[CalaymTimerSettings100]"

PrivateDimLong(xTagBoxHeight)
PublicDimSingle(DPIScaleX)
PublicDimSingle(DPIScaleY)
PrivateDimLong(xDefHeight16)
PrivateDimLong(xDefIconTopShift16)
PrivateDimLong(xDefCtlHeight16)
PrivateDimLong(xDefButtonHeight)

#WizardHasLabel = #False
Global SysColor5.i
Global SysColor8.i
Global SysColor13.i
Global SysColor14.i
Global SysColor15.i
Global SysColor17.i
Global SysColor20.i

PrivateDimLong(xIRBarHeight)

#WPL_AnsiTest = #False

CompilerIf #PB_Compiler_Unicode
  #DefaultPLExtension = "m3u8"
  CompilerElse
  #DefaultPLExtension = "m3u"
  CompilerEndIf

CompilerIf Not #PB_Compiler_Processor = #PB_Processor_x64
  Global xUseChmHelp.i
  CompilerEndIf

PrivateDimBoolean(xAutoUSBQuit)
#MouseWheelDeltaDivVol = 120 / 15
#MouseWheelDeltaDivLst = 120 / 3
PrivateDimLong(MouseWheelDeltaVol)
Global Dim MouseWheelDeltaLst.i(2)

#NoDroppingIfOverloaded = #False ; you can still load playlists, timers etc!
Global Dim MainForm_XMenuRefresherFileDir_Counts.i(2)

;xMWindowIDsX
;ttips
;animiconpos

PrivateDimBoolean(CanIRadio)
PublicDimLong(QuitMode)
PublicDimLong(QuitModePending)
PublicDimBoolean(WantsShutdownDialog)
;PublicDimSingle(vShutDownDTimer)
PublicDimLong(hwndShutDownDialog)

Global FormatToolTip1.s
Global FormatToolTip2.s
Global CurSongToolTip1.s
Global CurSongToolTip2.s
Global xTimerDisplayLastParamValue.s


CompilerIf #PB_Compiler_Unicode And #XPDeviceRemoveDetect And #XPDeviceRemoveDetectPST
  Global PendingDeviceRegB.i
  Global PendingDeviceRegT.i
  CompilerEndIf


Global SSRestrictions.s

Global xLoadURL.s
#Interface_Mode_None = 0
#Interface_Mode_Search = 1
#Interface_Mode_Timer = 2
#Interface_Mode_Radio = 3
#Interface_Mode_Wizard = 4
PublicDimLong(InterfaceMode)

PrivateDimBoolean(SearchFormDraggingIs)
PrivateDimLong(SearchFormDraggingWParam)
PrivateDimLong(SearchFormDraggingLParam)
PrivateDimLong(SearchFormDraggingWMsgPlus)

;PrivateDimLong(HWndCapLabel)
;PrivateDimLong(HWndTxt)
;PrivateDimLong(HWndDrop)
;PrivateDimLong(HWndSearchResultList)
PrivateDimLong(TimerListForm_xMenu)
PrivateDimLong(TimerListForm_xMenu2)
PrivateDimLong(TimerListForm_xPopupMenu2)
PrivateDimLong(TimerListUpdateHWnd)

PrivateDimBoolean(TimerListForm_xLocked)
PrivateDimLong(xTimerDisplayExtraLen)
PrivateDimLong(xTimerDisplayExtraLenT)
#xTimerDisplaySpace1 = 16
#xTimerDisplaySpace2 = 16
PublicDimLong(xTimerEditingHWnd)

CompilerIf #WizardHasLabel
  #Interface_Control_Wizard_CapLabel = 0
  #Interface_Control_Wizard_Holder = 1
  #Interface_Control_Wizard_ButtonFirst = 2
  CompilerElse
  #Interface_Control_Wizard_Holder = 0
  #Interface_Control_Wizard_ButtonFirst = 1
  CompilerEndIf
#Interface_Control_Wizard_Help = #Interface_Control_Wizard_ButtonFirst
#Interface_Control_Wizard_AddDir = #Interface_Control_Wizard_ButtonFirst + 1
#Interface_Control_Wizard_AddPList = #Interface_Control_Wizard_ButtonFirst + 2
#Interface_Control_Wizard_AutoRefresh = #Interface_Control_Wizard_ButtonFirst + 3
#Interface_Control_Wizard_IRadio = #Interface_Control_Wizard_ButtonFirst + 4
#Interface_Control_Wizard_ButtonLast = #Interface_Control_Wizard_IRadio
#xStaticIcons_IntroWizCount = #Interface_Control_Wizard_ButtonLast - #Interface_Control_Wizard_ButtonFirst + 1
#xStaticIcons_IntroWizCountSub1 = #xStaticIcons_IntroWizCount - 1
PrivateDimLong(xStaticIcons_IntroWizCtlHeight)
Global Dim IntroWizIcon.i(#xStaticIcons_IntroWizCountSub1)
Global Dim IntroWizText.s(#xStaticIcons_IntroWizCountSub1)
PrivateDimBoolean(IntroWizIconHas)
PrivateDimLong(WizardSelIndex)
PrivateDimLong(WizardSelHWnd)
;#Interface_Control_Wizard_LastHook = #Interface_Control_Wizard_ButtonLast
;#Interface_Control_Wizard_LastAccel = #Interface_Control_Wizard_ButtonLast
;#Interface_Control_Wizard_LastFont = #Interface_Control_Wizard_ButtonLast
PrivateDimLong(WizardMainHookOld)

#Interface_Control_Search_SpecialCheck = 2
#Interface_Control_Search_Check1 = 0
#Interface_Control_Search_Check2 = 1
#Interface_Control_Search_Play = 2
#Interface_Control_Search_Select = 3
#Interface_Control_Search_Return = 4
#Interface_Control_Search_Txt = 5
#Interface_Control_Search_CapLabel = 6
#Interface_Control_Search_LastFontApply = 6
#Interface_Control_Search_Results = 7
#Interface_Control_Search_Image = 8

;#Interface_Control_Search_Last = #Interface_Control_Search_Image ;8
#Interface_Control_Search_LastHook = #Interface_Control_Search_Txt ;5
#Interface_Control_Search_LastAccel = #Interface_Control_Search_Txt ;5

#Interface_Control_Timer_Add = 0
#Interface_Control_Timer_Edit = 1
#Interface_Control_Timer_Remove = 2
#Interface_Control_Timer_RemoveAll = 3
#Interface_Control_Timer_Close = 4
#Interface_Control_Timer_List = 5
#Interface_Control_Timer_CapLabel = 6
#Interface_Control_Timer_Image = 7

;#Interface_Control_Timer_Last = #Interface_Control_Timer_Image ;7
;#Interface_Control_Timer_LastHook = #Interface_Control_Timer_Close ;4
;#Interface_Control_Timer_LastAccel = #Interface_Control_Timer_List ;5
#Interface_Control_Timer_LastFont = #Interface_Control_Timer_CapLabel

#Interface_Control_Radio_Go = 0
#Interface_Control_Radio_Play = 1
#Interface_Control_Radio_OpenHP = 2
#Interface_Control_Radio_AutoCloseCheck = 3
#Interface_Control_Radio_Add = 4
#Interface_Control_Radio_Edit = 5
#Interface_Control_Radio_Remove = 6
#Interface_Control_Radio_Return = 7
#Interface_Control_Radio_Txt = 8
#Interface_Control_Radio_CapLabel = 9
#Interface_Control_Radio_LastFontApply = 9
#Interface_Control_Radio_List = 10
#Interface_Control_Radio_Image = 11

#Interface_Control_Radio_Last = #Interface_Control_Radio_Image ;11
;#Interface_Control_Radio_LastHook = #Interface_Control_Radio_Txt ;8
#Interface_Control_Radio_LastAccel = #Interface_Control_Radio_Txt ;8




#Interface_Control_Last = #Interface_Control_Radio_Last
;#Interface_Control_HookLast = #Interface_Control_Radio_LastHook
#Interface_Control_AccelLast = #Interface_Control_Radio_LastAccel

Global Dim Interface_Control.i(#Interface_Control_Last)
Global Dim Interface_Control_Accel.i(#Interface_Control_AccelLast)







PublicDimBoolean(UrlsAllowed)
PublicDimBoolean(DragOut)

Global LayerHP.s
PrivateDimBoolean(IsDevicePlugging)
PrivateDimBoolean(HasDevicePlugged)
PrivateDimBoolean(HasDevicePlugStoppedSong)
;PublicDimBoolean(DeviceAddAutoPlay)
PrivateDimBoolean(xPStateIconPlugging)

#FirstNonFloppy = 2

#DefTxt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
#LenDefTxt = 26 + 26 +10



PrivateDimLong(PLSHeight)
PrivateDimLong(PLSIconTopShift)
PublicDimLong(PLODHeight)
PrivateDimLong(PLODIconTopShift)

CompilerIf #ListFocusedLists
  PublicDimLong(xCurFocusHWnd)
  CompilerEndIf

; 0/1/2 = play stop pauses

;hdcs / epic:
; 2 = pl anysize
; 3 = pl/def small; req timedisp

; 5 req anim -> tags!!!
; 6 req defaultfont bitmapgen

; fadinganim
; deleting
;refreshing
;quit
;startup


;HaveToDo :
;NoSmooth
;PopupMenu mM!!

;6 - 1
;5+1
; max 6xxxx
; -> 7000-9000 -> pre-strings...
;  900 = tag reading etc
;  900-19 = reset... / unknown stream/tracker/midi/cda
;        0=reset, 4=strea, 8=tracker, 12=midi, 16=cda
;   1x-7x = streams <-> tracker
; 1000 maincaps (playing...) / icons
; 1100 = tooltips / caps...
;   0x -> dirlist, prevlist
;   1x -> buttons itself (prev - next) 7x -> each 4pcs? -> 0 - 28+3, -> 10-49
;   5x -> vol
;   6x -> repeatmode
;   7x -> position, spectrum
;   8x -> timer
;   9x -> addinfo/tags tooltip
; 1200 File dialogs
;   00 = addfiles
;   10 = adddir
;   20 = load/savepl
; 1300 PlayControl dialogs/msg
; 1400 playList dialogs/msg
;   00 = finddialog
; 1500 options dialogs/msg
; 1600 tools dialogs/msg
;   00 = timer lsdialog (5x)
;   10 = timerAsks
;   50 = presetlsdialog
; 1700 help dialogs/msg
;   1780 about / dragmenu

; 1800 - 1900 startup error msgs (/traymenus)
;2 0/1 xx -> Startup
;2 2   xx -> Info
;2 3   xx -> search
;2 4   xx -> arsetup
;2 5   xx FREEEEEEEEEEE
;2 6   xx -> timer
;2 7   xx -> timer edit
;2 8   xx -> ShutDown
;2 9   xx -> SPDisplayIcon
;3  x  xx -> setup

;4  x  xx -> Timer / Edit (0/1 timer 2 edit win 3/4 strings
;4 6/7 xx -> SearchWindow
;4 8   xx -> SPDisplayIcon

; 4000 = internet radio?

#PlayLoosingLog = #False
PrivateDimBoolean(IsMessageing)

PrivateDimBoolean(EnqueueFlag)
Global OutOfSessionLeft.i
PrivateDimBoolean(OutOfSessionHasPaused)
Global OutOfSession_MySessionID.i



PrivateDimBoolean(NeedRestoreReg)
Global LastStreamTT.s

Global GMCD_URL.s
PrivateDimLong(GMCD_Mode)
PrivateDimBoolean(GMCD_Pending)

Global SenderURL.s
Global LockWinUpd.i
Global xAutoSwitchIRadioOEPl.i

Global curTagText.s

;#TrackerSkipperMinValM = -TrackerSkipperMinVal

Global Dim RegFolderMode.i(3) ; boolean!



CompilerIf #UseFileLogging
  PrivateDimLong(PLClearCounter)
  CompilerEndIf


; !!!!!!!!!!!! FMOD depending currently only !!!!!!!!!!!!1
#TryPreventReInit = #False ; Designed to automatically reset output device if playback fails with device busy
    ; (e.g. starting some games cause playback to ;hang;, and when skipping nothing can be played)
    ; not quite finished
#TrayIconViaTimerCheck = 2

;PrivateDimLong(CalaymDragSource)

#xAutoDirCountMax = 256
#xAutoDirCountMaxX = #xAutoDirCountMax - 1
Global Dim xAutoDir.s(#xAutoDirCountMaxX)
PublicDimLong(xAutoDirCount)
Global Dim xAutoRefreshTimer.i(1)
Global Dim xAutoDirHWnd.i(#xAutoDirCountMaxX)
PrivateDimLong(xAutoDirHWndCount)

PrivateDimLong(RegisteredFindMsgID)
PrivateDimLong(CurrentFindHWnd)
PrivateDimLong(CurrentFindHMem)
PrivateDimLong(CurrentFindInvert)
Global CurrentFindMatchCase.i

PrivateDimLong(CurSongPatterns)

Global Dim *FormatIconBMP(4)
Global Dim FormatIconLen(4)

#ShowIRTicksFull = 5000

            
CompilerIf #PresetBinded
  PrivateDimBoolean(xNoPresets)
  CompilerEndIf

PrivateDimBoolean(xNoTimers)

PrivateDimLong(NewSongID)
PrivateDimLong(OldSongID)



CompilerIf #CanEnumComputerShares
  Structure sNETRESOURCE
    dwScope.i
    dwType.i
    dwDisplayType.i
    dwUsage.i
    lpLocalName.i
    lpRemoteName.i
    lpComment.i
    lpProvider.i
    EndStructure
  #sNETRESOURCE_Len.i = 32
  
  CompilerEndIf

PrivateDimLong(xLastPathTimeSpace)
PrivateDimLong(xLastPathCurMaxWidth)


Global LogFile.s
Global LogFileLog.s
PrivateDimBoolean(LogFileMulti)
CompilerIf #UseFileLogging
  PrivateDimBoolean(LogFileDoLog)
  CompilerEndIf
PrivateDimBoolean(LogFileDo)

;PrivateDimLong(xTimerLoaded)
  ; $100 = led               0
  ;($010 = startup / eTimer  2)
  ; ^h001 = GUI def / eTimer  1)


PublicDimLong(xSearchCount)
#xSearchCountMax = 2048
#xSearchCountMaxX = #xSearchCountMax - 1
#xSearchCountOver = #xSearchCountMax + 1
;#xSearchResultDigitsCount = 4

Global Dim xSearch.i(#xSearchCountMaxX)
Global Dim xSearchSortAlias.i(#xSearchCountMaxX)
Global Dim xSearchSortCap.s(#xSearchCountMaxX)
Global Dim xSearchSortDir.i(#xSearchCountMaxX)
Global xSearchError.s


PublicDimLong(xRadioCount)
#xRadioCountMax = 2048
#xRadioCountMaxX = #xRadioCountMax - 1
Global Dim xRadioCap.s(#xRadioCountMaxX)
Global Dim xRadioURL.s(#xRadioCountMaxX)
Global Dim xRadioHP.s(#xRadioCountMaxX)
Global xRadioLastEnteredURL.s
PrivateDimLong(xRadioEditingHWnd)
PrivateDimLong(xRadioEditingEdit)

PrivateDimLong(xRadioMenu)
PrivateDimLong(xRadioMenu2)
PrivateDimLong(xRadioPopupMenu2)

#STARTF_USESHOWWINDOW = 1
#STARTF_USESIZE = 2
#STARTF_USEPOSITION = 4





Global xVolTTText.s
Global xModeTTText.s
PrivateDimBoolean(xNoPLMenu)
PrivateDimBoolean(xNoQuitMenu)
PrivateDimBoolean(xNoSetup)
PrivateDimBoolean(xNoAutoSetup)
PrivateDimBoolean(xNoAutoRefreshByUser)
PrivateDimBoolean(xNoAutoRefresh)
PrivateDimLong(xNoSpectrumForce)
#SpectrumProcIntervalKb = 100
PrivateDimLong(LastPosTime)
#LastPosSkipTime = 1000
#LastPosSkipTimeNetStream = 8000
PrivateDimLong(xProcID)





;PrivateDimLong(CrossFadeModeXX = 0
; 0 = ~  1.5 secs superfade
; 1 = ~  6.5 secs
; 2 = ~ 11.5 secs
; 3 = ~ 16.5 secs
Global xCrossFadeTimeMC.i

#CrossFadeWaitTime = 1000 ; Wait time if seeking fails; should be <= WaitSeek
#CrossFadeWaitSeek = 1000 ; Seek time for new song
#CrossFadeWaitSkipPattern = 1 ; seek pattern (mod)

;PrivateDimLong(xWaitKey)
;PrivateDimLong(xCrossFadeTime)
Global xCrossFadeTimeM.i

#xFadeConsts1 = 2
#xFadeConsts2 = 20
;#xFadeConsts2x = xFadeConsts2 - xFadeConsts1
#xFadeConstsX = #xFadeConsts2 - #xFadeConsts1 ;- 1

;#CrossFadeWaitEndTime = 600  ;500
Global Dim CrossFadeTimeSingle.i(#xFadeConstsX) ; Pure fade time each song
Global Dim CrossFadeTimeDelay.i(#xFadeConstsX) ; Delay (or time not really fading each song)

  Global Dim CrossFadeMinTime.i(#xFadeConstsX) ; requ length cursong or newsong
    Global Dim CrossFadeNewMinMinTime.i(#xFadeConstsX)                ;requ length  newsong on userends
  Global Dim CrossFadeMaxPos.i(#xFadeConstsX)           ; pos1 (TimerEvent checking)
  Global Dim CrossFadeMinPos.i(#xFadeConstsX)           ; pos2 (TimerEvent checking)
  Global Dim CrossFadeMinRemainTime.i(#xFadeConstsX)                  ;requ remaining time
    
  Global Dim CrossFadeMinPatterns.i(#xFadeConstsX) ;requ pattern cursong or newsong
    Global Dim CrossFadeNewMinMinPatterns.i(#xFadeConstsX)        ;requ pattern newsong on userends
  Global Dim CrossFadeMaxPattern.i(#xFadeConstsX) ;pos1 (TimerEvent checking)
  Global Dim CrossFadeMinPattern.i(#xFadeConstsX) ;pos2 (TimerEvent checking)
  Global Dim CrossFadeMinRemainPatterns.i(#xFadeConstsX) ;requ remaining pattern
    

#CannotPlayAbortTime = 3000
PrivateDimLong(xTrayIconOld)
Global CDDriveLetters.s

;32736


PrivateDimBoolean(xWarnOverload)
PrivateDimBoolean(xOldWarnOverload)

#xLastPathMax = 1024
#xLastPathMaxX = #xLastPathMax - 1
Global Dim xLastPath.s(#xLastPathMaxX)
Global Dim xLastPathCap.s(#xLastPathMaxX)
Global Dim xLastPathTime.s(#xLastPathMaxX)
Global Dim xLastPathLen.i(#xLastPathMaxX)
PrivateDimLong(xLastPathCount)

#Test256 = #False
CompilerIf #Test256
  CompilerElse
  #PLCountMax95 = 32700 ;32736
  CompilerEndIf
PrivateDimLong(PLCountMax)
PrivateDimLong(PLCountMaxX)
PrivateDimLong(PLCountMaxX2)
PrivateDimLong(PLCountWarn)

#RandomizerPattern = 16
PrivateDimLong(RndPLPatternCount)
Global Dim RndPatternAlias.b(#RandomizerPattern - 1)


;PrivateDimBoolean(xOLEisDragging)
PrivateDimBoolean(xPStateIconRefreshing)
PrivateDimLong(xLastSkipDirection)
PrivateDimLong(xXFadeCurMusic)
;PrivateDimLong(xSongWasMidi)
PrivateDimLong(xSongWillBeMidi)
;PrivateDimLong(xXFadeCDDriveLetterByte As Byte
PrivateDimLong(xXFadeOldTime)

;PrivateDimLong(xCDDriveLetterByte As Byte
PublicDimLong(xOldIconState)


PrivateDimLong(xTimerTimeTimerTime)
PrivateDimLong(xEndSongTimerEventTime)
Global Dim xAutoRefreshTimerEventTime.i(1)

CompilerIf #TrayIconViaTimerCheck
  PrivateDimLong(xTrayIconCrashUpdateTimer)
  CompilerIf #TrayIconViaTimerCheck = 1
    #xTrayIconCrashUpdateTimerDelay = 300000 ;300 secs = 5 mins
    CompilerElse
    #xTrayIconCrashUpdateTimerDelay = 30000 ;300 secs = 5 mins
    CompilerEndIf
  CompilerEndIf
PrivateDimLong(xAutoPlaybackLastRetryTime)
;PrivateDimLong(xOldDropRepeat)

;#MAX_PATH = 260
;#INVALID_HANDLE_VALUE = -1


PrivateDimBoolean(xIsVoluming)
PrivateDimLong(PLCurSongLastPos)
PrivateDimLong(PLCurSongPos)


PrivateDimLong(xFollowCurSongLast)
PrivateDimLong(xFollowCurSongLastDiff) ;Time that has to be elapsed since new song started due FollowCurrentSong to delete current song (to ensure the new song is to be deleted and not the old one that finished a few ms before)
  #xFollowCurSongLastDiffDef = 1500 + 225 ;FadingTimerEx = 225

Global xCurPlistFilename.s
PrivateDimBoolean(xCurPlistFilenameSuggestNew)
Global PLCurSongDisplay.s
PrivateDimLong(PLCurSongDisplaySpace)
PrivateDimLong(PLCurSongDisplaySpacePerc)
PrivateDimLong(PLCurSongDisplaySpacePos)
PrivateDimLong(PLCurSongDisplaySpacePosOrg)
Global PLCurSongDisplaySpaceStr.s
Global PLCurFullURL.s
Global PLCurSong.s
Global xFindNextString.s
PrivateDimLong(NSCursor)
PrivateDimLong(WECursor)

PrivateDimLong(lPlayList_Height)

PrivateDimLong(PLNext)
Global PlNextSong.s
Global PlNextSongCap.s


PublicDimBoolean(xNoRemove)

Global DirLblCaption.s
PrivateDimBoolean(ReAutoPlayDR)
PrivateDimLong(ReAutoPlayDRTime)

;PrivateDimLong(xCurSmallFont)

PrivateDimLong(xGUIClickDelayTimer)

PrivateDimBoolean(MainFormDraggingIs)
PrivateDimLong(MainFormDraggingWParam)
PrivateDimLong(MainFormDraggingLParam)
PrivateDimLong(MainFormDraggingWMsgPlus)

#xDirListMinTH = 1
#xDirListMaxTH = 8
#xDirListDivTH = 10

#xDirListMinLW = 20
#xDirListMaxLW = 80
#xDirListDivLW = 100

PublicDimLong(xDirListModeSet)
PublicDimLong(xDirListModeCur)
PublicDimLong(xDirListTopHeight)
PublicDimLong(xDirListLeftWidth)

PrivateDimLong(PlayControlsTop)
PublicDimLong(eSPTopX)
PublicDimLong(eSPTopY)
PrivateDimLong(CurSongPosRealHeight)
Global PanelSizeNow.i
Global PanelSizeDef.i
Global PanelSizeTags.i
PrivateDimLong(AnimExtraPadding)
PrivateDimLong(SongPosScrollWidth)
PrivateDimLong(SpectrumTop)
PrivateDimLong(SpectrumMinLeft)
PrivateDimLong(SpectrumWidth)
PrivateDimLong(SpectrumHeight)
PrivateDimLong(HWndSplitterTH)
PrivateDimLong(HWndSplitterLW)
PrivateDimLong(HWndSplitterMoveTH)
PrivateDimLong(HWndSplitterMoveLW)
PrivateDimLong(SplitterPreResult)

PublicDimBoolean(ShowIRWin)
PrivateDimLong(xNoSaveListMenu)

#xMenuCountX = 8
Global Dim xMenu.i(#xMenuCountX)  ; 2 CD Popups
Global Dim xPopupMenu.i(#xMenuCountX)

Global.NOTIFYICONDATA SysTrayIcon
Global CommandX.s

PublicDimBoolean(xTrayIconIndicator)


#ReadDirectory_xArraySMax = 32767
#ReadDirectory_xArraySMaxX = #ReadDirectory_xArraySMax - 1
Global Dim ReadDirectory_xArrayS.s(#ReadDirectory_xArraySMaxX)



Global sCharA1Max.i
Global sCharA1MaxX.i

PrivateDimLong(xDirCount)

PrivateDimBoolean(xPStateIconQuit)


#PLIconFolderFake = 100
#PLIconFileFake = 200

Global PLIconFolder.i
Global PLIconFile.i
PrivateDimLong(PLIconURL)
PrivateDimLong(Interface_Icon)
#PLIconFolder_ResID = 1700 ;1350
#PLIconFile_ResID = 1750 ;1065
#PLIconURL_ResID = 2800 ;1065

#PLIconSearch_ResID = 2300 ;1065
#PLIconTimer_ResID = 2600 ;1065
#PLIconRadio_ResID1 = 2820 ;1065
#PLIconRadio_ResID2 = 2840 ;1065

CompilerIf #BoldDirs = 98
  #PLISize = SizeOf(tPlaylistItem) ; 14 if w9x
  CompilerElse
  #PLISize = 20 ; 14 if w9x
  CompilerEndIf
  

#PLI_Depth = $1FFF
#PLI_IsDir = $2000
#PLI_IsAuto = $4000

PublicDimLong(PLCount)
PrivateDimLong(PLCurItem)

;PrivateDimLong(hwndSpektrumHook)
PrivateDimLong(xFindNtfy)
PrivateDimBoolean(xTimerIsEnabled)




Global Dim xListHWndHook.i(2)
PrivateDimLong(VolumeHookOld)
PrivateDimLong(BARHookOld)

PrivateDimLong(SplitterMoveTopOrLeftPos)

PrivateDimLong(xSharedDCOldFont)
PrivateDimLong(hFontPLLg)
PublicDimLong(hFontPLLgB)
PrivateDimLong(hFontPLSm)
PublicDimLong(hFontGSys) ; global dialog unit stuff
PublicDimLong(hFontGFix) ; win default font in my size?
PrivateDimLong(hFontIntroWiz)
PrivateDimLong(hFontShIR)
PrivateDimBoolean(hFontShIRIsVerticalBitmapFont)
PrivateDimLong(VertIRBarHeight)
Global NeedIRPathElipse.s
Global ShownIRPath.s

Structure InitCommonControlsExType
  dwSize.i
  dwICC.i
  EndStructure
;PrivateDimLong(FirstDown.i

; 0=calaymclass -> custom
; 1=animstuff   -> playlistsize    2   ok
; 2=dropdown1   -> smallgeneric    3



CompilerIf #FlatCastCF17
  Dim xFCI As CCtrlProd
  CompilerEndIf

;Global DragClass.IDropTarget
;PublicDimBoolean(IsVistaOrXP)

Global CurrentFindType.FINDREPLACE

Global GBN2.s
;Global GBN3.s

Global Reg_IsAutoRun.i

#W_BUTTON = "BUTTON"
#W_EDIT = "EDIT"
#W_LISTBOX = "LISTBOX"
#W_STATIC = "STATIC"

Global sSystemTime.SYSTEMTIME


PrivateDimBoolean(xCanSpectrum)
  
PublicDimBoolean(PlayerIsLocked)
;PrivateDimLong(PLFontCur.i
;PrivateDimLong(FontChooseDHWnd.i
PublicDimBoolean(GlobalXInitRun)

;PublicDimLong(xLastSearchExResultsSpace.i
#lWidth = 4 ;+ 4
Global *DynButtonsResXDefBMP
Global DynButtonsResXDefLen
Global *DynButtonsResXRepBMP
Global DynButtonsResXRepLen
Global *xTimerIconBMP
Global xTimerIconLen.i
PublicDimBoolean(xCmdSaveSet)
#xAnySkipperMin = 3
#xAnySkipperMax = 60
#xAnySkipperMinN = -#xAnySkipperMin
#xAnySkipperMaxN = -#xAnySkipperMax
#IntroMdSkipperMinVal = 20
#IntroMdSkipperMaxVal = 99
#IntroModeTimeDef = 30
PublicDimBoolean(IntroModeActive)
PublicDimLong(IntroModeTime)
;PrivateDimLong(GrabErrorVar)
PrivateDimLong(ShowIR_IconHWnd1)
PrivateDimLong(ShowIR_IconHWnd2)
PrivateDimLong(ShowIR_IconHWnd)
PrivateDimLong(ShowIR_Width)










PrivateDimLong(FormatIconBack)

PublicDimLong(MaxDeviceCount)
PrivateDimLong(ePic1ScaleBonus)

PrivateDimSingle(xGlobalDialogUnits)
PrivateDimSingle(xGlobalDialogUnitsPLSm)
;PrivateDimSingle(xGlobalDialogUnitsPL)
PublicDimSingle(xGlobalDialogUnitsGFix)

PublicDimBoolean(xSearchAutoClose)
PublicDimBoolean(xSearchAutoPlay)
PublicDimBoolean(xRadioAutoClose)

Global OLEDropMemory.i

Global xMWinPos.RECT

















#AutoIgnoreWaitTime = 10
#LongFadingTotalTimeStrt = 8000
#LongFadingTotalTimeStrtF = 4000
#LongFadingTotalTimeQuit = 4000
#LongFadingTotalTimeShut = 6500


#CalaymBackupSchemeREGName = ".CalaymBackup"
PublicDimLong(xCmdQuitMode)
PublicDimBoolean(xShellMode)
Global PlayerPriority.i
Global SoundSchemePointerMode.i
Global *SoundSchemePointer


Global xNoVerWarnDLL.s


Global StartUpWindowMode.i



Global xSupportedFiles.s
Global xSupportedFilesS.s
Global xSupportedFilesM.s

Global xUsedTypes.s
PublicDimBoolean(xUsedTypesResort)


Global CDDAUse.i
Global CDDAJitter.i
Global ShowFullPath.i
Global ShowFullTitle.i
PrivateDimBoolean(xHasNextSong)
PrivateDimBoolean(SilentPlNext)


PublicDimBoolean(KioskDown)


#GUIInterval = 1000
#GUIMinWaitInterval = 100
PrivateDimLong(xCalaymClassAlign)

PublicDimBoolean(AbortReading)
PrivateDimLong(LEDState)
PublicDimLong(LEDMode)
PublicDimLong(xAutoIgnoreTime)
PublicDimBoolean(xNoSpektrumOnStartup)
Global xRealBaseFile.s

Global xLastDir.s

Global m3uList.s
Global TimerDir.s
Global xLastDirectory.s
Global PresetFile.s
Global UnloadLayerOnDialog.i

PublicDimLong(xRep)
PublicDimBoolean(xGenFading)
PublicDimLong(xProcessMode)
PublicDimBoolean(xRemoveMissingSongs)
PublicDimBoolean(xRemovePlayedSongs)
PublicDimBoolean(xRemoveSkippedSongs)
PrivateDimBoolean(xFollowCurSong)
PublicDimBoolean(MP3GetID3Tag)
PublicDimBoolean(xShowSpectrum)
;compilerif #PresetBinded = 2
;  PrivateDimBoolean(PSetManVisible)
;  compilerendif

Global RandomPosOnTrackerSkipper.i

PublicDimLong(AskSndReset)
PublicDimLong(AskSndResetButton)
#xAutoRefreshTimeMinAll = 10
#xAutoRefreshTimeMaxAll = 180
#xAutoRefreshTimeMin = 2
#xAutoRefreshTimeMax = 30
PrivateDimLong(LastDoneTimer)
#vPLXMax = 64
Global Dim vPLX.s(#vPLXMax * 3 - 1)
Global Dim xTimerPLMenu.i(2)
Global Dim xTimerPLMenuLoaded.i(2)
Global vPLXMain.s
Global xSorting.i
PrivateDimBoolean(xTimer2)
#xTimerEvMax = 256
Global Dim xTimerEv.s(#xTimerEvMax)
Global Dim xTimerEvTime.i(#xTimerEvMax)
PublicDimLong(xTimerEvCount)
PublicDimLong(xTimerEvIR)
Global xTimerEvMode.i
PublicDimLong(xTimerEvUpdateTimer)


#xTimerEvMaxSubEvents = 24
#xTimerEvMaxSubEventsX = #xTimerEvMaxSubEvents - 1
#TimerSepp = "|"

Global CheckAccurate.i
Global IgnoreUnderscored.i
Global RemoveMissingOnPLLoad.i

Global xShowElapsed.i
Global xTitlesWhenMinimized.i
Global xTitlesPos.i
PublicDimBoolean(vKioskMode)
Global UsePLSettings.i


PrivateDimLong(FLineColorX)
PrivateDimLong(FLineColorWDCTxt)

#SpectrumProcInterval = 100 ;100

Global Dim xMaxVU.i(32)
Global Dim xMaxVUWait.i(32)
#xMaxVUWaitInit = 1200 / #SpectrumProcInterval

PrivateDimBoolean(xHiddenAutoDoing)
Global xOutputSSLID.s
Global xDelMode.i
PublicDimBoolean(xSecureMode)
Global xAutoPlayback.i
PublicDimBoolean(xReAutoPlay)

Global Dim xTrackerSkipper.i(3)
Global xTrayIconEnabled.i
Global xTrayIconVisible.i
Global xTrayIconLeft.i
Global xTrayIconRight.i
PrivateDimBoolean(xInfoQuit)
Global xDeluxeSpectrum.i
;PrivateDimBoolean(AutoRefreshVisible)
PrivateDimLong(AutoRefreshApplyHWnd)
;PrivateDimBoolean(SetupVisible)
;PrivateDimBoolean(xfrmSearchExVisible)
Global CPListText.s
PublicDimBoolean(CPListMustDo)
PublicDimLong(CPListTime)
#CPListDelay = 1100
Global PlDClickAction.i
Global MP3GetFormat.i

CompilerIf #PB_Compiler_Unicode
  Global MapVirtualKeyA_H14.i
  Global MapVirtualKeyA_H90.i
  Global MapVirtualKeyA_H91.i
  CompilerEndIf
Global IsInSpectrumxTimer1.i
Global FinalTimersDisabled.i
#ctSSLayer_SpectrumArrayCountX = #ctSSLayer_SpectrumArrayCount - 1
Global Dim SpectrumProcKB_vByteA1.b(255)
Global Dim SpectrumProcKB_xSingleA1.f(32)
#FileFilterVBNullChar = "|"
#UsedTypesVBNullChar = "|" ; purebasic like ...

#HowToDeferWindowPos = 0 ; No real improvements either!
CompilerIf #HowToDeferWindowPos = 3
  PrivateDimLong(TrDeferWindowPos_Coll As Collection
  Structure TrDeferWindowPos_Type
    hWnd.i
    hWndInsertAfter.i
    x.i
    y.i
    cx.i
    cy.i
    wFlags.i
    EndStructure
  #TrDeferWindowPos_TypeLen = 28
  PrivateDimLong(TrDeferWindowPos_LastParent)
  CompilerElseIf #HowToDeferWindowPos = 2
  PrivateDimLong(TrDeferWindowPos_Handle)
  CompilerElseIf #HowToDeferWindowPos = 3
  PrivateDimBoolean(TrDeferWindowPos_Active)
  CompilerElse
  CompilerEndIf

Procedure MessageHandler()
  Define.i xLong1
  Define.MSG xMsg
  
  IsMessageing = #True
  xLong1 = GetMessage_(xMsg, 0, 0, 0)
  While xLong1
    If xLong1 = -1
      ; handle the error and possibly exit
      ElseIf CurrentFindHWnd = 0
      ;If Not TranslateAccelerator(hwnd, haccel, xMsg)
        TranslateMessage_(xMsg)
        DispatchMessage_(xMsg)
      ;  endif
      ElseIf IsDialogMessage_(CurrentFindHWnd, xMsg) = 0
      ;If Not TranslateAccelerator(hwnd, haccel, xMsg)
        TranslateMessage_(xMsg)
        DispatchMessage_(xMsg)
      ;  endif
      EndIf
    CompilerIf #PB_Compiler_Unicode And #XPDeviceRemoveDetect And #XPDeviceRemoveDetectPST
      If PendingDeviceRegB
        If IsTickTimeElapsedMS(PendingDeviceRegT, 2500)
          RemovableDevices_UnregisterAll()
          RemovableDevices_RegisterAll(MainHWnd)
          EndIf
        PendingDeviceRegB = #False
        EndIf
      CompilerEndIf
    xLong1 = GetMessage_(xMsg, 0, 0, 0)
    Wend
  IsMessageing = #False
  EndProcedure

Procedure DialogTimerProc(hWnd.i, Msg.i, idEvent.i, xLong1.i)
  Define.s xChar1

  DoAnimateReadDir(1)
  If Not (AskSndReset = 0 Or xAutoIgnoreTime = -1)
    xLong1 = GetElapsedTickTimeMS(xAutoIgnoreTime) / 1000
    If xLong1 < #AutoIgnoreWaitTime
      xChar1 = ReplaceString(LoadResString(2075), "$", Str(#AutoIgnoreWaitTime - xLong1))
      SetWindowText_(AskSndReset, @xChar1)
      Else
      If AskSndResetButton
        SendMessage_(AskSndResetButton, $F5, 0, 0)
        EndIf
        ;frmStartup.cmdRes_Click 2090
      EndIf
    EndIf
  EndProcedure

Procedure DialogTimer(Init.i)
  If Init
    IsDialoging + 1
    If IsDialoging = 1
      SetTimer_(MainHWnd, 2, #DoEventsEx_SleepPeriodical_Interval, @DialogTimerProc())
      EndIf
    Else
    IsDialoging - 1
    If Not IsDialoging
      KillTimer_(MainHWnd, 2)
      EndIf
    EndIf
  EndProcedure

Procedure.i CalaymMessageBox(hWndOwner.i, Prompt.s, Title.s, Buttons.i)
  Define.i xResult
  DialogTimer(#True)
  xResult = MessageBox_(hWndOwner, Prompt, Title, Buttons)
  DialogTimer(#False)
  ProcedureReturn xResult
  EndProcedure

Procedure ShellDrvInitialize()
  Define.i xLong1

  ShellDrvInited = #True
CompilerIf Not #PB_Compiler_Processor = #PB_Processor_x64
  If IsMinWindows982000
CompilerEndIf
    xLong1 = LoadLibrary_("imageres.dll")
    If Not xLong1 = 0
      ShellDrvIcons(0) = LoadImage_(xLong1, 30, 1, 16, 16, 0)
      ShellDrvIcons(1) = LoadImage_(xLong1, 32, 1, 16, 16, 0)
      ShellDrvIcons(2) = LoadImage_(xLong1, 35, 1, 16, 16, 0)
      FreeLibrary_(xLong1)
      EndIf
    xLong1 = GetModuleHandle_("shell32.dll")
    If xLong1
      If ShellDrvIcons(0) = 0
        ShellDrvIcons(0) = LoadImage_(xLong1, 12, 1, 16, 16, 0)
        EndIf
      If ShellDrvIcons(1) = 0
        ShellDrvIcons(1) = LoadImage_(xLong1, 9, 1, 16, 16, 0)
        EndIf
      If ShellDrvIcons(2) = 0
        ShellDrvIcons(2) = LoadImage_(xLong1, 8, 1, 16, 16, 0)
        EndIf
      EndIf
CompilerIf Not #PB_Compiler_Processor = #PB_Processor_x64
    EndIf
CompilerEndIf
  EndProcedure

Procedure GetMyWindowPos(xChar1.s, FirstValue.i) ; byref byref?
  Define.i xLong1
  
  If Not Right(xChar1, 3) = ",-1"
    For xLong1 = 0 To 3
      Select xLong1
        Case 0: xMWinPos\left   = FirstValue
        Case 1: xMWinPos\top    = FirstValue
        Case 2: xMWinPos\right  = FirstValue
        Case 3: xMWinPos\bottom = FirstValue
        EndSelect
      FirstValue = FindString(xChar1, ",")
      If Not FirstValue
        Break
        EndIf
      xChar1 = Mid(xChar1, FirstValue + 1)
      FirstValue = Val(xChar1)
      Next
    EndIf
  EndProcedure

Procedure GetValidSkipper(MusType.i, xLong1.i)
  If xLong1 < #xAnySkipperMaxN
    xLong1 = #xAnySkipperMaxN
    ElseIf xLong1 > #xAnySkipperMax
    xLong1 = #xAnySkipperMax
    ElseIf xLong1 < #xAnySkipperMinN Or xLong1 > #xAnySkipperMin
    ;xLong1 = xLong1
    ElseIf xLong1 < 0
    xLong1 = #xAnySkipperMinN ; -xAnySkipperMinN!
    Else
    xLong1 = #xAnySkipperMin ;>=0
    EndIf
  xTrackerSkipper(MusType) = xLong1
  EndProcedure

Procedure.s GetDeviceName(DeviceID.i)
  Define.s xResult
  Define.i xLong1

  xResult = ctSSLayer_GetDeviceName(DeviceID, @xLong1)
  If Not Len(xResult)
    xResult = ReplaceString(LoadResString(3200), "$", Str(xLong1 & $FF) + 1)
    EndIf
  xRealBaseFile = ReplaceString(LoadResString(3201 + ((xLong1 & $FF00) >> 8)), "$", xRealBaseFile)
  ProcedureReturn xResult
  EndProcedure

Procedure SetKeyXP(KeyID.i, KeyMap.i)
  Define.i xLong1
  
  xLong1 = GetKeyState_(KeyID)
  If Not xLong1 = SpectrumProcKB_vByteA1(KeyID)
    keybd_event_(KeyID, KeyMap, 0, 0)
    keybd_event_(KeyID, KeyMap, $2, 0)
    EndIf
  EndProcedure

;compilerif #LockWinUpd = 2 Or AnimateReadDir
Procedure DoEventsEx_SleepPeriodicalLW(hWndLocked.i)
  Static xLong1.i

  If IsTickTimeElapsedMS(xLong1, #DoEventsEx_SleepPeriodical_Interval)
;      compilerif #LockWinUpd = 2
    If hWndLocked
      LockWindowUpdate_(0)
      EndIf
    DoEventsEx_Sleep(25)
    If Not xHiddenAutoDoing
      DoAnimateReadDir(1)
      EndIf
;      compilerif #LockWinUpd = 2
    If hWndLocked
      LockWindowUpdate_(hWndLocked)
      EndIf
    xLong1 = (GetTickCount_() & TickTimeMSAndMask())
    EndIf
  EndProcedure
;  compilerendif

Procedure CheckApiMenu(MenuID.i, Checked.i)
  Define.i xLong1
  
  If Checked
    Checked = 8
    EndIf
  For xLong1 = 0 To #xMenuCountX
    CheckMenuItem_(xMenu(xLong1), 1000 + MenuID, Checked)
    CheckMenuItem_(xMenu(xLong1), 2000 + MenuID, Checked)
    Next
  EndProcedure

Procedure RadioApiMenu(MenuIDFirst.i, MenuIDLast.i, MenuIDChecked.i)
  Define.i xLong1
  For xLong1 = 0 To #xMenuCountX
    CheckMenuRadioItem_(xMenu(xLong1), 1000 + MenuIDFirst, 1000 + MenuIDLast, 1000 + MenuIDChecked, 0)
    CheckMenuRadioItem_(xMenu(xLong1), 2000 + MenuIDFirst, 2000 + MenuIDLast, 2000 + MenuIDChecked, 0)
    Next
  EndProcedure

Procedure.s CheckDlls(xChar1.s)
  Define.s xResult
  Define.i xLong1
  Define.s xChar2
  
  xChar1 = LCase(ReplaceString(xChar1, ",", ";")) + ";"
  Repeat
    xLong1 = FindString(xChar1, ";")
    If Not xLong1
      Break
      EndIf
    xChar2 = Trim(Left(xChar1, xLong1 - 1))
    xChar1 = Mid(xChar1, xLong1 + 1)
    If Len(xChar2)
      xLong1 = LoadLibrary_(xChar2)
      If xLong1
        FreeLibrary_(xLong1)
        Else
        xResult = xResult + ", " + xChar2
        EndIf
      EndIf
    ForEver
  ProcedureReturn Mid(xResult, 3)
  EndProcedure

;boolean
Procedure.i LoadResEx_Dialog_CheckBool(DialogHWnd.i, ControlID.i, *Value, ReadFromDialog.i);, Optional Depency1ControlID.i, Optional Depency1ControlID.i) as boolean
  Define.i xResult
  If ReadFromDialog
    If GetDlgItem_(DialogHWnd, ControlID)
      xResult = IsDlgButtonChecked_(DialogHWnd, ControlID)
      If xResult XOr PeekI(*Value)
        If xResult
          xResult = #True
          EndIf
        PokeI(*Value, xResult)
        xResult = #True
        Else
        xResult = #False
        EndIf
      EndIf
    Else
    If PeekI(*Value)
      ReadFromDialog = #BST_CHECKED
      EndIf
    CheckDlgButton_(DialogHWnd, ControlID, ReadFromDialog)
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure UpdateSnds(HWndDialog.i, ControlID.i)
  Define.s xChar1

  ControlID = GetDlgItem_(HWndDialog, ControlID)
  If ControlID
    SendMessage_(ControlID, #CB_RESETCONTENT, 0, 0)
    For HWndDialog = 0 To MaxDeviceCount - 1
      xChar1 = GetDeviceName(HWndDialog)
      SendMessage_(ControlID, $143, 0, @xChar1)
      Next
    HWndDialog = ctSSLayer_GetDeviceFromSSLID(@xOutputSSLID)
    If Not HWndDialog = -1
      If MaxDeviceCount > 1
        EnableWindow_(ControlID, #True)
        Else
        EnableWindow_(ControlID, #False)
        EndIf
      SendMessage_(ControlID, #CB_SETCURSEL, HWndDialog, 0)
      EndIf
    SendMessage_(ControlID, $155, 1, 0)
    EndIf
  EndProcedure

Procedure.i FetchSSLIDFromComboBoxAndCheckItHasChanged(HWndDialog.i, ControlID.i)
  Define.i xResult
  Define.s xChar1

  ControlID = GetDlgItem_(HWndDialog, ControlID)
  If ControlID
    ControlID = SendMessage_(ControlID, $147, 0, 0)
    If Not ControlID = -1
      xChar1 = ctSSLayer_GetDeviceSSLID(ControlID)
      If Not xChar1 = xOutputSSLID
        xOutputSSLID = xChar1
        xResult = #True
        EndIf
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure checkVerBox(HWndDialog.i)
  Define.i xLong1
  LoadResEx_Dialog_CheckBool(HWndDialog, 2260, @xLong1, #True)
  If xLong1
    xNoVerWarnDLL = LCase(ctSSLayer_GetInfoString(4))
    EndIf
  EndProcedure

Procedure.i GenericMessageHandler(HWndDialog.i, Msg.i, ControlID.i, ControlHWnd.i)
  Define.i xResult
  Define.s xChar1

  If Msg = $110
    If (xSecureMode Or vKioskMode)
      LoadResEx_Dialog_Enable(HWndDialog, 2095, #False)
      Else
      CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
        LoadResEx_Dialog_Enable(HWndDialog, 2095, IsFileExists(xRealBaseFile + "chm"))
        CompilerElse
        If xUseChmHelp
          LoadResEx_Dialog_Enable(HWndDialog, 2095, IsFileExists(xRealBaseFile + "chm"))
          Else
          LoadResEx_Dialog_Enable(HWndDialog, 2095, IsFileExists(xRealBaseFile + "hlp"))
          EndIf
        CompilerEndIf
      EndIf
    If (GenericMessageHandler_Param > 2099 And GenericMessageHandler_Param < 2299) Or GenericMessageHandler_Param = 2090 Or GenericMessageHandler_Param = 2070 Or GenericMessageHandler_Param = 2071
      Msg = ctSSLayer_CanUseItem($20)
      If Msg > -1 And Msg < 90
        If Msg < 10 Or Msg > 19
          Msg = 9
          EndIf
        SetDlgItemText_(HWndDialog, 2080, ReplaceString(SSRestrictions, "$I", ReplaceString(LoadResString(2100 + Msg), "$S", ctSSLayer_GetInfoString(5))))
        EndIf
      SetDlgItemText_(HWndDialog, 2040, ReplaceString(GetDlgItemText(HWndDialog, 2040), "$", LayerHP))
      EndIf
    Select GenericMessageHandler_Param
      Case 2070, 2071
        xChar1 = LoadResString(GenericMessageHandler_Param)
        SetDlgItemText_(HWndDialog, 2000, @xChar1)
        GenericMessageHandler_Param = 2090
        AskSndResetButton = GetDlgItem_(HWndDialog, 2090)
        AskSndReset = GetDlgItem_(HWndDialog, 2099)
      Case 2050 To 2052
        xChar1 = ReplaceString(LoadResString(GenericMessageHandler_Param), "$", SimpleFile(xRealBaseFile + "lay"))
        SetDlgItemText_(HWndDialog, 2000, @xChar1)
      Case 2100, 2130 To 2132
        xChar1 = ReplaceString(LoadResString(GenericMessageHandler_Param), "$", ctSSLayer_GetInfoString(2))
        SetDlgItemText_(HWndDialog, 2000, @xChar1)
      Case 2101
        If Not GlobalXInitRun
          LoadResEx_Dialog_Enable(HWndDialog, 2091, #False)
          EndIf
        ctSSLayer_RefreshDeviceList(MainHWnd)
        ControlHWnd = ctSSLayer_GetDeviceFromSSLID(@xOutputSSLID)
        If ControlHWnd = -1
          ControlHWnd = 0
          EndIf
        xChar1 = GetDeviceName(ControlHWnd)
        SetDlgItemText_(HWndDialog, 2040, @xChar1)
        xChar1 = ReplaceString(LoadResString(GenericMessageHandler_Param), "$", ctSSLayer_GetInfoString(2))
        SetDlgItemText_(HWndDialog, 2000, @xChar1)
      Case 2130 To 2132
        xChar1 = ReplaceString(LoadResString(GenericMessageHandler_Param), "$", ctSSLayer_GetInfoString(2))
        SetDlgItemText_(HWndDialog, 2000, @xChar1)
      Case 2190
        xChar1 = CheckDlls(ctSSLayer_GetInfoString($31))
;Debug GenericMessageHandler_Param
;Debug xChar1
        SetDlgItemText_(HWndDialog, 2030, @xChar1)
      Case 2102
        If LCase(ctSSLayer_GetInfoString(4)) = xNoVerWarnDLL
          LoadResEx_Dialog_Enable(HWndDialog, 2260, #False)
          CheckDlgButton_(HWndDialog, 2260, #BST_CHECKED)
          ;chkres(2260).Value = 1
          ElseIf ctSSLayer_CanUseItem($20) = 0 Or Not xCmdSaveSet
          LoadResEx_Dialog_Enable(HWndDialog, 2260, #False)
          EndIf
      EndSelect
    
    If Not UrlsAllowed
      ControlHWnd = GetDlgItem_(HWndDialog, 2050) ; Visit me
      If ControlHWnd
        EnableWindow_(ControlHWnd, 0)
        EndIf
      ControlHWnd = GetDlgItem_(HWndDialog, 2051) ; Visit ms (for dx)
      If ControlHWnd
        EnableWindow_(ControlHWnd, 0)
        EndIf
      ControlHWnd = GetDlgItem_(HWndDialog, 2060) ; Visit sound system
      If ControlHWnd
        EnableWindow_(ControlHWnd, 0)
        EndIf
      EndIf
    If GenericMessageHandler_Param = 2090 Or GenericMessageHandler_Param = 2101
      MaxDeviceCount = ctSSLayer_RefreshDeviceList(MainHWnd)
      UpdateSnds(HWndDialog, 2040)
      If HWndSetupDialogSSPage
        UpdateSnds(HWndSetupDialogSSPage, 3200)
        EndIf
      If ctSSLayer_CanUseItem($E) = 0
        LoadResEx_Dialog_Enable(HWndDialog, 2041, #False)
        EndIf
      DialogTimer(#True)
      EndIf
    If UnloadLayerOnDialog
      ctSSLayer_UnLoadVB()
      UnloadLayerOnDialog = #False
      EndIf
    ElseIf Msg = $12
    If GenericMessageHandler_Param = 2090 Or GenericMessageHandler_Param = 2101
      DialogTimer(#False)
      FetchSSLIDFromComboBoxAndCheckItHasChanged(HWndDialog, 2040)
      MaxDeviceCount = ctSSLayer_RefreshDeviceList(MainHWnd)
      If HWndSetupDialogSSPage
        UpdateSnds(HWndSetupDialogSSPage, 3200)
        EndIf
      If GenericMessageHandler_Param = 2090
        If IsDlgButtonChecked_(HWndDialog, 2045)
          xNoSpektrumOnStartup = #True
          CheckAccurate = #False
          xDeluxeSpectrum = #False
          If LockWinUpd = 0
            LockWinUpd = 1
            EndIf
          EndIf
        EndIf
      ElseIf GenericMessageHandler_Param = 2102
      checkVerBox(HWndDialog)
      EndIf
    
    
    
    
    ElseIf Msg = $111
    Select (ControlID & $FFFF)
      Case 2050 ; Visit me
        If UrlsAllowed
          ShellExecute_(HWndDialog, @"Open", @"http://www.ctuser.net", 0, 0, 5)
          EndIf
      Case 2041
        MaxDeviceCount = ctSSLayer_RefreshDeviceList(MainHWnd)
        UpdateSnds(HWndDialog, 2040)
        If Not HWndSetupDialogSSPage = 0
          UpdateSnds(HWndSetupDialogSSPage, 3200)
          EndIf
      Case 2051 ; Visit ms (for dx)
        If UrlsAllowed
          xChar1 = LoadResString(2120)
          ShellExecute_(HWndDialog, @"Open", @xChar1, 0, 0, 5)
          EndIf
      Case 2060 ; Visit sound system
        If UrlsAllowed
          ShellExecute_(HWndDialog, @"Open", @LayerHP, 0, 0, 5)
          EndIf
      Case 2095 ; Help!
        If Not (xSecureMode Or vKioskMode)
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
            HtmlHelp(MainHWnd, xRealBaseFile + "chm", 0, @"soundsystem.htm")
            CompilerElse
            If xUseChmHelp
              HtmlHelp(MainHWnd, xRealBaseFile + "chm", 0, @"soundsystem.htm")
              Else
              WinHelp(MainHWnd, xRealBaseFile + "hlp", $101, @"Soundsystem")
              EndIf
            CompilerEndIf
          EndIf
      Default
        xResult = 1
      EndSelect
    If GenericMessageHandler_Param = 2090
      If ControlID = 2045 Or ((ControlID & $FFFF) = 2040 And (ControlID & $FFFF0000) = $10000)
        If Not xAutoIgnoreTime = -1
          xAutoIgnoreTime = -1
          If AskSndReset
            SetWindowText_(AskSndReset, @"")
            EndIf
          EndIf
        EndIf
      If HWndSetupDialogSSPage
        FetchSSLIDFromComboBoxAndCheckItHasChanged(HWndDialog, 2040)
        MaxDeviceCount = ctSSLayer_RefreshDeviceList(MainHWnd)
        UpdateSnds(HWndSetupDialogSSPage, 3200)
        EndIf
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.s GetUsedFileFilters()
  Define.s xResult

  xResult = ReplaceString(LoadResString(1201), "$", ReplaceString(Mid(xUsedTypes, 2, Len(xUsedTypes) - 2), #UsedTypesVBNullChar, "/")) + "|"
  xResult + "*." + ReplaceString(Mid(xUsedTypes, 2, Len(xUsedTypes) - 2), #UsedTypesVBNullChar, ";*.") + "|"
  xResult + ReplaceString(LoadResString(1202), "$", ReplaceString(Mid(xSupportedFiles, 2, Len(xSupportedFiles) - 2), #UsedTypesVBNullChar, "/")) + "|"
  xResult + "*." + ReplaceString(Mid(xSupportedFiles, 2, Len(xSupportedFiles) - 2), #UsedTypesVBNullChar, ";*."); + "|"
  ;xResult + #UsedTypesVBNullChar
  ProcedureReturn xResult
  EndProcedure

Procedure.s MainForm_ResortTypes(TypesString.s)
  Dim xCharA1.s(99)
  Define.i xLong1
  Define.i xLong2
  
  TypesString = Mid(TypesString, 2)
  Repeat
    xLong2 = FindString(TypesString, #UsedTypesVBNullChar)
    If xLong2 = 0 Or xLong1 = 100
      Break
      Else
      xCharA1(xLong1) = Left(TypesString, xLong2 - 1)
      xLong1 + 1
      TypesString = Mid(TypesString, xLong2 + 1)
      EndIf
    ForEver
;  ArraySort_String_IC(xCharA1(), xLong1)
  SortArray(xCharA1(), #PB_Sort_Ascending | #PB_Sort_NoCase, 0, xLong1 - 1)
  TypesString = ""
  For xLong2 = 0 To xLong1 - 1
    TypesString = TypesString + #UsedTypesVBNullChar + xCharA1(xLong2)
    Next
  ProcedureReturn TypesString + #UsedTypesVBNullChar
  EndProcedure

Procedure.s PrettyFileTypes()
  If xUsedTypesResort
    xUsedTypes = MainForm_ResortTypes(xUsedTypes)
    xUsedTypesResort = #False
    EndIf
  ProcedureReturn ReplaceString(Mid(xUsedTypes, 2, Len(xUsedTypes) - 2), #UsedTypesVBNullChar, ",")
  EndProcedure

Procedure CheckFileTypes()
  Define.s xChar1
  Define.s xChar2
  Define.i xLong1
  
  xUsedTypes = ReplaceString(xUsedTypes, ",", #UsedTypesVBNullChar) + #UsedTypesVBNullChar
  Repeat
    xLong1 = FindString(xUsedTypes, #UsedTypesVBNullChar)
    If xLong1 = 0
      Break
      EndIf
    xChar2 = LCase(Left(xUsedTypes, xLong1 - 1))
    If FindString(xSupportedFiles, #UsedTypesVBNullChar + xChar2 + #UsedTypesVBNullChar)
      xChar1 = xChar1 + #UsedTypesVBNullChar + xChar2
      EndIf
    xUsedTypes = Mid(xUsedTypes, xLong1 + 1)
    ForEver
  If xChar1 = ""
    xUsedTypes = #UsedTypesVBNullChar + ReplaceString(ReplaceString(ctSSLayer_GetInfoString($19), ";", #UsedTypesVBNullChar), ",", #UsedTypesVBNullChar)
    Else
    xUsedTypes = xChar1 + #UsedTypesVBNullChar
    EndIf
  xUsedTypesResort = #True
  EndProcedure

Procedure.i AllowedItemSongFast(ShortFilename.s, IgnoreNotEnabled.i)
  Define.i xResult

  ShortFilename = GetExtensionPart(ShortFilename)
  If FindString(xSupportedFiles, #UsedTypesVBNullChar + ShortFilename + #UsedTypesVBNullChar)
    If IgnoreNotEnabled
      xResult = #True
      ElseIf FindString(xUsedTypes, #UsedTypesVBNullChar + ShortFilename + #UsedTypesVBNullChar)
      xResult = #True
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_SaveSettings(WriteFailSave.i, xSpectrum.i)
  Define.i xLong1
  Define.i hFile
  ;GetMyWindowEx

  hFile = TxtFileWriter_CreateFile(AppBase_GetByExt("ini"))
  If hFile
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Saving settings")
      CompilerEndIf
    TxtFileWriter_WriteLine(hFile, "AllowFileDeleting=" + BoolChar1(xDelMode))
    TxtFileWriter_WriteLine(hFile, "AutoPlay=" + BoolChar1(xAutoPlayback))
    TxtFileWriter_WriteLine(hFile, "AutoPauseOnUserSwitch=" + BoolChar1(OutOfSessionPause))
    TxtFileWriter_WriteLine(hFile, "AutoSwitchIRadioView=" + BoolChar1(xAutoSwitchIRadioOEPl))
    TxtFileWriter_WriteLine(hFile, "BlockIDEWhileLoading=" + BoolChar1(xClassicBlockingOnLoad))
    TxtFileWriter_WriteLine(hFile, "CDDA=" + BoolChar1(CDDAUse))
    TxtFileWriter_WriteLine(hFile, "CDDAJitterCorrection=" + BoolChar1(CDDAJitter))
    TxtFileWriter_WriteLine(hFile, "CheckAccurateStreams=" + BoolChar1(CheckAccurate))
    TxtFileWriter_WriteLine(hFile, "CheckSongsOnPlaylistLoad=" + BoolChar1(RemoveMissingOnPLLoad))
    TxtFileWriter_WriteLine(hFile, "CrossfadeTime=" + Str(xCrossFadeTimeM + #xFadeConsts1))
    TxtFileWriter_WriteLine(hFile, "DirectoryListAlignment=" + Str(xDirListModeSet))
    TxtFileWriter_WriteLine(hFile, "DirectoryListLeftWidth=" + Str(xDirListLeftWidth))
    TxtFileWriter_WriteLine(hFile, "DirectoryListTopHeight=" + Str(xDirListTopHeight))
    TxtFileWriter_WriteLine(hFile, "DisableWindowsSounds=" + Str(SoundSchemePointerMode))
    TxtFileWriter_WriteLine(hFile, "ElapsedTime=" + BoolChar1(xShowElapsed))
    TxtFileWriter_WriteLine(hFile, "EndSongMode=" + Str(xProcessMode))
    TxtFileWriter_WriteLine(hFile, "EndStreams=" + StrS(xTrackerSkipper(#ctSSLayer_MusicTypeStream)))
    TxtFileWriter_WriteLine(hFile, "EndTrackers=" + StrS(xTrackerSkipper(#ctSSLayer_MusicTypeTracker)))
    TxtFileWriter_WriteLine(hFile, "EndCDAudio=" + StrS(xTrackerSkipper(#ctSSLayer_MusicTypeCDAudio)))
    TxtFileWriter_WriteLine(hFile, "Fading=" + BoolChar1(xGenFading))
    TxtFileWriter_WriteLine(hFile, "FailSave=" + Str(WriteFailSave))
    TxtFileWriter_WriteLine(hFile, "FollowSong=" + BoolChar1(xFollowCurSong))
    TxtFileWriter_WriteLine(hFile, "GetFileInfos=" + BoolChar1(MP3GetID3Tag))
    TxtFileWriter_WriteLine(hFile, "GetFileFormat=" + BoolChar1(MP3GetFormat))
    TxtFileWriter_WriteLine(hFile, "GlobalPlayKeys=" + BoolChar1(GlobalKeys))
    TxtFileWriter_WriteLine(hFile, "IgnoreUnderscored=" + BoolChar1(IgnoreUnderscored))
    If IntroModeActive
      TxtFileWriter_WriteLine(hFile, "IntroMode=" + Str(IntroModeTime))
      Else
      TxtFileWriter_WriteLine(hFile, "IntroMode=" + StrS(-IntroModeTime))
      EndIf
    WriteKeyboardSetup(hFile)
    TxtFileWriter_WriteLine(hFile, "NoVerWarn=" + xNoVerWarnDLL)
    TxtFileWriter_WriteLine(hFile, "OutputDevice=" + xOutputSSLID)
    TxtFileWriter_WriteLine(hFile, "PlayerWindowPos=" + StrS(xMWinPos\left) + "," + StrS(xMWinPos\Top) + "," + StrS(xMWinPos\Right) + "," + StrS(xMWinPos\Bottom))
    TxtFileWriter_WriteLine(hFile, "PlayerWindowState=" + Str(StartUpWindowMode))
    TxtFileWriter_WriteLine(hFile, "PlaylistDoubleClick=" + Str(PlDClickAction))
    TxtFileWriter_WriteLine(hFile, "PlaylistUpdateInterval=" + Str(LockWinUpd))
    TxtFileWriter_WriteLine(hFile, "Priority=" + Str(PlayerPriority))
    TxtFileWriter_WriteLine(hFile, "RadioAutoClose=" + BoolChar1(xRadioAutoClose))
CompilerIf #UseIRPlugins
    TxtFileWriter_WriteLine(hFile, "RadioWindowPos=" + StrS(xMWinPosx(xMWindowID_IRadio)\left) + "," + StrS(xMWinPosx(xMWindowID_IRadio)\Top) + "," + StrS(xMWinPosx(xMWindowID_IRadio)\Right) + "," + StrS(xMWinPosx(xMWindowID_IRadio)\Bottom))
CompilerEndIf
    TxtFileWriter_WriteLine(hFile, "RandomSeek=" + BoolChar1(RandomPosOnTrackerSkipper))
    xLong1 = 0
    If RegFolderMode(0)
      xLong1 | 1
      EndIf
    If RegFolderMode(1)
      xLong1 | 2
      EndIf
    If RegFolderMode(2)
      xLong1 | 4
      EndIf
    If RegFolderMode(3)
      xLong1 | 8
      EndIf
    TxtFileWriter_WriteLine(hFile, "RegisterFolders=" + Str(xLong1))
    TxtFileWriter_WriteLine(hFile, "RemoveMissingSongs=" + BoolChar1(xRemoveMissingSongs))
    TxtFileWriter_WriteLine(hFile, "RemovePlayedSongs=" + BoolChar1(xRemovePlayedSongs))
    TxtFileWriter_WriteLine(hFile, "RemoveSkippedSongs=" + BoolChar1(xRemoveSkippedSongs))
    TxtFileWriter_WriteLine(hFile, "RepeatMode=" + Str(xRep))
    TxtFileWriter_WriteLine(hFile, "SearchAutoClose=" + BoolChar1(xSearchAutoClose))
    TxtFileWriter_WriteLine(hFile, "SearchAutoPlay=" + BoolChar1(xSearchAutoPlay))
    TxtFileWriter_WriteLine(hFile, "ShowFullPath=" + BoolChar1(ShowFullPath))
    TxtFileWriter_WriteLine(hFile, "ShowFullTitle=" + BoolChar1(ShowFullTitle))
    TxtFileWriter_WriteLine(hFile, "Sorting=" + BoolChar1(xSorting))
    If xShowSpectrum Or xSpectrum
      xLong1 = 1
      Else
      xLong1 = 0
      EndIf
    If xDeluxeSpectrum
      xLong1 = xLong1 | 2
      EndIf
    TxtFileWriter_WriteLine(hFile, "Spectrum=" + Str(xLong1))
    TxtFileWriter_WriteLine(hFile, "TitlesPosition=" + Str(xTitlesPos))
    TxtFileWriter_WriteLine(hFile, "TitlesWhenMinimized=" + Str(xTitlesWhenMinimized))
    TxtFileWriter_WriteLine(hFile, "TrackerPanSeperation=" + Str(xModPanning))
    TxtFileWriter_WriteLine(hFile, "TrayIcon=" + BoolChar1(xTrayIconVisible))
    TxtFileWriter_WriteLine(hFile, "TrayLeftClick=" + Str(xTrayIconLeft))
    TxtFileWriter_WriteLine(hFile, "TrayMinimize=" + BoolChar1(xTrayIconEnabled))
    TxtFileWriter_WriteLine(hFile, "TrayRightClick=" + Str(xTrayIconRight))
    TxtFileWriter_WriteLine(hFile, "UsedFileTypes=" + PrettyFileTypes())
    TxtFileWriter_WriteLine(hFile, "UsePlaylistSettings=" + BoolChar1(UsePLSettings))
    TxtFileWriter_WriteLine(hFile, "Volume=" + Str(xSetVolume))
    TxtFileWriter_Close(hFile)
CompilerIf #UseFileLogging
    Else
    MainForm_ctConsoleA_AddLog("Error saving configuration")
CompilerEndIf
    EndIf
  EndProcedure

Procedure UpdateFolderReg(DoSet.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.s xChar1

  For xLong2 = 0 To 1
    If RegFolderMode(xLong2)
      If DoSet
        xChar1 = "Folder\Shell\" + LoadResString(3534 + xLong2 * 5) + "\command"
        If RegCreateKeyEx_($80000000, @xChar1, 0, 0, 0, 2, 0, @xLong1, *ptrTemp)
          If xLong2 = 1
            xChar1 = " /ENQUEUE "
            Else
            xChar1 = " "
            EndIf
          xChar1 = Chr(34) + xRealBaseFile + "exe" + Chr(34) + xChar1 + Chr(34) + "%1" + Chr(34)
          RegSetValueEx_String(xLong1, 0, xChar1)

          RegCloseKey_(xLong1)
          xChar1 = "Folder\Shell\" + LoadResString(3534 + xLong2 * 5)
          If RegOpenKeyEx_($80000000, @xChar1, 0, 2, @xLong1)
            xChar1 = LoadResString(3533 + xLong2 * 5)
            RegSetValueEx_String(xLong1, 0, xChar1)
            RegCloseKey_(xLong1)
            EndIf
          EndIf
        Else
        xChar1 = "Folder\Shell\" + LoadResString(3534 + xLong2 * 5) + "\command"
        RegDeleteKey_($80000000, @xChar1)
        xChar1 = "Folder\Shell\" + LoadResString(3534 + xLong2 * 5)
        RegDeleteKey_($80000000, @xChar1)
        EndIf
      EndIf
    Next
  
  If RegFolderMode(2)
; playlistformatsimport
    If DoSet
      RegisterFileTypes_SetRegistered("m3u", LoadResString(3525), LoadResString(3527), LoadResString(3526), ReplaceString(LoadResString(3528), "$", "M3U"), "", -1, RegFolderMode(3), #True, LoadResString(3529))
      CompilerIf #PB_Compiler_Unicode
        RegisterFileTypes_SetRegistered("m3u8", LoadResString(3525), LoadResString(3527), LoadResString(3526), ReplaceString(LoadResString(3528), "$", "M3U8"), "", -1, RegFolderMode(3), #True, LoadResString(3529))
        RegisterFileTypes_SetRegistered("aimppl", LoadResString(3525), LoadResString(3527), LoadResString(3526), ReplaceString(LoadResString(3528), "$", "WPL"), "", -1, RegFolderMode(3), #True, LoadResString(3529))
        RegisterFileTypes_SetRegistered("plc", LoadResString(3525), LoadResString(3527), LoadResString(3526), ReplaceString(LoadResString(3528), "$", "WPL"), "", -1, RegFolderMode(3), #True, LoadResString(3529))
        RegisterFileTypes_SetRegistered("wpl", LoadResString(3525), LoadResString(3527), LoadResString(3526), ReplaceString(LoadResString(3528), "$", "WPL"), "", -1, RegFolderMode(3), #True, LoadResString(3529))
        CompilerEndIf
      RegisterFileTypes_SetRegistered("pls", LoadResString(3525), LoadResString(3527), LoadResString(3526), ReplaceString(LoadResString(3528), "$", "PLS"), "", -1, RegFolderMode(3), #True, LoadResString(3529))
      RegisterFileTypes_SetRegistered("aap", LoadResString(3525), LoadResString(3527), LoadResString(3526), ReplaceString(LoadResString(3528), "$", "AAP"), "", -1, RegFolderMode(3), #True, LoadResString(3529))
      RegisterFileTypes_SetRegistered("xspf", LoadResString(3525), LoadResString(3527), LoadResString(3526), ReplaceString(LoadResString(3528), "$", "XSPF"), "", -1, RegFolderMode(3), #True, LoadResString(3529))
      Else
      RegisterFileTypes_RemoveRegistered("m3u", LoadResString(3527), LoadResString(3529))
      RegisterFileTypes_RemoveRegistered("m3u8", LoadResString(3527), LoadResString(3529))
      RegisterFileTypes_RemoveRegistered("pls", LoadResString(3527), LoadResString(3529))
      RegisterFileTypes_RemoveRegistered("aimppl", LoadResString(3527), LoadResString(3529))
      RegisterFileTypes_RemoveRegistered("plc", LoadResString(3527), LoadResString(3529))
      RegisterFileTypes_RemoveRegistered("aap", LoadResString(3527), LoadResString(3529))
      RegisterFileTypes_RemoveRegistered("xspf", LoadResString(3527), LoadResString(3529))
      RegisterFileTypes_RemoveRegistered("wpl", LoadResString(3527), LoadResString(3529))
      EndIf
    EndIf
  EndProcedure

Procedure SetFormatToolTip(xChar1.s, xChar2.s)
  FormatToolTip1 = xChar1
  FormatToolTip2 = xChar2
  SetToolTip(#xStaticIcons_CurSong, ReplaceString(CurSongToolTip1, "$M", FormatToolTip1), CurSongToolTip2 + FormatToolTip2)
  EndProcedure

Procedure MainForm_EnableApiMenu(MenuID.i, IsEnabled.i)
  Define.i xLong1
  
  If IsEnabled
    IsEnabled = 0
    Else
    IsEnabled = 3
    EndIf
  For xLong1 = 0 To #xMenuCountX
    EnableMenuItem_(xMenu(xLong1), 1000 + MenuID, IsEnabled)
    EnableMenuItem_(xMenu(xLong1), 2000 + MenuID, IsEnabled)
    Next
  EndProcedure

Procedure ClearOldSongInfo()
  curTagText = ""
  SetWindowText_(xStaticIconsHWnd(#xStaticIcons_Tags), "")
  SetFormatToolTip(LoadResString(1900), "")
  MainForm_EraseBackground(xStaticIconsHWnd(#xStaticIcons_CurSongPos))
  MainForm_EnableApiMenu(408, #False)
  EndProcedure

Procedure.i SpectrumProc(xLong1.i, xLong3.i, xLong4.i, xLong5.i)
  Dim xSingleA1.f(#ctSSLayer_SpectrumArrayCountX)
  Define.f xSingle1
  Define.f xSingle2
  Define.i xLong6
  Define.i xLong7
  Define.i hPen
  Define.i hPenOld
  Define.i hBmp
  Define.i hBmpOld
  Define.RECT xType1
  Define.i hdc
  
  If Not (IsInSpectrumxTimer1 Or FinalTimersDisabled)
    IsInSpectrumxTimer1 = #True
    hdc = GetDC_(xStaticIconsHWnd(#xStaticIcons_Spectrum))
    If Not hdc = 0
      If CurMusic = #ctSSLayer_MusicTypeNone
        ctSSLayer_GetSpectrum(@xSingleA1(0), #ctSSLayer_SpectrumArrayCount, 0, 0)
        Else
        ctSSLayer_GetSpectrum(@xSingleA1(0), #ctSSLayer_SpectrumArrayCount, SongPointer(CurrentSongID), 0)
        EndIf
      For xLong1 = 0 To #ctSSLayer_SpectrumArrayCountX
        xSingleA1(xLong1) = xSingleA1(xLong1) / (1 / (xLong1 + 1)) ;* 1.5  ;* 0.4
        If xSingleA1(xLong1) > 1
          xSingleA1(xLong1) = 1
          EndIf
        Next
      
      
      
      hBmp = CreateCompatibleBitmapX(128, 22)
      If Not hBmp = 0
        hBmpOld = SelectObject_(xSharedDC, hBmp)
        CompilerIf Not #NoClearSpectrum
          xType1\Bottom = 21
          xType1\Right = 128
          FillRect_(xSharedDC, xType1, #FillSysColorBack)
          CompilerEndIf
        hPen = CreatePen_(0, 0, FLineColor)
        If Not hPen = 0
          hPenOld = SelectObject_(xSharedDC, hPen)
          If xDeluxeSpectrum
            xLong3 = GetTickCount_() & $FFF
            xSingle1 = Cos(xLong3 * 3.1415926536 / $1000)
            xSingle2 = Sin(xLong3 * 3.1415926536 / $1000)
            MoveToEx_(xSharedDC, 16, 10, 0)
            LineTo_(xSharedDC, 112, 10)
            MoveToEx_(xSharedDC, 13 - xSingle1 * 10, 10 - xSingle2 * 10, 0)
            LineTo_(xSharedDC, 13 + xSingle1 * 10, 10 + xSingle2 * 10)
            LineTo_(xSharedDC, 114 + xSingle1 * 10, 10 + xSingle2 * 10)
            LineTo_(xSharedDC, 114 - xSingle1 * 10, 10 - xSingle2 * 10)
            LineTo_(xSharedDC, 13 - xSingle1 * 10, 10 - xSingle2 * 10)
            For xLong1 = 0 To #ctSSLayer_SpectrumArrayCountX
              xLong5 = xSingle1 * xSingleA1(xLong1) * 8
              xLong4 = 16 + xLong1 * 3 - xLong5
              xLong5 = 16 + xLong1 * 3 + xLong5
              xLong7 = xSingle2 * xSingleA1(xLong1) * 8
              xLong6 = 10 - xLong7
              xLong7 = 10 + xLong7
              MoveToEx_(xSharedDC, xLong4, xLong6, 0)
              LineTo_(xSharedDC, xLong5, xLong7)
              MoveToEx_(xSharedDC, xLong4 + 1, xLong6, 0)
              LineTo_(xSharedDC, xLong5 + 1, xLong7)
              MoveToEx_(xSharedDC, xLong4 + 2, xLong6, 0)
              LineTo_(xSharedDC, xLong5 + 2, xLong7)
              Next
            Else
            For xLong1 = 0 To #ctSSLayer_SpectrumArrayCountX
              xSingleA1(xLong1) = Int(xSingleA1(xLong1) * 21)
              If xSingleA1(xLong1) >= xMaxVU(xLong1)
                xMaxVU(xLong1) = xSingleA1(xLong1)
                xMaxVUWait(xLong1) = #xMaxVUWaitInit
                ElseIf Not xMaxVU(xLong1) = 0
                If xMaxVUWait(xLong1) = 0
                  xMaxVU(xLong1) = xMaxVU(xLong1) - 1
                  Else
                  xMaxVUWait(xLong1) = xMaxVUWait(xLong1) - 1
                  EndIf
                EndIf
              
              xType1\left = xLong1 * 4
              xType1\Top = 21 - xSingleA1(xLong1)
              xType1\Right = xLong1 * 4 + 4
              xType1\Bottom = 21
              FillRect_(xSharedDC, xType1, #FillSysColorFore)
              MoveToEx_(xSharedDC, xLong1 * 4, 21 - xMaxVU(xLong1), 0)
              LineTo_(xSharedDC, xLong1 * 4 + 4, 21 - xMaxVU(xLong1))
              Next
            EndIf
          SelectObject_(xSharedDC, hPenOld)
          DeleteObject_(hPen)
          EndIf
        BitBlt_(hdc, 0, 0, 128, 21, xSharedDC, 0, 0, #SRCCOPY)
        SelectObject_(xSharedDC, hBmpOld)
        DeleteObject_(hBmp)
        EndIf
      ReleaseDC_(xStaticIconsHWnd(#xStaticIcons_Spectrum), hdc)
      EndIf
    IsInSpectrumxTimer1 = #False
    EndIf
  ProcedureReturn 0
  EndProcedure

Procedure.f ValHighSgn(Value1.f, Value2.f)
  Define.f xResult
  If Value1 > Value2
    xResult = Value1
    Else
    xResult = Value2
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure SpectrumProcKb(hWnd.i, uMsg.i, idEvent.i, xLong1.i)
  Static xByte1.b
  Static xBool1.i
  ;Static xOldLEDState.i
  ;Dim xTimer1 As Boolean
  
  ;If Not xTimer1
    ;xTimer1 = #True
    xByte1 = 1 - xByte1
    Select LEDState
      Case 0
        If xShowSpectrum
          If CurMusic = #ctSSLayer_MusicTypeNone
            If xBool1
              For xLong1 = 0 To 32
                SpectrumProcKB_xSingleA1(xLong1) = 0
                Next
              xBool1 = #False
              EndIf
            Else
            ctSSLayer_GetSpectrum(@SpectrumProcKB_xSingleA1(0), #ctSSLayer_SpectrumArrayCount, SongPointer(CurrentSongID), 0)
            xBool1 = #True
            EndIf
          
          
          
          
          ; Multiplicating higher frequencies to show a usefull spectrum for choral songs
          ; and songs that have no bass
          xLong1 = Int( ValHighSgn ( ValHighSgn ( ValHighSgn(SpectrumProcKB_xSingleA1(2) * 1.5, SpectrumProcKB_xSingleA1(4) * 1.5) , ValHighSgn(SpectrumProcKB_xSingleA1(7) * 1.25, SpectrumProcKB_xSingleA1(11))), ValHighSgn(ValHighSgn(SpectrumProcKB_xSingleA1(15) * 1.5, SpectrumProcKB_xSingleA1(19) * 2), ValHighSgn(SpectrumProcKB_xSingleA1(23) * 2.5, SpectrumProcKB_xSingleA1(27) * 3))) * 4)          ;3 is real!
          Select xLong1
            Case 0
              SpectrumProcKB_vByteA1($90) = 0
              SpectrumProcKB_vByteA1($14) = 0
              SpectrumProcKB_vByteA1($91) = 0
            Case 1
              SpectrumProcKB_vByteA1($90) = 1
              SpectrumProcKB_vByteA1($14) = 0
              SpectrumProcKB_vByteA1($91) = 0
            Case 2
              SpectrumProcKB_vByteA1($90) = 1
              SpectrumProcKB_vByteA1($14) = 1
              SpectrumProcKB_vByteA1($91) = 0
            Default ;3
              SpectrumProcKB_vByteA1($90) = 1
              SpectrumProcKB_vByteA1($14) = 1
              SpectrumProcKB_vByteA1($91) = 1
            EndSelect
          EndIf
      Case 1 ; nothing / playing
        SpectrumProcKB_vByteA1($90) = 0
        SpectrumProcKB_vByteA1($14) = 0
        SpectrumProcKB_vByteA1($91) = 0
      Case 2
        SpectrumProcKB_vByteA1($90) = 1
        SpectrumProcKB_vByteA1($14) = 1
        SpectrumProcKB_vByteA1($91) = 1
      Case 3
        SpectrumProcKB_vByteA1($90) = xByte1
        SpectrumProcKB_vByteA1($14) = xByte1
        SpectrumProcKB_vByteA1($91) = xByte1
      Default
        SpectrumProcKB_vByteA1($90) = 0
        xLong1 = (LEDState & $F0) / $10
        If xLong1 = 2
          SpectrumProcKB_vByteA1($14) = xByte1
          Else
          SpectrumProcKB_vByteA1($14) = xLong1
          EndIf
        xLong1 = (LEDState & $FF00) / $100
        If xLong1 = 2
          SpectrumProcKB_vByteA1($91) = xByte1
          Else
          SpectrumProcKB_vByteA1($91) = xLong1
          EndIf
      EndSelect
    If LEDMode
      CompilerIf #PB_Compiler_Unicode
        SetKeyXP($14, MapVirtualKeyA_H14) ;MapVirtualKeyA($14, 0))
        SetKeyXP($90, MapVirtualKeyA_H90) ;MapVirtualKeyA($14, 0))
        SetKeyXP($91, MapVirtualKeyA_H91) ;MapVirtualKeyA($14, 0))
        CompilerElse
        SetKeyboardState_(@SpectrumProcKB_vByteA1(0))
        CompilerEndIf
      EndIf
    ;xTimer1 = #False
    ;EndIf
  ProcedureReturn 0
  EndProcedure

Procedure UnTheme()
  If hThemeComboDropButtons
    CloseThemeData(hThemeComboDropButtons)
    hThemeComboDropButtons = 0
    EndIf
  EndProcedure

Procedure DoThemeUpdates()
  UnTheme()
  If IsThemeActive()
    If IsAppThemed()
      hThemeComboDropButtons = OpenThemeData(MainHWnd, @"SCROLLBAR")
      EndIf
    EndIf
  EndProcedure

CompilerIf #HowToDeferWindowPos
  Procedure TrDeferWindowPos(hWnd.i, hWndInsertAfter.i, x.i, y.i, cx.i, cy.i, wFlags.i)
    CompilerIf #HowToDeferWindowPos = 1
      Dim xType1 As TrDeferWindowPos_Type
      Define.i xLong1
      Define.i xLong2
      ;define.i xLong3
     ;Const SWP_SHOWWINDOW = $40
      ;Const SWP_HIDEWINDOW = $80
      ; SWP_NOSENDCHANGING 400
      If Not GetParent(hWnd) = MainHWnd
        If IsWindowVisible_(hWnd)
          ShowWindow_(hWnd, 0)
          EndIf
        ProcedureReturn
        EndIf
    ;Stop
      If Not (wFlags & $4C0)
        xLong1 = LocalAlloc(0, TrDeferWindowPos_TypeLen)
        EndIf
      If xLong1 = 0
        TrEndDeferWindowPos
        SetWindowPos_(hWnd, hWndInsertAfter, x, y, cx, cy, wFlags)
        Else
        If Not xLong2 = TrDeferWindowPos_LastParent
          If Not TrDeferWindowPos_Coll.Count = 0
            TrEndDeferWindowPos
            EndIf
          xLong2 = TrDeferWindowPos_LastParent
          EndIf
        With xType1
          .hWnd = hWnd
          .hWndInsertAfter = hWndInsertAfter
          .x = x
          .y = y
          .cx = cx
          .cy = cy
          .wFlags = wFlags
          End With
        RtlMoveMemory(xLong1, xType1, TrDeferWindowPos_TypeLen)
        TrDeferWindowPos_Coll.Add xLong1
        EndIf
      CompilerElseIf HowToDeferWindowPos = 2
      Define.i xLong1
      
      If Not GetParent(hWnd) = MainHWnd
        If IsWindowVisible_(hWnd)
          ShowWindow_(hWnd, 0)
          EndIf
        ProcedureReturn
        EndIf
      If TrDeferWindowPos_Handle = 0
        TrDeferWindowPos_Handle = BeginDeferWindowPos(99)
        EndIf
      If Not TrDeferWindowPos_Handle = 0
        TrDeferWindowPos_Handle = DeferWindowPos(TrDeferWindowPos_Handle, hWnd, hWndInsertAfter, x, y, cx, cy, wFlags | $8)
        EndIf
      CompilerElseIf HowToDeferWindowPos = 3
      TrDeferWindowPos_Active = #True
      SetWindowPos_(hWnd, hWndInsertAfter, x, y, cx, cy, wFlags | $8)
      CompilerElse
      SetWindowPos_(hWnd, hWndInsertAfter, x, y, cx, cy, wFlags)
      CompilerEndIf
    EndProcedure
  
  Procedure TrEndDeferWindowPos()
    CompilerIf #HowToDeferWindowPos = 1
      Define.i xLong1
      Define.i xLong2
      Define.i xLong3
      Dim xType1 As TrDeferWindowPos_Type
    ;Stop
      xLong1 = TrDeferWindowPos_Coll.Count
      If Not xLong1 = 0
        xLong2 = BeginDeferWindowPos(xLong1)
        If Not xLong2 = 0
          For xLong1 = 1 To TrDeferWindowPos_Coll.Count
            xLong3 = TrDeferWindowPos_Coll(xLong1)
            RtlMoveMemory(xType1, xLong3, TrDeferWindowPos_TypeLen)
            With xType1
    If xLong1 = 1
      Debug.Print .hWnd, .hWndInsertAfter, .x, .y, .cx, .cy, .wFlags
      EndIf
              xLong2 = DeferWindowPos(xLong2, .hWnd, .hWndInsertAfter, .x, .y, .cx, .cy, .wFlags)
              End With
            If xLong2 = 0 
              Exit For
              EndIf
            Next
          EndIf
        If Not xLong2 = 0
    ;Debug "NewDone"
    ;Stop
          xLong2 = EndDeferWindowPos(xLong2)
          EndIf
        If xLong2 = 0
    ;Debug "OldDone"
          For xLong1 = 1 To TrDeferWindowPos_Coll.Count
            xLong3 = TrDeferWindowPos_Coll(xLong1)
            RtlMoveMemory(xType1, xLong3, TrDeferWindowPos_TypeLen)
            With xType1
              xLong2 = SetWindowPos_(.hWnd, .hWndInsertAfter, .x, .y, .cx, .cy, .wFlags)
              End With
            Next
          EndIf
        EndIf
      ;Debug "  Cleanup"
      For xLong1 = TrDeferWindowPos_Coll.Count To 1 Step -1
        xLong3 = TrDeferWindowPos_Coll(xLong1)
        LocalFree_(xLong3)
        TrDeferWindowPos_Coll.Remove xLong1
        Next
      CompilerElseIf HowToDeferWindowPos = 2
      EndDeferWindowPos(TrDeferWindowPos_Handle)
      TrDeferWindowPos_Handle = 0
      CompilerEndIf
    EndProcedure
  CompilerElse
  Macro TrDeferWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, wFlags)
    SetWindowPos_(hWnd, hWndInsertAfter, x, y, cx, cy, wFlags)
    EndMacro
  CompilerEndIf

Procedure DrawWhiteDC(hWnd.i, HWndDownCtrl.i, ID.i, xEraseBackgrnd.i)
  Define.i xLong1
  Define.i xLong2
  Define.RECT xType1
  Define.RECT xType2
  
  If GetClientRect_(hWnd, xType1)
    xLong1 = GetDC_(hWnd)
    If xLong1
      xType2\Bottom = xType1\Bottom
      xLong2 = SelectObject_(xLong1, hFontGFix)
      SetBkColor_(xLong1, FLineColorX) ; FLineColorX)
      SetTextColor_(xLong1, FLineColorWDCTxt)
      xType2\Right = xType1\Right - ScrollComboWidth
      If xEraseBackgrnd
        FillRect_(xLong1, xType2, #FillSysColorBack)
        EndIf
      If ID = 0
        If Not CurMusic = #ctSSLayer_MusicTypeNone
          xType2\Right = xType2\Right - PLCurSongDisplaySpacePos
          xType2\left = PLCurSongDisplaySpacePos
          xType2\Bottom = xType2\Bottom
          DrawText_(xLong1, @PLCurSongDisplaySpaceStr, Len(PLCurSongDisplaySpaceStr), @xType2, $8924)
          If MP3GetFormat And MP3FormatBitmap
            xLong2 = SelectObject_(xSharedDC, MP3FormatBitmap)
            If xLong2
              BitBlt_(xLong1, 4, xDefIconTopShift16, 16, 16, xSharedDC, 0, 0, #SRCCOPY)
              SelectObject_(xSharedDC, xLong2)
              EndIf
            EndIf
          EndIf
        ElseIf ID = 1 And Len(DirLblCaption)
        ;debug "RePrintDir: " + DirLblCaption
        If PLIconFolder = 0
          DrawText_(xLong1, @DirLblCaption, Len(DirLblCaption), xType2, $4924) ;$8924 + $4000 * CLng(ShowFullPath))
          Else
          DrawIconEx_(xLong1, 4, xDefIconTopShift16, PLIconFolder, 16, 16, 0, 0, 3)
          ;xType2\Right = xType2\Right - 20
          xType2\left = 20
          DrawText_(xLong1, @DirLblCaption, Len(DirLblCaption), xType2, $4924) ;$8924 + $4000 * CLng(ShowFullPath))
          EndIf
        EndIf
;        SetBkColor_(xSharedDC, FLineColorX)
      SelectObject_(xLong1, xLong2)
  
      xType1\left = xType1\Right - ScrollComboWidth ;3
      If hThemeComboDropButtons = 0
        If IsWindowVisible_(HWndDownCtrl)
          DrawFrameControl_(xLong1, @xType1, 3, $200 + ID) ;(ID & $1))
          Else
          DrawFrameControl_(xLong1, @xType1, 3, ID) ;(ID & $1))
          EndIf
        Else
        If IsWindowVisible_(HWndDownCtrl)
          xLong2 = 2
          Else
          xLong2 = 0
          EndIf
        xLong2 = ID * 4 + 1 + xLong2
        If IsThemeBackgroundPartiallyTransparent(hThemeComboDropButtons, 1, xLong2)
          DrawThemeParentBackground(hWnd, xLong1, xType1)
          EndIf
        DrawThemeBackground(hThemeComboDropButtons, xLong1, 1, xLong2, xType1, 0)
        EndIf
      ReleaseDC_(hWnd, xLong1)
      EndIf
    EndIf
  EndProcedure

Procedure MP3GetFormatChanged(ReDraw.i)
  If MP3GetFormat
    PLCurSongDisplaySpacePos = PLCurSongDisplaySpacePosOrg + 20
    Else
    PLCurSongDisplaySpacePos = PLCurSongDisplaySpacePosOrg
    EndIf
  If ReDraw
    DrawWhiteDC(xStaticIconsHWnd(#xStaticIcons_CurSong), xListHWnd(1), 0, #True)
    EndIf
  EndProcedure

Procedure MainForm_RedrawPosition()
  Define.i xLong1
  Define.i hDC
  Define.RECT xType1
  
  If GetClientRect_(xStaticIconsHWnd(#xStaticIcons_CurSongPos), @xType1)
    hDC = GetDC_(xStaticIconsHWnd(#xStaticIcons_CurSongPos))
    If hDC
      If Not (CurMusic = #ctSSLayer_MusicTypeNone Or PLCurSongLength = 0)
        xLong1 = xType1\Right
        xType1\Right = MulDiv_(PLCurSongPos, xLong1 - ePic1ScaleBonus, PLCurSongLength)
        FillRect_(hDC, @xType1, 14)
        xType1\left = xType1\Right
        xType1\Right = xLong1
        EndIf
      FillRect_(hDC, @xType1, 6)
      ReleaseDC_(xStaticIconsHWnd(#xStaticIcons_CurSongPos), hDC)
      EndIf
    EndIf
  EndProcedure

Procedure DrawWhiteDCWizButton(xID.i) ;, IsDisabled As Boolean)
  Define.i hdc
  Define.i hWnd
  Define.i hFontOld
  Define.RECT xType1
  
  hWnd = Interface_Control(#Interface_Control_Wizard_ButtonFirst + xID)
  If GetClientRect_(hWnd, @xType1)
    hdc = GetDC_(hWnd)
    If hdc
      hFontOld = SelectObject_(hdc, hFontIntroWiz)
      
      If hWnd = WizardSelHWnd
        If PlayerIsLocked
          FillRect_(hdc, xType1, 16)
          SetBkColor_(hdc, FormatIconBack)
          SetTextColor_(hdc, SysColor20)
          Else
          FillRect_(hdc, xType1, 14)
          SetBkColor_(hdc, FLineColor)
          SetTextColor_(hdc, SysColor14)
          EndIf
        Else
        FillRect_(hdc, xType1, 6)
        SetBkColor_(hdc, FLineColorX)
        If PlayerIsLocked
          SetTextColor_(hdc, SysColor17)
          Else
          SetTextColor_(hdc, FLineColorWDCTxt)
          EndIf
        EndIf
      DrawFocusRect_(hdc, @xType1)

      If (xType1\Right - xType1\left) > 100 And IntroWizIconHas
        If Not IntroWizIcon(xID) = 0
          DrawIconEx_(hdc, xType1\left + 8, (xStaticIcons_IntroWizCtlHeight - 32) / 2, IntroWizIcon(xID), 32, 32, 0, 0, 3)
          EndIf
        xType1\left = xType1\left + 48
        Else
        xType1\left = xType1\left + 8
        EndIf
      
      If hWnd = WizardSelHWnd And PlayerIsLocked
        xType1\left = xType1\left + 1
        xType1\Top = xType1\Top + 1
        EndIf
      xType1\Right = xType1\Right - 8
      
      DrawText_(hdc, @IntroWizText(xID), Len(IntroWizText(xID)), xType1, $8924)
      If hWnd = WizardSelHWnd And PlayerIsLocked
        SetTextColor_(hdc, SysColor17)
        SetBkMode_(hdc, 1)
        xType1\left = xType1\left - 1
        xType1\Top = xType1\Top - 1
        xType1\Right = xType1\Right - 1 ; to enforce same clipping (same width)!
        DrawText_(hdc, @IntroWizText(xID), Len(IntroWizText(xID)), xType1, $8924)
        EndIf
      If Not hFontOld = 0
        SelectObject_(hdc, hFontOld)
        EndIf
      ReleaseDC_(hWnd, hdc)
      EndIf
    EndIf
  EndProcedure

Procedure DoVolume(VolumeToSet.i, ApplyVolume.i)
  Static xOldVolume.i
  
  If ApplyVolume
    xSetVolume = VolumeToSet
    MainForm_DrawVolFaderA(xSetVolume); 0
    xOldVolume = Int(VolumeToSet / 25.5)
    RadioApiMenu(345, 355, 345 + xOldVolume)
    If Not vKioskMode Or vCanVolume
      If xSetVolume = 255
        MainForm_EnableApiMenu(341, #False)
        Else
        MainForm_EnableApiMenu(341, #True)
        EndIf
      MainForm_EnableApiMenu(342, xSetVolume)
      EndIf
    CompilerIf #UseFileLogging And #DetailLog
      MainForm_ctConsoleA_AddLog("Volume: "+Str(xSetVolume)+" ("+CInt(xSetVolume / 2.55)+"%)")
      CompilerEndIf
    PlayerIsLocked = #False
    EndIf
  If Tear_StepT(CurrentSongID) = 0 And Not CurMusic = #ctSSLayer_MusicTypeNone
    ctSSLayer_SetVolume(SongPointer(CurrentSongID), VolumeToSet)
    EndIf
  SetToolTip(#xStaticIcons_Volume, ReplaceString(ReplaceString(ReplaceString(LoadResString(1150), "$V", Str(MulDiv_(xSetVolume, 100, 255))), "$C", GetKeyNameText(MapVirtualKey_($11, 0) * $10000)), "$S", GetKeyNameText(MapVirtualKey_($10, 0) * $10000)), xVolTTText)
  EndProcedure

Procedure MainForm_ePic_MouseDown(Index.i, x.i)
  Define.i xLong1

  If Not PlayerIsLocked
    Select Index
      Case 100
        If Not (xSongIsMidi = 3 Or PLCurSongLength = 0)
;Debug Hex(x) + "/" + ePic1ScaleBonus + "/" + Str(SongPosScrollWidth) + "/" + Str(PLCurSongLength)
          xLong1 = MulDiv_(x + ePic1ScaleBonus, PLCurSongLength, SongPosScrollWidth)
          If Not (vKioskMode Or PlayerIsLocked Or CurMusic = #ctSSLayer_MusicTypeNone Or xLong1 < 0 Or xLong1 > PLCurSongLength)
            ctSSLayer_SeekSong(SongPointer(CurrentSongID), xLong1)
            If CurMusic = #ctSSLayer_MusicTypeTracker
              ResetPatternLog()
              ;xModCurPattern = -1
              EndIf
            EndIf
          EndIf
      Case 1
        If Not (xSongIsMidi = 3 Or PLCurSongLength = 0)
          xLong1 = MulDiv_(x + ePic1ScaleBonus, PLCurSongLength, SongPosScrollWidth)
          If Not (vKioskMode Or PlayerIsLocked Or CurMusic = #ctSSLayer_MusicTypeNone Or xLong1 < 0 Or xLong1 > PLCurSongLength)
            ctSSLayer_SeekSong(SongPointer(CurrentSongID), xLong1)
            If CurMusic = #ctSSLayer_MusicTypeTracker
              ResetPatternLog()
              EndIf
            EndIf
          EndIf
      Case 2
        If Not (vKioskMode Or PlayerIsLocked)
          DoVolume(MainForm_MeasureAlignVolFaderA(X), #True)
          EndIf
      EndSelect
    EndIf
  EndProcedure

Procedure.s GetCurSong(Shortened.i)
  Define.s xResult
  If CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3
    If Shortened
      xResult = PLCurSongDisplay
      Else
      xResult = PLCurFullURL
      EndIf
    ElseIf Shortened
    xResult = SimpleFile(PLCurSong)
    Else
    xResult = PLCurSong
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.i FastCopy(hWnd.i, wParam.i, lParam.i)
  Define.i xResult
  Define.i xLong1
  Define.s xChar1

  xLong1 = GetAccessSize(lParam)
  CompilerIf #PB_Compiler_Unicode
    wParam = wParam >> 1
    CompilerEndIf
  If wParam = 0
  ;  debug "Handed!"
    MessageBox_(MainHwnd, @"Test message received", @"Calaym / Test", #MB_ICONINFORMATION)
    EndIf
  If wParam > 0 And Not xLong1 < wParam
    Select hWnd
      Case xStaticIconsHWnd(#xStaticIcons_DirList)
        xChar1 = DirLblCaption
      Case xStaticIconsHWnd(#xStaticIcons_CurSong)
        If xPStateIconPlaying And Not (xPStateIconSndcard Or xPStateIconQuit Or CurMusic = #ctSSLayer_MusicTypeNone Or xPStateIconStartup)
          xChar1 = PLCurSongDisplaySpaceStr
          EndIf
      Case xStaticIconsHWnd(#xStaticIcons_ShowIR)
        If xPStateIconPlaying And Not (xPStateIconSndcard Or xPStateIconQuit Or CurMusic = #ctSSLayer_MusicTypeNone Or xPStateIconStartup)
          xChar1 = GetCurSong(#False)
          EndIf
      Default
        ProcedureReturn
      EndSelect
    
    xLong1 = Len(xChar1)
    If wParam > xLong1
      wParam = xLong1
      EndIf
    PokeS(lParam, xChar1, wParam, #PB_Unicode)
    xResult = wParam
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure ExtraSongPos(lParam.i)
  Define.POINT xType1

  If xStaticIconsHWnd(#xStaticIcons_CurSongPos)
    If ClientToScreen_(xStaticIconsHWnd(#xStaticIcons_CurSongPos), @xType1)
      MainForm_ePic_MouseDown(100, SignedLowerWord(lParam) - xType1\x)
      EndIf
    EndIf
  EndProcedure

Procedure.i RedrawProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Define.i xResult
  
  Select Message
    Case $14
      Select hWnd
        Case xStaticIconsHWnd(#xStaticIcons_DirList)
          ProcedureReturn 1
        Case xStaticIconsHWnd(#xStaticIcons_CurSong)
          ProcedureReturn 1
        Case xStaticIconsHWnd(#xStaticIcons_CurSongPos)
          ProcedureReturn 1
        EndSelect
    Case $F ;, $14 ;WM_PAINT = $F
      Select hWnd
        Case xStaticIconsHWnd(#xStaticIcons_DirList)
          DrawWhiteDC(xStaticIconsHWnd(#xStaticIcons_DirList), xListHWnd(0), 1, #True)  ;, DirLblCaption
        Case xStaticIconsHWnd(#xStaticIcons_CurSong)
          DrawWhiteDC(xStaticIconsHWnd(#xStaticIcons_CurSong), xListHWnd(1), 0, #True)
        Case xStaticIconsHWnd(#xStaticIcons_CurSongPos)
          ;If Not (CurMusic = #ctSSLayer_MusicTypeNone Or PLCurSongLength = 0)
            MainForm_RedrawPosition()
          ;  endif
        Case xStaticIconsHWnd(#xStaticIcons_Anim)
          DoAnimateReadDir(0)
        Case xStaticIconsHWnd(#xStaticIcons_Spectrum)
          If xCanSpectrum
            SpectrumProc(0, 0, 0, 0)
            EndIf
        Case xStaticIconsHWnd(#xStaticIcons_ToolTip)
          If ToolTipInitTime = -1 And Not CurShownToolTip = -1
            WriteToolTip()
            EndIf
        Case Interface_Control(#Interface_Control_Wizard_Help)
          DrawWhiteDCWizButton(#Interface_Control_Wizard_Help - #Interface_Control_Wizard_ButtonFirst)
        Case Interface_Control(#Interface_Control_Wizard_AddDir)
          DrawWhiteDCWizButton(#Interface_Control_Wizard_AddDir - #Interface_Control_Wizard_ButtonFirst)
        Case Interface_Control(#Interface_Control_Wizard_AddPList)
          DrawWhiteDCWizButton(#Interface_Control_Wizard_AddPList - #Interface_Control_Wizard_ButtonFirst)
        Case Interface_Control(#Interface_Control_Wizard_AutoRefresh)
          DrawWhiteDCWizButton(#Interface_Control_Wizard_AutoRefresh - #Interface_Control_Wizard_ButtonFirst)
        Case Interface_Control(#Interface_Control_Wizard_IRadio)
          DrawWhiteDCWizButton(#Interface_Control_Wizard_IRadio - #Interface_Control_Wizard_ButtonFirst)
        EndSelect
    Case $202
      xResult = DefWindowProc_(hWnd, Message, wParam, lParam)
        Select hWnd
          Case xStaticIconsHWnd(#xStaticIcons_DirList)
            If InterfaceMode = #Interface_Mode_None
              If xDirListModeCur = 0
                If IsWindowVisible_(xListHWnd(0))
                  ShowWindow_(xListHWnd(0), 0)
                  DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
                  Else
                  ShowWindow_(xListHWnd(0), 5)
                  DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 1)
                  SetFocus_(xListHWnd(0))
                  EndIf
                EndIf
              EndIf
          Case xStaticIconsHWnd(#xStaticIcons_CurSong)
            If IsWindowVisible_(xListHWnd(1))
              ShowWindow_(xListHWnd(1), 0)
              DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
              Else
              ShowWindow_(xListHWnd(1), 5)
              DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 1)
              SetFocus_(xListHWnd(1))
              EndIf
          Case xStaticIconsHWnd(#xStaticIcons_CurSongPos)
            MainForm_ePic_MouseDown(1, SignedLowerWord(lParam))
          EndSelect
;        endif
      ProcedureReturn xResult
    Case $203
      If hWnd = xStaticIconsHWnd(#xStaticIcons_Spectrum) And Not vKioskMode
        
        If xDeluxeSpectrum
          xDeluxeSpectrum = #False
          Else
          xDeluxeSpectrum = #True
          EndIf
        EndIf
      Case $D ; WM_GETTEXT
        ProcedureReturn FastCopy(hWnd, wParam, lParam)
      Case $E ; WM_GETTEXTLENGTH = $E
        ProcedureReturn FastCopy(hWnd, wParam, *ptrTemp)
    Case $A1
      If hWnd = xStaticIconsHWnd(#xStaticIcons_CurSongPos)
        ExtraSongPos(lParam)
        EndIf
    EndSelect
  ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure TextOutVBF(hdc.i, TopPos.i, WidthX.i, strCap.s)
  Define.i hBmp
  Define.i hBmpOld
  Define.i xLong1
  Define.i xLong2
  Define.RECT xType1
  Define.BITMAPINFOHEADER xType2
  
  If WidthX
    hBmp = CreateCompatibleBitmapX(WidthX, xIRBarHeight)
    If hBmp
      SelectObject_(xSharedDC, hFontShIR)
      hBmpOld = SelectObject_(xSharedDC, hBmp)
      If hBmpOld
        xType1\Bottom = xIRBarHeight
        xType1\Right = WidthX
        FillRect_(xSharedDC, xType1, $6)
        TextOut_(xSharedDC, 0, 0, strCap, Len(strCap))
        SelectObject_(xSharedDC, hBmpOld)
        Dim SrcBits.l(WidthX - 1, xIRBarHeight - 1)
        With xType2
          \biBitCount = 32
          \biSize = 40
          \biWidth = WidthX
          \biHeight = -xIRBarHeight
          \biPlanes = 1
          EndWith
        xLong1 = GetDIBits_(xSharedDC, hBmp, 0, xIRBarHeight, @SrcBits(0, 0), @xType2, 0)
        DeleteObject_(hBmp)
        If xLong1
          Dim DesBits.l(xIRBarHeight - 1, WidthX - 1)
          For xLong1 = 0 To WidthX - 1
            For xLong2 = 0 To xIRBarHeight - 1
              DesBits(xLong2, xLong1) = SrcBits(xLong1, xLong2)
              Next
            Next
          hBmp = CreateCompatibleBitmapX(xIRBarHeight, WidthX)
          If Not hBmp = 0
            xType2\biWidth = xIRBarHeight
            xType2\biHeight = WidthX
            If SetDIBits_(xSharedDC, hBmp, 0, WidthX, @DesBits(0, 0), @xType2, 0)
              If SelectObject_(xSharedDC, hBmp)
                BitBlt_(hdc, 0, TopPos, xIRBarHeight, WidthX, xSharedDC, 0, 0, #SRCCOPY)
                SelectObject_(xSharedDC, hBmpOld)
                EndIf
              EndIf
            DeleteObject_(hBmp)
            EndIf
          EndIf
        Else
        DeleteObject_(hBmp)
        EndIf
      SelectObject_(xSharedDC, hFontGFix)
      EndIf
    EndIf
  EndProcedure

Procedure IRDraw()
  Define.i hdc
  Define.i hFontOld
  Define.i xLong2
  Define.i xLong3
  Define.POINT xType1
  Define.i URLChangedHook

  hdc = GetDC_(xStaticIconsHWnd(#xStaticIcons_ShowIR))
  If hdc
    hFontOld = SelectObject_(hdc, hFontShIR)
    If ShowIR_IconHWnd
      xLong2 = 38
      xLong3 = 36
      If xTitlesPos = 1 Or xTitlesPos = 2
        Else
        DrawIconEx_(hdc, 4, (xIRBarHeight - 32) >> 1, ShowIR_IconHWnd, 32, 32, 0, 0, 3)
        EndIf
      EndIf
    
    CompilerIf #LoudestSongMethode
      If Not NeedIRPathElipse = LastLoudestTearFn
        If ShowIR_IconHWnd
          xLong2 = 38
          EndIf
        If ShowFullTitle And Not LastLoudestTearIS
          ShownIRPath = Ellipsis_PathSmartStart(hdc, LastLoudestTearFn, VertIRBarHeight - 6 - xLong2)
          Else
          ShownIRPath = Ellipsis_PathSmartStart(hdc, LastLoudestTearCp, VertIRBarHeight - 6 - xLong2)
          EndIf
        NeedIRPathElipse = LastLoudestTearFn
        EndIf
      CompilerElse
      If CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3
        If Not NeedIRPathElipse = PLCurFullURL
          URLChangedHook = #True
          EndIf
        ElseIf Not NeedIRPathElipse = PLCurSong
        URLChangedHook = #True
        EndIf
      If URLChangedHook
        If ShowIR_IconHWnd
          xLong2 = 38
          EndIf
        If ShowFullTitle And Not (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
          ShownIRPath = Ellipsis_PathSmartStart(hdc, PLCurSong, VertIRBarHeight - 6 - xLong2)
          Else
          ShownIRPath = Ellipsis_PathSmartStart(hdc, PLCurSongDisplay, VertIRBarHeight - 6 - xLong2)
          EndIf
        NeedIRPathElipse = PLCurSong
        EndIf
      CompilerEndIf
    
    If xTitlesPos = 1 Or xTitlesPos = 2
      If ShowIR_IconHWnd
        DrawIconEx_(hdc, (xIRBarHeight - 32) / 2, VertIRBarHeight - 36, ShowIR_IconHWnd, 32, 32, 0, 0, 3)
        EndIf
      If hFontShIRIsVerticalBitmapFont
        GetTextExtentPoint32_(hdc, @ShownIRPath, Len(ShownIRPath), @xType1)
        TextOutVBF(hdc, VertIRBarHeight - 4 - xLong3 - xType1\x, xType1\x, ShownIRPath)
        Else
        TextOut_(hdc, 0, VertIRBarHeight - 4 - xLong3, @ShownIRPath, Len(ShownIRPath))   ;- 40) ; - xType2.x)
        EndIf
      Else
      TextOut_(hdc, 4 + xLong3, 0, @ShownIRPath, Len(ShownIRPath))
      EndIf
    SelectObject_(xSharedDC, hFontOld)
    ReleaseDC_(xStaticIconsHWnd(#xStaticIcons_ShowIR), hdc)
    EndIf
  EndProcedure

Procedure ResizeRemember()
  Define.RECT xType1
  If GetWindowRect_(MainHWnd, @xType1)
    If IsIconic_(MainHWnd) = 0
      If IsZoomed_(MainHWnd) = 0
        xMWinPos\left = xType1\left
        xMWinPos\Top = xType1\Top
        xMWinPos\Right = xType1\Right - xType1\left
        xMWinPos\Bottom = xType1\Bottom - xType1\Top
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure CheckValidScreen(ReRead.i)
  Define.i xLong2
  Define.i xLong3
  Define.RECT xType1
  
  #WindowOverlapBottom = 48 ;128
  #WindowOverlapSide = 96
  
  GetOptMonitorFromPoint(xMWinPos\left + xMWinPos\Right / 2, xMWinPos\Top + xMWinPos\Bottom / 2, xType1)
  xLong2 = xType1\Right - xType1\left
  xLong3 = xType1\Bottom - xType1\Top
  
  If ReRead
    ResizeRemember()
    EndIf
  If xMWinPos\Right > xLong2
    xMWinPos\Right = xLong2
    EndIf
  If xMWinPos\Bottom > xLong3
    xMWinPos\Bottom = xLong3
    EndIf
  
  If xMWinPos\left + xMWinPos\Right < xType1\left + #WindowOverlapSide
    xMWinPos\left = xType1\left + #WindowOverlapSide - xMWinPos\Right
    EndIf
  If xMWinPos\left > xLong2 - #WindowOverlapSide
    xMWinPos\left = xLong2 - #WindowOverlapSide
    EndIf
  If xMWinPos\Top > xLong3 - #WindowOverlapBottom
    xMWinPos\Top = xLong3 - #WindowOverlapBottom
    EndIf
  If xMWinPos\Top < xType1\Top
    xMWinPos\Top = xType1\Top
    EndIf
  SetWindowPos_(MainHWnd, 0, xMWinPos\left, xMWinPos\Top, xMWinPos\Right, xMWinPos\Bottom, $214)
  
  xType1\left = 0
  ClientToScreen_(xStaticIconsHWnd(#xStaticIcons_BAR), @xType1)
  xLong2 = xType1\left
  xType1\left = 0
  ClientToScreen_(xStaticIconsHWnd(#xStaticIcons_CurSongPos), @xType1)
  ePic1ScaleBonus = xType1\left - xLong2
  EndProcedure

Procedure IRPos(Force.i)
  #xBarHeightX2 = 2.5
  #xBarHeightX3 = 4
  #xBarHeightX4 = 5

  Define.i xLong1
  Define.RECT xType1
  Define.RECT xType2

  GetWindowRect_(GetDesktopWindow_(), @xType1)
  GetCursorPos_(@xType2)
  NeedIRPathElipse = ""
  Select xTitlesPos
    Case 0 ;top
      If xType2\Top < xIRBarHeight * #xBarHeightX2
        xLong1 = 1
        EndIf
      VertIRBarHeight = xType1\Right
    Case 1 ;left
      If xType2\left < xIRBarHeight * #xBarHeightX2
        xLong1 = 3
        Else
        xLong1 = 2
        EndIf
      SystemParametersInfo_(#SPI_GETWORKAREA, 0, @xType2, 0)
      VertIRBarHeight = xType2\Bottom - xType2\Top
    Case 2 ;right
      If xType2\left > xType1\Right - xIRBarHeight * #xBarHeightX2
        xLong1 = 5
        Else
        xLong1 = 4
        EndIf
      SystemParametersInfo_(#SPI_GETWORKAREA, 0, @xType2, 0)
      VertIRBarHeight = xType2\Bottom - xType2\Top
    Case 3 ;bottom
      GetWindowRect_(GetDesktopWindow_(), @xType1)
      If xType2\Top > xType1\Bottom - xIRBarHeight * #xBarHeightX2
        xLong1 = 7
        Else
        xLong1 = 6
        EndIf
      VertIRBarHeight = xType1\Right
    EndSelect
  If Force Or Not xLong1 = xCalaymClassAlign
    Select xLong1
      Case 0: SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0, 0, 0, xType1\Right, xIRBarHeight, $214)
      Case 1: SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0, 0, xIRBarHeight * #xBarHeightX3, xType1\Right, xIRBarHeight, $214)
      Case 2: SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0, 0, xType2\Top, xIRBarHeight, VertIRBarHeight, $214)
      Case 3: SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0, xIRBarHeight * #xBarHeightX3, xType2\Top, xIRBarHeight, VertIRBarHeight, $214)
      Case 4: SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0, xType1\Right - xIRBarHeight, xType2\Top, xIRBarHeight, VertIRBarHeight, $214)
      Case 5: SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0, xType1\Right - xIRBarHeight * #xBarHeightX4, xType2\Top, xIRBarHeight, VertIRBarHeight, $214)
      Case 6: SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0, 0, xType1\Bottom - xIRBarHeight, xType1\Right, xIRBarHeight, $214)
      Case 7: SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0, 0, xType1\Bottom - xIRBarHeight * #xBarHeightX4, xType1\Right, xIRBarHeight, $214)
      EndSelect
    xCalaymClassAlign = xLong1
    EndIf
  If ShowIR_IconHWnd
    ShowIR_Width = xType1\Right - 44
    Else
    ShowIR_Width = xType1\Right - 4
    EndIf
  EndProcedure

Procedure MainForm_DesireSpectrumState(Activated.i, ForceLEDMode.i)
  Static xBool1.i
  
  If LEDMode = 0 And (Not vKioskMode Or MP3GetID3Tag)
    If (Not xShowSpectrum Or IsIconic_(MainHWnd) Or xTrayIconIndicator)
      Activated = #False
      EndIf
    If xBool1 XOr Activated
      xBool1 = Activated
      If Activated
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("Starting spectrum analyzer")
          CompilerEndIf
        ctSSLayer_SetSpectrum(#True)
        xCanSpectrum = #True
        SetTimer_(MainHWnd, 0, #SpectrumProcInterval, @SpectrumProc())
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  Spectrum analyzer started")
          CompilerEndIf
        Else
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("Stopping Spectrum analyzer")
          CompilerEndIf
        KillTimer_(MainHWnd, 0)
        xCanSpectrum = #False
        ctSSLayer_SetSpectrum(#False)
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  Spectrum analyzer stopped")
          CompilerEndIf
        EndIf
      EndIf
    ElseIf ForceLEDMode
    ;led mode
    If Not xShowSpectrum
      Activated = #False
      EndIf
    If xBool1 XOr Activated
      xBool1 = Activated
      If Activated
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("Starting LED spectrum analyzer")
          CompilerEndIf
         ;no set/kill timer here! SpectrumProcKb
        ctSSLayer_SetSpectrum(#True)
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  LED Spectrum analyzer started")
          CompilerEndIf
        Else
        CompilerIf #UseFileLogging
           MainForm_ctConsoleA_AddLog("Stopping LED Spectrum analyzer")
           CompilerEndIf
        ctSSLayer_SetSpectrum(#False)
        If LEDState = 0
          LEDState = 1
          SpectrumProcKb(0, 0, 0, 0)
          LEDState = 0
          EndIf
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  LED Spectrum analyzer stopped")
          CompilerEndIf
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_ShowTray(NoVisible.i)
Define.i xLong1
Define.i xLong2

CompilerIf #UseFileLogging
  MainForm_ctConsoleA_AddLog("Performing system tray icon changes")
  CompilerEndIf

If Not xTrayIconOld = -1
  If xTrayIconIndicator And xTrayIconEnabled
    ShowWindow_(MainHWnd, 7)
    ShowWindow_(MainHWnd, 0)
    Else
    xTrayIconIndicator = #False
    ;Me.Visible = #True
    ;ShowWindow_(MainHWnd, 9)
    ShowWindow_(MainHWnd, 5)
    DoEvents()
    EndIf
  If xTrayIconVisible
    xLong1 = 2
    EndIf
  If xTrayIconIndicator
    xLong1 = xLong1 + 1
    EndIf
  If Not xLong1 = xTrayIconOld
    If (xLong1 = 0 Or xLong1 = 2) And (xTrayIconOld = 1 Or xTrayIconOld = 3) And Not NoVisible
      xLong2 = GetLastActivePopup_(MainHWnd)
      If IsIconic_(MainHWnd)
        If xLong2 = 0
          ShowWindow_(MainHWnd, 9)
          SetForegroundWindow_(MainHWnd)
          Else
          ShowWindow_(MainHWnd, 9)
          ShowWindow_(xLong2, 9)
          SetForegroundWindow_(xLong2)
          EndIf
        Else
        If xLong2 = 0
          ShowWindow_(MainHWnd, 5)
          SetForegroundWindow_(MainHWnd)
          Else
          ShowWindow_(MainHWnd, 5)
          ShowWindow_(xLong2, 5)
          SetForegroundWindow_(xLong2)
          EndIf
        EndIf
      MainForm_DesireSpectrumState(#True, #False)
      EndIf
    If xTrayIconOld = 0
      Shell_NotifyIcon(0, @SysTrayIcon)
      CompilerIf #TrayIconViaTimerCheck
        xTrayIconCrashUpdateTimer = GetTickTimeMS()
        CompilerEndIf
      EndIf
    If xLong1 = 0
      Shell_NotifyIcon(2, @SysTrayIcon)
      CompilerIf #TrayIconViaTimerCheck
        xTrayIconCrashUpdateTimer = 0
        CompilerEndIf
      EndIf
    xTrayIconOld = xLong1
    EndIf
  EndIf
EndProcedure

Procedure.i xFindSong(SongNameA.s = "")
  Define.i xResult
  Define.i xLong1
  Define.i xLong2

  If SongNameA = ""
    SongNameA = PLCurSong
    EndIf
  SongNameA = UCase(SongNameA)
  If Not PLCurItem < PLCount
    PLCurItem = 0
    EndIf
CompilerIf #BoldDirs = 98
  If UCase(PLI(PLCurItem)\Filename) = SongNameA And (PLI(PLCurItem)\DirDepthFlags & #PLI_IsDir) = 0
CompilerElse
  If UCase(PLIFile(PLCurItem)) = SongNameA And (PLIDF(PLCurItem) & #PLI_IsDir) = 0
CompilerEndIf
    xResult = PLCurItem
    ElseIf PLCount
    xLong2 = Len(SongNameA)
    For xLong1 = 0 To PLCount - 1
CompilerIf #BoldDirs = 98
      If Len(PLI(xLong1)\Filename) = xLong2
        If UCase(PLI(xLong1)\Filename) = SongNameA
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = 0
CompilerElse
      If Len(PLIFile(xLong1)) = xLong2
        If UCase(PLIFile(xLong1)) = SongNameA
          If (PLIDF(xLong1) & #PLI_IsDir) = 0
CompilerEndIf
            xResult = xLong1
            Break
            EndIf
          EndIf
        EndIf
      Next
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_SetDirCaption(xChar1.s)
  DirLblCaption = xChar1
  If InterfaceMode = #Interface_Mode_None
    DrawWhiteDC(xStaticIconsHWnd(#xStaticIcons_DirList), xListHWnd(0), 1, 1)
    EndIf
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("DirCap: " + DirLblCaption)
    CompilerEndIf
  EndProcedure

Procedure MainForm_CheckDir(Force.i, DontMarkPath.i = #False)
  Static xLong1.i
  Static xLong2.i
  Define.i xLong3
  
  If Not xAutoDoing
    GetListIndexMS(xListHWnd(2), @xLong3)
    If xLong3 = -1
      xLong3 = 0
      EndIf
    If Not xDirCount = 0 And (Force Or xLong3 < xLong1 Or xLong3 > xLong2)
      For xLong1 = 1 To xDirCount
        If xDirPath(xLong1) > xLong3
          Break
          EndIf
        Next
      xLong2 = xDirPath(xLong1) - 1
      If xLong1 > xDirCount
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("Playlist index overdrive error (notification)")
          CompilerEndIf
        xLong1 = xDirCount
        EndIf
      If Not DontMarkPath
        SendMessage_(xListHWnd(0), #LB_SETCURSEL, xLong1 - 1, 0)
        EndIf
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("SetDirCap")
        CompilerEndIf
      CompilerIf #BoldDirs = 98
        MainForm_SetDirCaption(" " + PLI(xDirPath(xLong1 - 1))\Filename)
        CompilerElse
        MainForm_SetDirCaption(" " + PLIFile(xDirPath(xLong1 - 1)))
        CompilerEndIf
      xLong1 = xDirPath(xLong1 - 1)
CompilerIf #UseFileLogging
      Else
      MainForm_ctConsoleA_AddLog("LeaveDirCap")
CompilerEndIf
      EndIf
    EndIf
  EndProcedure

Procedure xMarkSong(ItemID.i, SkipUnmarking.i, NoListMarkX.i)
  Define.i xLong1
  Define.i xLong2

  If ItemID < PLCount And PLCount And Not xAutoDoing
    If Not SkipUnmarking
      SendMessage_(xListHWnd(2), #LB_SETSEL, 0, -1)
      EndIf

    xLong1 = SendMessage_(xListHWnd(2), #LB_GETTOPINDEX, 0, 0)
    xLong2 = Int(lPlayList_Height / SendMessage_(xListHWnd(2), #LB_GETITEMHEIGHT, 0, 0))
    If ItemID < xLong1 Or ItemID > xLong1 + xLong2
      xLong2 = ItemID - (xLong2 >> 1)
      If xLong2 < 0
        xLong2 = 0
        EndIf
      If Not xLong2 = xLong1
        SendMessage_(xListHWnd(2), #LB_SETTOPINDEX, xLong2, 0)
        EndIf
      ElseIf ItemID < xLong1 + (xLong2 >> 3)
      xLong2 = ItemID - (xLong2 >> 3)
      If xLong2 < 0
        xLong2 = 0
        EndIf
      If Not xLong2 = xLong1
        SendMessage_(xListHWnd(2), #LB_SETTOPINDEX, xLong2, 0)
        EndIf
      ElseIf ItemID > xLong1 + ((xLong2 * 7) >> 3)
      xLong2 = ItemID - ((xLong2 * 7) >> 3)
      If xLong2 < 0
        xLong2 = 0
        EndIf
      If Not xLong2 = xLong1
        SendMessage_(xListHWnd(2), #LB_SETTOPINDEX, xLong2, 0)
        EndIf
      EndIf
  
    SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, ItemID, 0)
    SendMessage_(xListHWnd(2), #LB_SETSEL, 1, ItemID)
    If Not NoListMarkX
      MainForm_CheckDir(#False)
      EndIf
    EndIf
  EndProcedure

Procedure ShowPlayer(AndFocus.i)
  Define.i xLong1
  Define.i xLong2
  
  xLong1 = GetLastActivePopup_(MainHWnd)
  If IsIconic_(MainHWnd)
    If xLong1 = 0 Or xLong1 = MainHWnd
      If AndFocus
        ShowWindow_(MainHWnd, 9)
        SetForegroundWindow_(MainHWnd)
        Else
        xLong2 = GetForegroundWindow_()
        ShowWindow_(MainHWnd, 9)
        SetForegroundWindow_(xLong2)
        EndIf
      Else
      If AndFocus
        ShowWindow_(MainHWnd, 9)
        ShowWindow_(xLong1, 9)
        SetForegroundWindow_(xLong1)
        SetWindowPos_(MainHWnd, -1, 0, 0, 0, 0, $213)
        SetWindowPos_(MainHWnd, -2, 0, 0, 0, 0, $213)
        Else
        xLong2 = GetForegroundWindow_()
        ShowWindow_(MainHWnd, 9)
        ShowWindow_(xLong1, 9)
        SetForegroundWindow_(xLong2)
        SetWindowPos_(MainHWnd, -1, 0, 0, 0, 0, $213)
        SetWindowPos_(MainHWnd, -2, 0, 0, 0, 0, $213)
        SetWindowPos_(xLong1, -1, 0, 0, 0, 0, $213)
        SetWindowPos_(xLong1, -2, 0, 0, 0, 0, $213)
        EndIf
      EndIf
    Else
    If xLong1 = 0
      ShowWindow_(MainHWnd, 5)
      If AndFocus
        SetForegroundWindow_(MainHWnd)
        Else
        SetWindowPos_(MainHWnd, -1, 0, 0, 0, 0, $213)
        SetWindowPos_(MainHWnd, -2, 0, 0, 0, 0, $213)
        EndIf
      Else
      ShowWindow_(MainHWnd, 5)
      ShowWindow_(xLong1, 5)
      If AndFocus
        SetForegroundWindow_(xLong1)
        Else
        SetWindowPos_(MainHWnd, -1, 0, 0, 0, 0, $213)
        SetWindowPos_(MainHWnd, -2, 0, 0, 0, 0, $213)
        SetWindowPos_(xLong1, -1, 0, 0, 0, 0, $213)
        SetWindowPos_(xLong1, -2, 0, 0, 0, 0, $213)
        EndIf
      EndIf
    EndIf
  xTrayIconIndicator = #False
  MainForm_ShowTray(#False)
  If SendMessage_(xListHWnd(2), $190, 0, 0) < 2
    xLong1 = xFindSong()
    If Not xLong1 = 0
      xLong2 = xFollowCurSongLastDiff
      xMarkSong(xLong1, #False, #False)
      If xLong2 < #xFollowCurSongLastDiffDef
        xFollowCurSongLastDiff = #xFollowCurSongLastDiffDef
        Else
        xFollowCurSongLastDiff = xLong2
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_TrayIconHandling_ShowPlayerHack()
  DoEvents()
  DoEvents()
  DoEvents()
  ShowPlayer(#True)
  EndProcedure

Procedure MainForm_TrayIconHandling(x.i)
  If Not xInfoQuit
    If x = 513 Or x = 516
      If (x = 513 And xTrayIconLeft = 0) Or (x = 516 And xTrayIconRight = 0)
        MainForm_TrayIconHandling_ShowPlayerHack()
        ProcedureReturn
        ElseIf IsDialoging = 0 And Not (PlayerIsLocked Or xAutoDoing)
        CompilerIf #UseFileLogging
          If Not (xTrayIconVisible Or xTrayIconIndicator)
            MainForm_ctConsoleA_AddLog("### Debug Info: InvSysIconClickEvent")
            ProcedureReturn
            EndIf
          CompilerEndIf
        If vKioskMode
          If x = 513 And xTrayIconLeft = 6
            MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(4), 0))
            Else
            MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(2), 0))
            EndIf
          Else
          If (x = 513 And xTrayIconLeft = 4) Or (x = 516 And xTrayIconRight = 1)
            If x = 516 And xMenu(3) = 0
              MainForm_TrayIconHandling_ShowPlayerHack()
              ProcedureReturn
              EndIf
            Select xTrayIconLeft
              Case 0
                If xTrayIconIndicator And xTrayIconVisible
                  SetMenuDefaultItem_(xMenu(3), 2101, #False)
                  Else
                  SetMenuDefaultItem_(xMenu(3), -1, #True)
                  EndIf
              Case 1: SetMenuDefaultItem_(xMenu(3), 2102, #False)
              Case 2: SetMenuDefaultItem_(xMenu(3), 2105, #False)
              Case 3: SetMenuDefaultItem_(xMenu(3), 2106, #False)
              Default: SetMenuDefaultItem_(xMenu(3), -1, #True)
              EndSelect
            ;MenuEvent GetAPIPopupMenu(MainHWnd, xMenu(3), 0, 0)
            MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(3), 0))
            
            ElseIf (x = 513 And xTrayIconLeft = 5) Or (x = 516 And xTrayIconRight = 2)
            If x = 516 And xMenu(2) = 0
              MainForm_TrayIconHandling_ShowPlayerHack()
              ProcedureReturn
              EndIf
            Select xTrayIconLeft
              Case 0
                If xTrayIconIndicator And xTrayIconVisible
                  SetMenuDefaultItem_(xMenu(2), 2800, #True)
                  Else
                  SetMenuDefaultItem_(xMenu(2), -1, #True)
                  EndIf
              Case 1: SetMenuDefaultItem_(xMenu(2), 2102, #True)
              Case 2: SetMenuDefaultItem_(xMenu(2), 2105, #True)
              Case 3: SetMenuDefaultItem_(xMenu(2), 2106, #True)
              Default: SetMenuDefaultItem_(xMenu(2), -1, #True)
              EndSelect
            ;MenuEvent GetAPIPopupMenu(MainHWnd, xMenu(2), 0, 0)
            MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(2), 0))
            ElseIf x = 513
            Select xTrayIconLeft
              Case 1 ;play/pause
                If xPStateIconPaused Or Not xPStateIconPlaying
                  MainForm_IconsMouseUp(1)
                  Else
                  MainForm_IconsMouseUp(2)
                  EndIf
              Case 2 ;playnext (skip)
                If xPStateIconPaused Or Not xPStateIconPlaying
                  MainForm_IconsMouseUp(1)
                  Else
                  MainForm_IconsMouseUp(4)
                  EndIf
              Case 3 ;endsong
                If xPStateIconPaused Or Not xPStateIconPlaying
                  MainForm_IconsMouseUp(1)
                  Else
                  MainForm_IconsMouseUp(5)
                  EndIf
        ;      Case 4 ;show menu
        ;      Case 5 ;show minimenu
              Case 6 ;show volume menu
                ;SetMenuDefaultItem_(xMenu(4), -1, #True)
                ;MenuEvent GetAPIPopupMenu(MainHWnd, xMenu(4), 0)
                If x = 516 And xMenu(3) = 0
                  MainForm_TrayIconHandling_ShowPlayerHack()
                  ProcedureReturn
                  EndIf
              EndSelect
            EndIf
          EndIf
        ElseIf xAutoDoing And xLoadingStream = 0 And Not vKioskMode
        If xMenu(7) = 0
          MainForm_TrayIconHandling_ShowPlayerHack()
          ProcedureReturn
          EndIf
        MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(7), 0))
        Else
        If xMenu(6) = 0
          MainForm_TrayIconHandling_ShowPlayerHack()
          ProcedureReturn
          EndIf
        MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(6), 0))
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_UpdateMainIcon()
  Define.i xLong1
  Static xLong2.i
  Define.s xChar1
  Define.s xChar2
  Static xLastToolTip.s
  
  If xPStateIconPlaying
    If xPStateIconPaused
      xLong1 = 2
      Else
      xLong1 = 1
      EndIf
    EndIf
  
  If Not xLong2 = xLong1
    Select xLong2
      Case 1
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def1, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $0)
        CheckApiMenu(102, #False)
      Case 2
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def2, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $1000000)
        CheckApiMenu(103, #False)
      EndSelect
    xLong2 = xLong1
    Select xLong2
      Case 1
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def1, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $10000000)
        CheckApiMenu(102, #True)
      Case 2
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def2, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $11000000)
        CheckApiMenu(103, #True)
      EndSelect
    EndIf
    
; 0-2                 -> 0-2
; --- subicon ---
; 5=refres            -> 15
; 4=quit              -> 11
; 3=startup           -> 10
; -> caption / icon
; -> max 0-19 (0-4,5-9), icon x 10 (1000 - 1190)
;                          largeicon: ID-10 -> 1200 - 1290
; ID 18 reserved -> (x)fade
; ID 19 reserved -> overloaded
; string x, extra tooltip (10-19) -> (20-29)


; 9 -> over!
;    If Not IsDialoging = 0
  ;xLong1 = 11
  ;EndIf
  
  If xPStateIconSndcard
    If xPStateIconPlugging
      xLong1 = 12
      Else
      xLong1 = 4
      EndIf
    ElseIf xPStateIconQuit
    xLong1 = 5
    ElseIf Not xLoadingStream = 0
    xLong1 = 9 + xLoadingStream ;10/11
    ElseIf xPStateIconRefreshing
    xLong1 = 7
    ElseIf xPStateIconDeleting
    xLong1 = 6
CompilerIf #TrayXFadeIcon
    ElseIf AllTears_TypesCount > 2 And Not CurMusic = #ctSSLayer_MusicTypeNone
    xLong1 = 8
CompilerEndIf
    ElseIf xOldWarnOverload
    xLong1 = 9
    ElseIf xPStateIconStartup And xLong1 < 3
    xLong1 = 3
    EndIf
  
    ; Refreshing can occur when trying to resume playback after deleting songs (and playlist is now empty)
  
  If xLong1 = 10
    CompilerIf #BoldDirs = 98
      xChar2 = PLI(PLCurItem)\Caption
      CompilerElse
      xChar2 = PLICap(PLCurItem)
      CompilerEndIf
    ElseIf xLong1 = 11
    xChar2 = RealURL(Mid(xLoadURL, FindString(xLoadURL + #CR$, #CR$) + 1))
    If Len(xChar2) = 0
      xChar2 = RealURL(xLoadURL)
      EndIf
    Else
    xChar2 = PLCurSongDisplay
    EndIf
  
  
  ;If xLong1 = 10
  ;  xChar1 = replacestring(LoadResString(1000 + xLong1 * 2), "$", PLCurSongDisplay)
  ;  ElseIf xLong1 = 11
  ;  xChar1 = replacestring(LoadResString(1000 + xLong1 * 2), "$", PLCurSongDisplay)
  ;  Else
    xChar1 = ReplaceString(LoadResString(1000 + xLong1 * 2), "$", xChar2)
  ;  endif
    
  
  ;If Not IsDialoging = 0
    ;xLong1 = 4
    ;EndIf
  
  
  If Not xOldIconState = xLong1
    SetWindowText_(MainHWnd, @xChar1)
    xLastToolTip = xChar1
    LoadResEx_WindowIcon_MultiOS(MainHWnd, 1000 + xLong1 * 50 + 15, 1000 + xLong1 * 50, @SysTrayIcon)
    
    Shell_NotifyIcon_SetTooltip(@SysTrayIcon, xChar1) ;+ vbNullChar
    
    If xLong1 > 2 And Not xLong1 = 5
      DoAnimateSetIcon(1030 + xLong1 * 50)
      Else
      DoAnimateSetIcon(-1)
      EndIf
    xOldIconState = xLong1
    
    
    If xTrayIconVisible Or xTrayIconEnabled
      Shell_NotifyIcon(1, @SysTrayIcon)
      EndIf
    ElseIf Not xLastToolTip = xChar1
    SetWindowText_(MainHWnd, @xChar1)
    xLastToolTip = xChar1
    Shell_NotifyIcon_SetTooltip(@SysTrayIcon, xChar1) ;+ vbNullChar
    If xTrayIconVisible Or xTrayIconEnabled
      Shell_NotifyIcon(1, @SysTrayIcon)
      EndIf
    EndIf
  
  ;xChar1 = replacestring(LoadResString(1000 + xLong1 * 2), "$", PLCurSongDisplay)
  SetToolTip(#xStaticIcons_Anim, ReplaceString(LoadResString(1001 + xLong1 * 2), "$", xChar2), "")
  
  If Not (LEDMode = 0 Or LEDState = $2)
    If xPStateIconPlaying
      If xPStateIconPaused
        LEDState = $20
        Else
        LEDState = 0
        EndIf
      Else
      LEDState = $10
      EndIf
    If xPStateIconDeleting
      LEDState = LEDState + $200
      ElseIf xPStateIconRefreshing
      LEDState = LEDState + $100
      EndIf
    If LEDState = $10
      If PLCount = 0
        LEDState = $3
        EndIf
      EndIf
    If LEDState = 0 And Not xShowSpectrum
      LEDState = 1
      SpectrumProcKb(0, 0, 0, 0)
      LEDState = 0
      EndIf
    EndIf
  EndProcedure

Procedure GetTimeFmt(IsIStream.i)
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  
  If CurMusic = #ctSSLayer_MusicTypeStream And IsIStream
    xChar1 = " " + Str(PLCurSongPos) + "% "  ; * (SongPosScrollWidth - ePic1ScaleBonus)) + "% "
    xLong1 = Len(xChar1)
    MainForm_RedrawPosition()
    ElseIf (PLCurSongLength > 0 And Not (PLCurSongPos < 0 Or PLCurSongPos > PLCurSongLength)) Or ctSSLayer_CanUseItem(6) = $2
    If PLCurSongLength
      xLong1 = MulDiv_(PLCurSongPos, SongPosScrollWidth - ePic1ScaleBonus, PLCurSongLength)
      MainForm_RedrawPosition()
      EndIf
    If CurMusic = #ctSSLayer_MusicTypeTracker And ctSSLayer_CanUseItem(6) < 2
      ; nothing realtimes, or patterns
      xChar1 = " " + Right("0000000000" + Str(PLCurSongPos + 1), Int(Log10(PLCurSongLength)) + 1) + "/" + Str(PLCurSongLength)
      Else
      If Not CurMusic = #ctSSLayer_MusicTypeTracker Or (ctSSLayer_CanUseItem(6) & 4)
        If xShowElapsed
          xLong1 = PLCurSongPos / 1000
          Else
          xLong1 = (PLCurSongLength - PLCurSongPos) / 1000
          EndIf
        ElseIf ctSSLayer_CanUseItem(6) & 8
        CurSongPatterns = ctSSLayer_MusicGetPatterns(SongPointer(CurrentSongID))
        If CurSongPatterns
          xLong1 = ctSSLayer_MusicGetPattern(SongPointer(CurrentSongID))
          xLong2 = ctSSLayer_MusicTime(SongPointer(CurrentSongID))
          If xShowElapsed
            xLong1 = CurSongPatterns - xLong1
            EndIf
          xLong1 = MulDiv_(xLong1, xLong2, 1000 * CurSongPatterns)
          EndIf
        Else ; 2er
        xLong1 = ctSSLayer_MusicTime(SongPointer(CurrentSongID)) / 1000
        EndIf
      If (PLCurSongLength < 600000 And PLCurSongPos < 600000)
        xChar1 = " " + Str(Int(xLong1 / 60)) + ":" + Right("00" + Str(xLong1 % 60), 2)
        ElseIf (PLCurSongLength < 3600000 And PLCurSongPos < 3600000)
        xChar1 = " " + Right("00" + Str(Int(xLong1 / 60)), 2) + ":" + Right("00" + Str(xLong1 % 60), 2)
        Else
        xLong2 = (xLong1 % 3600)
        xChar1 = " " + Right("0000000000" + Str(Int(xLong1 / 3600)), Int(Log10(PLCurSongLength / 3600000)) + 1) + ":" + Right("00" + Str(Int(xLong2 / 60)), 2) + ":" + Right("00" + Str(xLong1 % 60), 2)
        EndIf
      EndIf
    ElseIf CurMusic = #ctSSLayer_MusicTypeTracker And ctSSLayer_CanUseItem(6) < 2
    If PLCurSongLength > 0
      xChar1 = " " + Right("????????", Int(Log10(PLCurSongLength)) + 1) + "/" + Str(PLCurSongLength)
      Else
      xChar1 = " ??/??"
      EndIf
    Else ;somethingtimebased
    ;If PLCurSongLength > 0
      If PLCurSongLength < 600000 Or (CurMusic = #ctSSLayer_MusicTypeTracker And (ctSSLayer_CanUseItem(6) & 4) = 0)
        xChar1 = " ?:??"
        ElseIf PLCurSongLength < 3600000
        xChar1 = " ??:??"
        Else
        xChar1 = " " + StringFromCharCode(Int(Log10(PLCurSongLength / 3600000)) + 1, 63) + "??:??" ; 63 = "?"
        EndIf
      ;Else
      ;xchar1 = " ?:??
      ;endif
    EndIf
  xLong1 = Len(xChar1)
  If Not xLong1 = 0
    PLCurSongDisplaySpaceStr = xChar1 + "  -  " + PLCurSongDisplay
    SelectObject_(xSharedDC, hFontGFix)
    xLong1 = GetTextOutWidth(xSharedDC, Left(PLCurSongDisplaySpaceStr, xLong1 + 1))
    PLCurSongDisplaySpaceStr = xChar1 + "  -  " + PLCurSongDisplay
    PLCurSongDisplaySpacePosOrg = PLCurSongDisplaySpace - xLong1
    MP3GetFormatChanged(#True)
    EndIf
  EndProcedure

Procedure ResetStreamTT()
  Define.s xChar1
  If vKioskMode
    SetFormatToolTip(LastStreamTT, "")
    ElseIf UrlsAllowed
    xChar1 = LoadResString(1932)

    xChar1 = ReplaceString(xChar1, "$I", ExtKbdEx(#KbdC_OInternetRadio))
    xChar1 = ReplaceString(xChar1, "$R", ExtKbdEx(#KbdC_OInternetRadioRe))
    xChar1 = ReplaceString(xChar1, "$U", ExtKbdEx(#KbdC_OInternetRadioHP))
    SetFormatToolTip(LastStreamTT, xChar1)
    Else
    xChar1 = LoadResString(1935)
    xChar1 = ReplaceString(xChar1, "$I", ExtKbdEx(#KbdC_OInternetRadio))
    xChar1 = ReplaceString(xChar1, "$R", ExtKbdEx(#KbdC_OInternetRadioRe))
    SetFormatToolTip(LastStreamTT, xChar1)
    EndIf
  EndProcedure

Procedure.s SPTimeShort()
  GetLocalTime_(@sSystemTime)
  ProcedureReturn Right("0" + Str(sSystemTime\wHour), 2) + ":" + Right("0" + Str(sSystemTime\wMinute), 2) + ":" + Right("0" + Str(sSystemTime\wSecond), 2)
  EndProcedure

Procedure.i AppendToTextFileEx(Filename.s, xLine.s)
  Define.i xResult
  Define.i hTxtFileOut
  
  hTxtFileOut = TxtFileWriter_AppendFile(Filename)
  If hTxtFileOut
    xResult = TxtFileWriter_WriteLine(hTxtFileOut, xLine)
    TxtFileWriter_Close(hTxtFileOut)
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_ctConsoleA_AddSong(MsgSong.s)
  MsgSong = SPTimeShort() + " " + MsgSong
  If LogFileDo
    If LogFileMulti
      With sSystemTime
        LogFileDo = AppendToTextFileEx(LogFile + "_" + Right("000" + Str(\wYear), 4) + "." + Str(\wMonth) + "." + Right("0" + Str(\wDay), 2) + ".log", MsgSong)
        EndWith
      Else
      LogFileDo = AppendToTextFileEx(LogFile, MsgSong)
      EndIf
    EndIf
  CompilerIf #UseFileLogging
    CompilerElse
    CompilerIf #UseFileLoggingIDE
      Debug MsgSong
      CompilerEndIf
    CompilerEndIf
  EndProcedure

Procedure.s MainForm_ReadLate_ComReplace(*xType1.ctSSLayerSongInfoNeat, xChar1.s)
  xChar1 = ReplaceString(xChar1, "$A", Chr(1))
  xChar1 = ReplaceString(xChar1, "$T", Chr(2))
  xChar1 = ReplaceString(xChar1, "$L", Chr(3))
  xChar1 = ReplaceString(xChar1, "$N", Chr(4))
  xChar1 = ReplaceString(xChar1, "$Y", Chr(5))
  xChar1 = ReplaceString(xChar1, "$S", Chr(6))
  If *xType1\Tag_Artist = ""
    *xType1\Tag_Artist = LoadResString(1186)
    EndIf
  If *xType1\Tag_Title = ""
    *xType1\Tag_Title = LoadResString(1186)
    EndIf
  If *xType1\Tag_Album = ""
    *xType1\Tag_Album = LoadResString(1186)
    EndIf
  xChar1 = ReplaceString(xChar1, Chr(1), *xType1\Tag_Artist)
  xChar1 = ReplaceString(xChar1, Chr(2), *xType1\Tag_Title)
  xChar1 = ReplaceString(xChar1, Chr(3), *xType1\Tag_Album)
  If *xType1\Tag_TrackID
    xChar1 = ReplaceString(xChar1, Chr(4), StrU(*xType1\Tag_TrackID))
    Else
    xChar1 = ReplaceString(xChar1, Chr(4), LoadResString(1186))
    EndIf
  If *xType1\Tag_Year
    xChar1 = ReplaceString(xChar1, Chr(5), StrU(*xType1\Tag_Year))
    Else
    xChar1 = ReplaceString(xChar1, Chr(5), LoadResString(1186))
    EndIf
  If Len(*xType1\IR_Name)
    xChar1 = ReplaceString(xChar1, Chr(6), *xType1\IR_Name)
    ElseIf Len(SenderURL)
    xChar1 = ReplaceString(xChar1, Chr(6), SenderURL)
    ElseIf Len(*xType1\IR_URL)
    xChar1 = ReplaceString(xChar1, Chr(6), *xType1\IR_URL)
    Else
    xChar1 = ReplaceString(xChar1, Chr(6), LoadResString(1192))
    EndIf
  ProcedureReturn xChar1
  EndProcedure

Procedure MainForm_ReadLate(Filename.s, UpdateMode.u)
  Define.i xLong1
  Define.s xChar1
  Define.s xChar2
  Define.i IsMidiValue
  Static xType1.ctSSLayerSongInfoNeat
  
  If UpdateMode
    IsMidiValue = xSongIsMidi
    Else
    IsMidiValue = xSongWillBeMidi
    EndIf
  
  If Filename = "" ;Or FileName = Chr(1)
    Filename = PLCurSong
    ;ClearOldSongInfo
    EndIf

  If MP3GetID3Tag Or MP3GetFormat
    Select CurMusic
      Case #ctSSLayer_MusicTypeNone
        ClearOldSongInfo()
      Case #ctSSLayer_MusicTypeStream
        If Not ctSSLayer_ReadSongInfo(SongPointer(CurrentSongID), @xType1)
          xType1\FormatOK = 0
          xType1\TagOK = 0
          EndIf
        If xType1\TagOK
          xChar1 = ReplaceString(LoadResString(1185), "|", #CRLF$)
          xChar1 = MainForm_ReadLate_ComReplace(@xType1, xChar1)
          If Not curTagText = xChar1
            curTagText = xChar1
            SetWindowText_(xStaticIconsHWnd(#xStaticIcons_Tags), @curTagText)
            EndIf
          Else
          curTagText = ""
          SetWindowText_(xStaticIconsHWnd(#xStaticIcons_Tags), @"")
          EndIf
        
        If IsMidiValue = 3
          If xType1\FormatOK And IsMidiValue = 3
            If UrlsAllowed
              xLong1 = 1931
              Else
              xLong1 = 1934
              EndIf
            ElseIf UrlsAllowed
            xLong1 = 1930
            Else
            xLong1 = 1933
            EndIf
          ElseIf xType1\FormatOK
          xLong1 = 1921
          Else
          xLong1 = 1920
          EndIf
        xChar2 = LoadResString(xLong1)


        If xType1\FormatOK
          xChar2 = ReplaceString(xChar2, "$B", Str(xType1\Format_BitRate / 1000))
          xChar2 = ReplaceString(xChar2, "$F", Str(xType1\Format_Frequency / 1000))
          If xType1\Format_Channels > 2
            xChar2 = ReplaceString(xChar2, "$C", ReplaceString(LoadResString(1992), "$", StrU(xType1\Format_Channels)))
            Else
            xChar2 = ReplaceString(xChar2, "$C", LoadResString(1989 + xType1\Format_Channels))
            EndIf
          If Not UpdateMode
            If IsMidiValue = 3
              MainForm_DrawRawBMP_CalaymStatic(-1, *FormatIconBmp(4), FormatIconLen(4), GetQualityStreamRGB(xType1))
              Else
              MainForm_DrawRawBMP_CalaymStatic(-1, *FormatIconBmp(0), FormatIconLen(0), GetQualityStreamRGB(xType1))
              EndIf
            EndIf
          ElseIf Not UpdateMode
          If IsMidiValue = 3
            MainForm_DrawRawBMP_CalaymStatic(-1, *FormatIconBmp(4), FormatIconLen(4), 0)
            Else
            MainForm_DrawRawBMP_CalaymStatic(-1, *FormatIconBmp(0), FormatIconLen(0), 0)
            EndIf
          EndIf
      ;Case #ctSSLayer_MusicTypeInetStream
      Case #ctSSLayer_MusicTypeTracker
        If IsMidiValue
          MainForm_DrawRawBMP_CalaymStatic(-1, *FormatIconBmp(1), FormatIconLen(1), 0)
          xChar2 = LoadResString(1902)
          Else
          MainForm_DrawRawBMP_CalaymStatic(-1, *FormatIconBmp(2), FormatIconLen(2), 0)
          xChar2 = LoadResString(1903)
          EndIf
      Case #ctSSLayer_MusicTypeCDAudio
        MainForm_DrawRawBMP_CalaymStatic(-1, *FormatIconBmp(3), FormatIconLen(3), 0)
        xChar2 = LoadResString(1904)
      EndSelect
      
    If IsMidiValue = 3
;debug "ReCreate"
      ;xchar2=xchar1
      xChar1 = MainForm_ReadLate_ComReplace(@xType1, LoadResString(1190))
;debug "  IsNow:", xChar1
      If Not PLCurSongDisplay = xChar1
;debug "  Update!"
        PLCurSongDisplay = xChar1
        MainForm_UpdateMainIcon()
        GetTimeFmt(#True)
        CompilerIf #FlatCastCF17
          xFCI.Text0 = xChar1
          CompilerEndIf
        CompilerIf #LoudestSongMethode
          Tear_Caption(CurrentSongID) = PLCurSongDisplay
          CompilerElse
          If Not xPStateIconPaused
            ShowIR
            EndIf
          CompilerEndIf
        xChar1 = MainForm_ReadLate_ComReplace(@xType1, LoadResString(1191))
        MainForm_ctConsoleA_AddSong(xChar1)
        EndIf
      If Len(xType1\IR_Name) = 0
        xType1\IR_Name = LoadResString(1936)
        EndIf
      If Len(xType1\IR_URL) = 0
        xType1\IR_URL = LoadResString(1937)
        ElseIf Len(SenderURL) = 0
        SenderURL = xType1\IR_URL
        EndIf
      ;xChar1 = LoadResString(1936)
      LastStreamTT = ReplaceString(ReplaceString(ReplaceString(xChar2, "$U", Chr(1)), "$T", xType1\IR_Name), Chr(1), xType1\IR_URL)
      ResetStreamTT()
      Else
      xChar1 = GetExtensionPart(Filename)
      SetFormatToolTip(ReplaceString(xChar2, "$T", UCase(Left(xChar1, 1)) + Mid(xChar1, 2)), "")
      EndIf
    EndIf
  EndProcedure

Procedure GetWhiteBackGrnd() ;(NoApply As Boolean)
  Define *Mem
  Define.i MemLen
  
  ;MSDN: The default delay times are based on the double-click time. For the default double-click time of 500 ms, the initial, autopop, and reshow delay times are 500ms, 5000ms, and 100ms respectively. The following code fragment uses the GetDoubleClickTime [ http://msdn.microsoft.com/en-us/library/ms646258(VS.85,printer).aspx ] function to determine the three delay times for any system.
  ToolTipDelay = GetDoubleClickTime_()
  
  ScrollComboWidth = GetSystemMetrics_(2)
  FLineColor = GetSysColor_(13)
  FLineColorX = GetSysColor_(5)
  FLineColorWDCTxt = GetSysColor_(8)
  FormatIconFore = GetSysColor_(18)
  FormatIconBack = GetSysColor_(15)
  FormatIconBackSunkenD = GetSysColor_(16)
  FormatIconBackSunkenW = GetSysColor_(20)
  FormatIconBackSunken = FormatIconBackSunkenW
  
  SysColor5 = GetSysColor_(5)
  SysColor8 = GetSysColor_(8)
  SysColor13 = GetSysColor_(13)
  SysColor14 = GetSysColor_(14)
  SysColor15 = GetSysColor_(15)
  SysColor17 = GetSysColor_(17)
  SysColor20 = GetSysColor_(20)
  SysColor23 = GetSysColor_(23)
  SysColor24 = GetSysColor_(24)
  

  xDoAnimColor1 = MixRGB(FLineColor, FLineColorX, 66)
  xDoAnimColor2 = MixRGB(FLineColor, FLineColorX, 33)
  xDoAnimColor3 = MixRGB(FLineColor, FLineColorX, 10)
  
  
  
  SetBkColor_(xSharedDC, FLineColorX)
  SetTextColor_(xSharedDC, FLineColorWDCTxt)
  
  
  
  If xTimerEvCount = 0
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_TimerInd, *xTimerIconBMP, xTimerIconLen, 0)
    Else
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_TimerInd, *xTimerIconBMP, xTimerIconLen, $10000000)
    EndIf
  
  MainForm_DrawVolFaderA(xSetVolume); 2
  
  *Mem = LoadResData_Copy(1000, 2, @MemLen)
  If *Mem
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def0, *Mem, MemLen, $0)
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def4, *Mem, MemLen, $1000000)
    LocalFree_(*Mem)
    EndIf
  
  If Not vKioskMode
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def3, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $2000000)
    EndIf
  If IntroModeActive
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_RepMode, *DynButtonsResXRepBMP, DynButtonsResXRepLen, $10000000 + xRep * $1000000)
    Else
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_RepMode, *DynButtonsResXRepBMP, DynButtonsResXRepLen, xRep * $1000000)
    EndIf
  
  If xPStateIconPlaying
    If xPStateIconPaused
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def1, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $0)
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def2, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $11000000)
      Else
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def1, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $10000000)
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def2, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $1000000)
      EndIf
    If xHasNextSong And Not SilentPlNext
      If vKioskMode
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def3, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $13000000)
        Else
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def5, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $13000000)
        EndIf
      Else
      If vKioskMode
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def3, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $3000000)
        Else
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def5, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $3000000)
        EndIf
      EndIf
    Else
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def1, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $0)
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def2, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $1000000)
    If vKioskMode
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def3, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $3000000)
      Else
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def5, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $3000000)
      EndIf
    EndIf
  
  MainForm_ReadLate("", #False)
  
  DoAnimateReadDir(0)
  EndProcedure

Procedure PseudoVolumeNow(lParam.i)
  MainForm_ePic_MouseDown(2, SignedLowerWord(lParam))
  EndProcedure

Procedure.i VolumeHook(hWnd.i, Message.i, wParam.i, lParam.i)
  Define.i xResult

  xResult = CallWindowProc_(VolumeHookOld, hWnd, Message, wParam, lParam)
  Select Message
    Case $200
      If xIsVoluming
        PseudoVolumeNow(lParam)
        EndIf
    Case $201
      SetCapture_(hWnd)
      xIsVoluming = #True
    Case $202
      If xIsVoluming
        PseudoVolumeNow(lParam)
        ReleaseCapture_()
        xIsVoluming = #False
        EndIf
    EndSelect
  ProcedureReturn xResult
  EndProcedure

;boolean
Procedure.i MainForm_CreatePlayerForm()
  Define.WNDCLASSEX xType1
  Define.i xLong1
  Define.i xResult

  NSCursor = LoadCursor_(0, $7F85)
  WECursor = LoadCursor_(0, $7F84)

  With xType1
    \cbSize = SizeOf(WNDCLASSEX)
    \Style = $83
    \hCursor = NSCursor
    \hbrBackground = 19
    \lpfnWndProc = @NoProc()
    ;Debug \lpszClassName
    RegisterClassEx(@xType1, #CalaymClassSplitterMoveTH)
    
    \hCursor = WECursor
    RegisterClassEx(@xType1, #CalaymClassSplitterMoveLW)
    
    
    \Style = $83
    \hCursor = LoadCursor_(0, $7F00)
    \hbrBackground = 25
    \lpfnWndProc = @RedrawProc()
    RegisterClassEx(@xType1, #CalaymClassToolTip)
    
    \hbrBackground = 6
    \lpfnWndProc = @ProcClassWnd()
    RegisterClassEx(@xType1, #CalaymClassNameMsg)
    
    \Style = $B  ; $4B / 40 causes disp. problems after standby (win7)
    \lpfnWndProc = @RedrawProc()
    RegisterClassEx(@xType1, #CalaymClassStaticWhiteDC)
    
    \Style = $83
    \hbrBackground = 16
    \lpfnWndProc = @SplitterProcTH()
    RegisterClassEx(@xType1, #CalaymClassSplitterTH)
    \lpfnWndProc = @SplitterProcLW()
    RegisterClassEx(@xType1, #CalaymClassSplitterLW)
    
    
    \Style = $3
    \lpfnWndProc = @PlayerFormProc()
    RegisterClassEx(@xType1, #CalaymClassForm)
    EndWith
  

  MainHWnd = CreateWindowExOC($0, #CalaymClassForm, "", $ECF1000, 0, 0, 0, 0, 0, 0, 0)
  If MainHWnd
    OleInitialize_(0)

    xStaticIconsHWnd(#xStaticIcons_BAR) = CreateWindowExOC($0, #W_STATIC, "", $56000000, 0, 0, 0, 0, MainHWnd, 0, 0)

    SplitterMoveTopOrLeftPos = xDefCtlHeight16 ;25
    HWndSplitterTH = CreateWindowExOC(0, #CalaymClassSplitterTH, "", $56000000, 0, SplitterMoveTopOrLeftPos, 369, eSPTopY, MainHWnd, 0, 1055)
    HWndSplitterLW = CreateWindowExOC(0, #CalaymClassSplitterLW, "", $46000000, 0, SplitterMoveTopOrLeftPos, eSPTopX, 240, MainHWnd, 0, 1055)
    HWndSplitterMoveTH = CreateWindowExOC(0, #CalaymClassSplitterMoveTH, "", $46000000, 0, SplitterMoveTopOrLeftPos, 369, eSPTopY, MainHWnd, 0, 1055)
    HWndSplitterMoveLW = CreateWindowExOC(0, #CalaymClassSplitterMoveLW, "", $46000000, 0, SplitterMoveTopOrLeftPos, eSPTopX, 240, MainHWnd, 0, 1055)
    
    xListHWnd(2) = CreateWindowExOC($200, #W_LISTBOX, "", $56300918, 0, xDefCtlHeight16 + eSPTopX, 377, 308, MainHWnd, 0, 1050)

    SendMessage_(xListHWnd(2), $1A8, PLCountMax, 0)
    xListHWnd(0) = CreateWindowExOC($20201, #W_LISTBOX, "", $46300110, 0, xDefCtlHeight16 - 3, 361, 122, MainHWnd, 0, 1060)
    xListHWnd(1) = CreateWindowExOC($20201, #W_LISTBOX, "", $46300110, 0, 216, 377, 122, MainHWnd, 0, 1061)
    
    
    xStaticIconsHWnd(#xStaticIcons_Anim) = CreateWindowExOC($0, #W_STATIC, "", $4600090E, 320, 40, 32, #AnimHeightAnimOnly, MainHWnd, 0, 1090)
    SetWindowPos_(xListHWnd(2), 1, 0, 0, 0, 0, $213)
    SetWindowPos_(xListHWnd(0), 0, 0, 0, 0, 0, $213)
    SetWindowPos_(xListHWnd(1), 0, 0, 0, 0, 0, $213)
    SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Anim), 0, 0, 0, 0, 0, $213)
      
    For xLong1 = 0 To 2
      If xListHWnd(xLong1) = 0
        ProcedureReturn
        EndIf
      xListHWndHook(xLong1) = SetWindowLong_(xListHWnd(xLong1), -4, @ListsHook())
      Next
    
      
    If Not xStaticIconsHWnd(#xStaticIcons_BAR) = 0
      BARHookOld = SetWindowLong_(xStaticIconsHWnd(#xStaticIcons_BAR), -4, @BARHook())
      If Not vKioskMode
        For xLong1 = 0 To 5
          xStaticIconsHWnd(xLong1) = CreateWindowExOC($0, #W_STATIC, "", $5000090E, 8 + 24 * xLong1, PlayControlsTop, 20, 16, xStaticIconsHWnd(#xStaticIcons_BAR), 0, 1000 + xLong1)
          Next
        xStaticIconsHWnd(#xStaticIcons_Volume) = CreateWindowExOC($0, #W_STATIC, "", $5000090E, 152, PlayControlsTop, 40, 16, xStaticIconsHWnd(#xStaticIcons_BAR), 0, 1006)
        VolumeHookOld = SetWindowLong_(xStaticIconsHWnd(#xStaticIcons_Volume), -4, @VolumeHook())
        
        xStaticIconsHWnd(#xStaticIcons_RepMode) = CreateWindowExOC($0, #W_STATIC, "", $5000090E, 196, PlayControlsTop, 20, 16, xStaticIconsHWnd(#xStaticIcons_BAR), 0, 1007)
        xStaticIconsHWnd(#xStaticIcons_TimerInd) = CreateWindowExOC($0, #W_STATIC, "", $5000090E, 220, PlayControlsTop, 20, 16, xStaticIconsHWnd(#xStaticIcons_BAR), 0, 1008)
        EndIf
      
      xStaticIconsHWnd(#xStaticIcons_CurSongPos) = CreateWindowExOC($200, #CalaymClassStaticWhiteDC, "", $56000000, 0, 24, 377, CurSongPosRealHeight, xStaticIconsHWnd(#xStaticIcons_BAR), 0, 1025)
      xStaticIconsHWnd(#xStaticIcons_CurSong) = CreateWindowExOC($200, #CalaymClassStaticWhiteDC, "", $56000000, 0, 0, 324, xDefCtlHeight16, xStaticIconsHWnd(#xStaticIcons_BAR), 0, 1021)
      xStaticIconsHWnd(#xStaticIcons_Tags) = CreateWindowExOC($20000, #W_EDIT, "", $50000944, 0, 32, 200, 24, xStaticIconsHWnd(#xStaticIcons_BAR), 0, 0)
      xStaticIconsHWnd(#xStaticIcons_Spectrum) = CreateWindowExOC($20000, #CalaymClassStaticWhiteDC, "", $40000000, SpectrumMinLeft, SpectrumTop, SpectrumWidth, SpectrumHeight, xStaticIconsHWnd(#xStaticIcons_BAR), 0, 0)
      xStaticIconsHWnd(#xStaticIcons_ShowIR) = CreateWindowExOC($88, #CalaymClassNameMsg, #CalaymClassTitleMsg, $8E800000, 0, 0, 400, 35, 0, 0, 0)
      xStaticIconsHWnd(#xStaticIcons_ToolTip) = CreateWindowExOC($84, #CalaymClassToolTip, "", $8E800000, 0, 0, 160, 16, MainHWnd, 0, 0)

      If Not xStaticIconsHWnd(#xStaticIcons_Anim) = 0
        xStaticIconsBMP(xLong1) = CreateCompatibleBitmapX(32, 40)
        EndIf
      If Not xStaticIconsHWnd(#xStaticIcons_ShowIR) = 0
        ChangeWindowMessageFilterEx(xStaticIconsHWnd(#xStaticIcons_ShowIR), $111, 1, 0)
        ChangeWindowMessageFilterEx(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, 1, 0)
        
        ShowIR_IconHWnd1 = LoadResEx_Image_MultiOS(2900, 1)
        If Not ShowIR_IconHWnd1 = 0
          ShowIR_IconHWnd2 = LoadResEx_Image_MultiOS(2920, 1)
          ShowIR_IconHWnd = ShowIR_IconHWnd1
          EndIf
        EndIf
      
      EndIf
    xStaticIconsHWnd(#xStaticIcons_DirList) = CreateWindowExOC($200, #CalaymClassStaticWhiteDC, "", $56000000, 0, 0, 361, xDefCtlHeight16, MainHWnd, 0, 1020)
    
    PLIconFolder = LoadResEx_Image_MultiOS(#PLIconFolder_ResID, 1, 16)
    If Not PLIconFolder = 0
      PLIconFile = LoadResEx_Image_MultiOS(#PLIconFile_ResID, 1, 16)
      If PLIconFile = 0
        DestroyIcon_(PLIconFolder)
        PLIconFolder = 0
        EndIf
      EndIf
    PLIconURL = LoadResEx_Image_MultiOS(#PLIconURL_ResID, 1, 16)

    SysTrayIcon\hWnd = xStaticIconsHWnd(#xStaticIcons_ShowIR)
    SysTrayIcon\uFlags = 7
    SysTrayIcon\uCallBackMessage = 512
    
    If Not (xListHWnd(0) = 0 Or xSharedDC = 0)
      xResult = #True
      CompilerIf #XPDeviceRemoveDetect
        RemovableDevices_RegisterAll(MainHWnd)
        CompilerEndIf
      ;Load OLEHelperForm
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure DestroyPlayerForm()
  Define.i xLong1

  If Not MainHWnd = 0
    If Not InterfaceMode = #Interface_Mode_None
      ToggleInterface(#Interface_Mode_None)
      EndIf
    If Not OldAnimIcon = 0
      DestroyIcon_(OldAnimIcon)
      EndIf
    
    If Not PLIconFolder = 0
      DestroyIcon_(PLIconFolder)
      DestroyIcon_(PLIconFile)
      EndIf

    CompilerIf #XPDeviceRemoveDetect
      RemovableDevices_UnregisterAll()
      CompilerEndIf

    If Not xSharedDC = 0
      If ShowIRWin
        KillTimer_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 3)
        ShowIRWin = #False
        EndIf
      DestroyWindow_(xStaticIconsHWnd(#xStaticIcons_ShowIR))
      If Not ShowIR_IconHWnd1 = 0
        DestroyIcon_(ShowIR_IconHWnd1)
        If Not ShowIR_IconHWnd2 = 0 
          DestroyIcon_(ShowIR_IconHWnd2)
          EndIf
        EndIf
      EndIf
    
    
    UnTheme()
    
    For xLong1 = 0 To 2
      If Not xListHWndHook(xLong1) = 0
        SetWindowLong_(xListHWnd(xLong1), -4, xListHWndHook(xLong1))
        EndIf
      Next
    
    If Not xStaticIconsHWnd(#xStaticIcons_BAR) = 0 
      SetWindowLong_(xStaticIconsHWnd(#xStaticIcons_BAR), -4, BARHookOld)
      EndIf
    If Not xStaticIconsHWnd(#xStaticIcons_Volume) = 0 
      SetWindowLong_(xStaticIconsHWnd(#xStaticIcons_Volume), -4, VolumeHookOld)
      EndIf
    
    DestroyWindow_(xStaticIconsHWnd(#xStaticIcons_ToolTip))
    
    LoadResEx_WindowIcon_Discard(MainHWnd, @SysTrayIcon)
    
    ;DoAnimateSetIcon(-1)
    DestroyWindow_(MainHWnd)
    
    SelectObject_(xSharedDC, xSharedDCOldFont)
    If Not hFontGFix = 0 
      DeleteObject_(hFontGFix)
      EndIf
    If Not hFontShIR = 0
      DeleteObject_(hFontShIR)
      EndIf
    If Not hFontPLLgB = 0
      DeleteObject_(hFontPLLgB)
      EndIf
    If Not hFontPLLg = 0
      DeleteObject_(hFontPLLg)
      EndIf
    If Not hFontPLSm = 0
      DeleteObject_(hFontPLSm)
      EndIf
    If Not hFontTTip = 0
      DeleteObject_(hFontTTip)
      EndIf
      
    OleUninitialize_()
    MainHWnd = 0

    For xLong1 = 0 To #xStaticIcons_LastBMP
      If Not xStaticIconsBMP(xLong1) = 0
        DeleteObject_(xStaticIconsBMP(xLong1))
        EndIf
      Next
    If Not MP3FormatBitmap = 0
      DeleteObject_(MP3FormatBitmap)
      EndIf
    EndIf
  
  UnregisterClass(#CalaymClassNameMsg)
  UnregisterClass(#CalaymClassStaticWhiteDC)
  UnregisterClass(#CalaymClassForm)
  UnregisterClass(#CalaymClassSplitterMoveLW)
  UnregisterClass(#CalaymClassSplitterMoveTH)
  UnregisterClass(#CalaymClassSplitterLW)
  UnregisterClass(#CalaymClassSplitterTH)
  UnregisterClass(#CalaymClassToolTip)
  
  
  SelectObject_(xSharedDC, xSharedDCOldFont)
  DeleteDC_(xSharedDC)
  EndProcedure

Procedure MouseWheelVolume(wParam.i)
  Define.i Message

  Message = SignedHigherWord(wParam)
  If Message < 0 And MouseWheelDeltaVol > 0
    MouseWheelDeltaVol = 0
    ElseIf Message > 0 And MouseWheelDeltaVol < 0
    MouseWheelDeltaVol = 0
    EndIf
  MouseWheelDeltaVol = MouseWheelDeltaVol + Message
  Message = xSetVolume + Int(MouseWheelDeltaVol / #MouseWheelDeltaDivVol)
  MouseWheelDeltaVol = MouseWheelDeltaVol % #MouseWheelDeltaDivVol
  If Message > 255
    Message = 255
    ElseIf Message < 0
    Message = 0
    EndIf
  If Not xSetVolume = Message
    DoVolume(Message, #True)
    EndIf
  EndProcedure

Procedure PlayerFormAbortMoveAndDrags()
  If xIsVoluming
    xIsVoluming = #False
    ReleaseCapture_()
    EndIf
  If MainFormIsSplitterMovingTH
    MainFormIsSplitterMovingTH = #False
    ReleaseCapture_()
    SetWindowPos_(HWndSplitterMoveTH, 1, 0, 0, 0, 0, $213)
    ShowWindow_(HWndSplitterMoveTH, 0)
;        ResizePlayer
    ElseIf MainFormIsSplitterMovingLW
    MainFormIsSplitterMovingLW = #False
    ReleaseCapture_()
    SetWindowPos_(HWndSplitterMoveLW, 1, 0, 0, 0, 0, $213)
    ShowWindow_(HWndSplitterMoveLW, 0)
    EndIf
  MainFormDraggingIs = #False
  SearchFormDraggingIs = #False
  EndProcedure

Procedure.i DragDetectWinLikePL(lParam.i)
  Define.i xResult
  Define.i xLong1
  Define.i X1
  Define.i X2
  
  If PLCount
    xLong1 = SendMessage_(xListHWnd(2), #LB_GETITEMHEIGHT, 0, 0)
    If xLong1 > 0
      xLong1 = SignedHigherWord(lParam) / xLong1 + SendMessage_(xListHWnd(2), #LB_GETTOPINDEX, 0, 0)
      If xLong1 < PLCount And Not xLong1 < -1
        If SendMessage_(xListHWnd(2), #LB_GETSEL, xLong1, 0) > 0
CompilerIf #BoldDirs = 98
          X1 = (PLI(xLong1)\DirDepthFlags & #PLI_Depth) * 20 + 24
          X2 = X1 + PLI(xLong1)\pxWidthLg
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
          X1 = (PLIDF(xLong1) & #PLI_Depth) * 20 + 24
          X2 = X1 + PLIPxLg(xLong1)
          If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
            If PLIconFolder
              X1 - 20
              EndIf
            ElseIf PLIconFile
            X1 - 20
            EndIf
          xLong1 = SignedLowerWord(lParam)
          If xLong1 >= X1 And xLong1 <= X2
            xResult = #True
            EndIf
          EndIf
        EndIf
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.i DragDetectWinLikeSL(lParam.i)
  Define.i xResult
  Define.i xLong1
  Define.i xLong2
  Define.i X1

  If Not (PLCount = 0 Or xSearchCount = 0)
    xLong1 = SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETITEMHEIGHT, 0, 0)
    If xLong1 > 0
      xLong1 = SignedHigherWord(lParam) / xLong1 + SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETTOPINDEX, 0, 0)
      If xLong1 < xSearchCount And Not xLong1 < -1
      ;xLong1 = SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETITEMDATA, xLong1, 0)
;Print PLI(xLong1).pxWidthSm
; +28...? 16+3*4? / 16=scrollbarwidth? NO
        xLong2 = xSearch(xLong1)
        If xLong2 < PLCount And Not xLong2 < -1
          If SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETSEL, xLong1, 0) > 0 
CompilerIf #BoldDirs = 98
            X1 = 24
            If (PLI(xLong2)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
            X1 = 24
            If (PLIDF(xLong2) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
              If PLIconFolder
                X1 - 20
                EndIf
              ElseIf PLIconFile
              X1 - 20
              EndIf
        
        
              xLong1 = lParam & $FFFF
CompilerIf #BoldDirs = 98
              If xLong1 >= X1 And xLong1 <= X1 + PLI(xLong2)\pxWidthLg
CompilerElse
              If xLong1 >= X1 And xLong1 <= X1 + PLIPxLg(xLong2)
CompilerEndIf
                xResult = #True
                EndIf
            EndIf
          EndIf
        EndIf
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_PlayListDoubleClickEvent()
  If IsTickTimeElapsedMS(xGUIClickDelayTimer, 200)
    xGUIClickDelayTimer = GetTickTimeMS()
    MainForm_MenuEventPlaylist(PlDClickAction)
    EndIf
  EndProcedure

Procedure MainForm_TryFindKeyEvent(xKeyToFind.i)
  Define.i xLong1

  For xLong1 = 0 To #KbdSplitP
    If xKey(xLong1) = xKeyToFind
      MainForm_ProcessKey(xLong1)
      Break
      EndIf
    Next
  EndProcedure

Procedure MainForm_TryFindKeyEventWParam(wParam.i)
  MainForm_TryFindKeyEvent(((wParam & $60) >> 5) + 4 + ((wParam & $C) << 6))
  EndProcedure

Procedure.i QueryUnload()
  Define.i xResult

  If Not (PlayerIsLocked Or xAutoDoing Or IsInSpectrumxTimer1 Or xTimer2)
    Select xCmdQuitMode
      Case 0 ;NoQuit
      Case 1 ;ShutDown
        PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 2)
      Case 2 ;Shell
        ExitWindowsDialog(MainHWnd)
      Case 3 ;Standart/Quit
        xResult = #True
      Case 4 ;hibernate
        PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 4)
      Case 5 ;standby
        PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 5)
      EndSelect
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_HideIRWin()
  If ShowIRWin
    ShowWindow_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 0)
    xCalaymClassAlign = -1
    KillTimer_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 3)
    ShowIRWin = #False
    EndIf
  EndProcedure

Procedure MainForm_RestoreScheme()
  If Not *SoundSchemePointer
    *SoundSchemePointer = SoundSchemes_ReadAll(#CalaymBackupSchemeREGName)
    EndIf
  If *SoundSchemePointer
    If SoundSchemes_Write(*SoundSchemePointer, ".Current", "")
      SoundSchemes_ClearAll(#CalaymBackupSchemeREGName, #True)
      EndIf
    SoundSchemes_Discard(*SoundSchemePointer)
    *SoundSchemePointer = 0
    EndIf
  EndProcedure

Procedure TestRestoreReg(ForceRemove.i)
  Define.i xLong1
  Define.i xBool1
  Define.s xChar1

  CompilerIf #UseFileLogging
    If Reg_IsAutoRun
      MainForm_ctConsoleA_AddLog("CheckRegSet: 1")
      Else
      MainForm_ctConsoleA_AddLog("CheckRegSet: 0")
      EndIf
    CompilerEndIf
  If Reg_IsAutoRun
    ElseIf *SoundSchemePointer Or Not SoundSchemePointerMode = 0
    xBool1 = #True
    Else
    For xLong1 = 0 To 2
      If RegFolderMode(xLong1)
        xBool1 = #True
        EndIf
      Next
    EndIf
    
  If (xBool1 XOr NeedRestoreReg) Or ForceRemove
    NeedRestoreReg = xBool1
    If NeedRestoreReg And Not ForceRemove
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("RestoreRegSet")
        CompilerEndIf
      xChar1 = "Software\Microsoft\Windows\CurrentVersion\RunOnce"
      If RegCreateKeyEx_($80000002, @xChar1, 0, 0, 0, 2, 0, @xLong1, *ptrTemp)
        xChar1 = Chr(34) + xRealBaseFile + "exe" + Chr(34) + " /RESTOREREG"
        RegSetValueEx_String(xLong1, LoadResString(3501), xChar1)
        RegCloseKey_(xLong1)
        EndIf
      Else
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("RestoreRegRemove")
        CompilerEndIf
      xChar1 = "Software\Microsoft\Windows\CurrentVersion\RunOnce"
      If RegOpenKeyEx_($80000002, @xChar1, 0, 2, @xLong1)
        xChar1 = LoadResString(3501)
        RegDeleteValue_(xLong1, @xChar1)
        RegCloseKey_(xLong1)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_SetAutoDirs(SetThem.i)
  Define.i xLong1

  If SetThem
    If xAutoRefreshTimer(1) > 0
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Adding autorefresh monitor items")
        CompilerEndIf
      For xLong1 = 0 To xAutoDirCount - 1
        xAutoDirHWnd(xLong1) = FindFirstChangeNotification_(@xAutoDir(xLong1), 1, 3)
        ; + FILE_NOTIFY_CHANGE_DIR_NAME
        Next
      xAutoDirHWndCount = xAutoDirCount
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Added " + StrU(xAutoDirHWndCount) + " autorefresh monitor items")
        CompilerEndIf
      EndIf
    Else
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Removing autorefresh monitor items")
      CompilerEndIf
    For xLong1 = 0 To xAutoDirHWndCount - 1
      If Not xAutoDirHWnd(xLong1) = 0
        FindCloseChangeNotification_(xAutoDirHWnd(xLong1))
        EndIf
      Next
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Removed " + StrU(xAutoDirHWndCount) + " autorefresh monitor items")
      CompilerEndIf
    xAutoDirHWndCount = 0
    EndIf
  EndProcedure

Procedure MainForm_xEndSong(CanFadeOut.i, NotCanFadeOuts.i, ForceFadeOut.i, SlowFadeout.i)
  TrackerLoop = #False

  If NotCanFadeOuts
    CanFadeOut = #False
    EndIf

CompilerIf #UseFileLogging
  If CurMusic = #ctSSLayer_MusicTypeNone
    MainForm_ctConsoleA_AddLog("### Error 6310: xEndSong without music")
    MessageBox_(MainHWnd, @"### Error 6310: xEndSong without music", 0, 0)
    Else
CompilerElse
  If Not CurMusic = #ctSSLayer_MusicTypeNone
CompilerEndIf
    If CanFadeOut And (xGenFading Or ForceFadeOut) And Not xPStateIconPaused ;Or Not (Tear_StepT(CurrentSongID) = 0)
      If SlowFadeout
        If Not QuitMode = 0
          Tear_StartDropping(CurrentSongID, xSongIsMidi, 1, 0, #LongFadingTotalTimeShut, 0)
          Else
          Tear_StartDropping(CurrentSongID, xSongIsMidi, 1, 0, #LongFadingTotalTimeQuit, 0)
          EndIf
        Else
        Tear_StartDropping(CurrentSongID, xSongIsMidi, 1, 0, #SimpleFadingTotalTime, 0)
        EndIf
      Else
      AllTears_Types(Tear_Type(CurrentSongID)) = AllTears_Types(Tear_Type(CurrentSongID)) + 1
      Tear_Dropped(CurrentSongID)
      ctSSLayer_UnloadSong(SongPointer(CurrentSongID))
      ;SongPointer(CurrentSongID) = 0
      EndIf
    
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Sound stopped")
      CompilerEndIf
      
    EndIf

  ClearOldSongInfo()
  
  
  
  CurMusic = #ctSSLayer_MusicTypeNone
  DrawWhiteDC(xStaticIconsHWnd(#xStaticIcons_CurSong), xListHWnd(1), 0, #True)
  MainForm_RedrawPosition()
  
  xPStateIconPaused = #False
  xEndSongTimerEventTime = -1
  MainForm_UpdateMainIcon()
  
  EndProcedure

Procedure MainForm_UnloadP()
  Define.i xResult
  Define.i xLong1
  CompilerIf #UseFileLogging
    Define.i xMyTimer1
    CompilerEndIf


  If Not xInfoQuit
    ;MainForm_UnloadP = #True
    xInfoQuit = #True
    MainForm_LockMe(#True)
    FinalTimersDisabled = #True
    xTimerIsEnabled = #False
    MainForm_HideIRWin()
    
    MainForm_RestoreScheme()
    UpdateFolderReg(#False)
    TestRestoreReg(#True)
    
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Killing timers and virtual window")
      CompilerEndIf
    MainForm_DesireSpectrumState(#False, #True)
    If Not LEDMode = 0
      KillTimer_(MainHWnd, 0)
      LEDState = $2 ;$1?
      SpectrumProcKb(0, 0, 0, 0)
      EndIf
    MainForm_SetAutoDirs(#False)
    If Not xFindNtfy = 0
      FindCloseChangeNotification_(xFindNtfy)
      xFindNtfy = 0
      EndIf
    KillTimer_(MainHWnd, 1)
    KillTimer_(MainHWnd, 4)
    
    CompilerIf #UseFileLogging
      If QuitMode = 1
        MainForm_ctConsoleA_AddLog("Unloading player, preparing to shut down")
        Else
        MainForm_ctConsoleA_AddLog("Unloading player")
        EndIf
      CompilerEndIf
    xPStateIconQuit = #True
    xTimerIsEnabled = #False
    EnableWindow_(MainHWnd, 0)
    MainForm_UpdateMainIcon()
    CompilerIf Not #FailSaveTest
      If xCmdSaveSet
        MainForm_SaveSettings(0, #False)
        EndIf
      CompilerEndIf
    If GlobalKeys
      GlobalKeys = #False
      MainForm_SetGlobalKeys(#False)
      EndIf
    xTimerIsEnabled = #False
    If Not (xSecureMode Or vKioskMode)
      CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
        HtmlHelpClose()
        CompilerElse
        If xUseChmHelp
          HtmlHelpClose()
          Else
          WinHelp(MainHWnd, xRealBaseFile + "hlp", $2, 0)
          EndIf
        CompilerEndIf
      EndIf
    DoEvents()
    
    
    If Not xTrayIconIndicator
      ShowWindow_(MainHWnd, 6)
      EndIf
    
    DoEvents()
    DoEvents()
    If FindString(CommandX, "/SAVE") Or (xNoSaveListMenu = 0 And Not vKioskMode)
      PLWriter_Save(AppBase_GetByExt(#DefaultPLExtension), #False)
      EndIf
    If Not CurMusic = #ctSSLayer_MusicTypeNone
      MainForm_xEndSong(xPStateIconPlaying, xPStateIconPaused, #False, #True)
      EndIf
    DoEvents()
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("PreTearResults: " + Hex(AllTears_TypesCount) + ": " + Hex(AllTears_Types(0)) + "-" + Hex(AllTears_Types(1)) + "-" + Hex(AllTears_Types(2)))
      CompilerEndIf
    Tear_WaitFor(-2)
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("PostTearResults: " + Hex(AllTears_TypesCount) + ": " + Hex(AllTears_Types(0)) + "-" + Hex(AllTears_Types(1)) + "-" + Hex(AllTears_Types(2)))
      CompilerEndIf
    CompilerIf #UseFileLogging

      MainForm_ctConsoleA_AddLog("Pre-Freeing memory...")
      xMyTimer1 = GetTickTimeMS()
      CompilerEndIf
    If OLEDropMemory
      BinaryBuffer_Discard(OLEDropMemory)
      OLEDropMemory = 0
      EndIf
    CompilerIf #BoldDirs = 98
      Dim PLI(0)
      CompilerElse
      Dim PLIFile(0)
      Dim PLICap(0)
      Dim PLIDF(0)
      Dim PLIPxLg(0)
      Dim PLIPxSm(0)
      CompilerEndIf
    Dim xDirPath(0)
    Dim sCharA1(0)
    Dim ReadDirectory_xArrayS(0)
;compilerendif
    
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("  done in " + Str(GetElapsedTickTimeMS(xMyTimer1)) + " ms (maximum used index: " + StrU(PLClearCounter) + ")")
      CompilerEndIf
    ;Close 1
    ctSSLayer_Close(0)
    ctSSLayer_UnLoadVB()
    
    If Not vKioskMode
      ;RevokeDragDrop_(MainHWnd)
      DragAcceptFiles_(MainHWnd, #False)
      ;DragClass\Release()
      EndIf
    
    CompilerIf #FlatCastCF17
      Set xFCI = Nothing
      CompilerEndIf
    
    DoEvents()
    If QuitMode = 1
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Sending ShutDown signal")
        CompilerEndIf
      ShutdownWindowsEx(#SDWE_Shutdown)
      EndIf
    EndIf
  
  If Not SoundSchemePointerMode = 0
    MainForm_RestoreScheme()
    EndIf
  
  If FindString(CommandX, "/NOTASKMGR") And FindString(CommandX, "/NOTASKMGR!") = 0
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Activating task manager")
      CompilerEndIf
    SystemParametersInfo_(#SPI_SETSCREENSAVERRUNNING, #False, 1, 0)
    EndIf
  
  
  
  
  xTrayIconEnabled = #False
  xTrayIconVisible = #False
  MainForm_ShowTray(#True)
  
  DestroyPlayerForm()
  For xLong1 = 1 To #xMenuCountX
    If Not xMenu(xLong1) = 0
      DestroyMenu_(xMenu(xLong1))
      EndIf
    If Not xPopupMenu(xLong1) = 0
      DestroyMenu_(xPopupMenu(xLong1))
      EndIf
    Next
  
  CompilerIf #LoadShellDriveIcons
    For xLong1 = 0 To 2
      If Not ShellDrvIcons(xLong1) = 0
        ;DeleteObject_(ShellDrvIcons(xLong1))
        DestroyIcon_(ShellDrvIcons(xLong1))
        EndIf
      Next
    CompilerEndIf
  
  If OLEDropMemory
    BinaryBuffer_Discard(OLEDropMemory)
    OLEDropMemory = 0
    EndIf
  
  If Not LEDMode = 0
    KillTimer_(MainHWnd, 0)
    LEDState = $1 ;$1?
    SpectrumProcKb(0, 0, 0, 0)
    EndIf

  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Unbinding language file (if required)")
    CompilerEndIf
  ;LoadResEx_SetLanguageFile
  ;LoadResEx_SetThemeFile

  DoEvents()
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Unloading main form finished, should now terminate (Quitting finished)")
    CompilerEndIf

  If IsMessageing
    PostQuitMessage_(0)
    EndIf
  ;ApplicationClose
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_UnloadPlayer()
  If QueryUnload()
    MainForm_UnloadP()
    EndIf
  EndProcedure

Procedure MainForm_ResizePlayer(SimpleResize.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.i xBool1
  Define.RECT xType1
  Define.i SimpleResizeNoPos
  
  If SimpleResize
    SimpleResizeNoPos = $2
    EndIf
  
  GetClientRect_(MainHWnd, xType1)
  
  DoEvents()
  
  
  
  If IsIconic_(MainHWnd)
    MainForm_DesireSpectrumState(#False, #False)
    If xTrayIconEnabled
      ShowWindow_(MainHWnd, 0)
      xTrayIconIndicator = #True
      MainForm_ShowTray(#False)
      EndIf
    Else
    MainForm_DesireSpectrumState(#True, #False)
    
    xLong1 = xType1\Right ;Me.ScaleWidth
    If xLong1 < 0
      xLong1 = 0
      EndIf
    xLong4 = xLong1 - ScrollComboWidth ;eImage0Width
    If xLong4 < 0
      xLong4 = 0
      EndIf
    
    xLong2 = xType1\Bottom
    If xLong2 < 0
      xLong2 = 0
      EndIf
    ;TrDeferWindowPos(MainForm_hwnd, 0, 0, 0, xType1\Right, xLong2 - PanelSizeNow, $216)
    
    If InterfaceMode = #Interface_Mode_Search Or InterfaceMode = #Interface_Mode_Radio
      xLong3 = 160 * DPIScaleY
      Else
      xLong3 = 96 * DPIScaleY
      EndIf
    If MP3GetID3Tag
      If xLong2 < xLong3 + PanelSizeTags
        PanelSizeNow = PanelSizeDef
        Else
        PanelSizeNow = PanelSizeTags
        EndIf
      ;Else
      ;PanelSizeNow = PanelSizeDef
      EndIf
    xLong2 = xLong2 - PanelSizeNow
    If (xLong2 < xDefCtlHeight16 + eSPTopY)
      xBool1 = #True
      EndIf
    
    TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_BAR), 0, 0, xLong2, xType1\Right, PanelSizeNow, $214)
    ;xLong2 = xLong2 - PanelSizeNow
    If xLong2 < 0
      xLong2 = 0
      EndIf
    xLong3 = ((xLong2 + xDefCtlHeight16) * 2) / 3
    TrDeferWindowPos(xListHWnd(1), 0, 0, xLong2 - xLong3, xLong4, xLong3, $214)
    Select InterfaceMode
      Case #Interface_Mode_Search
        SearchForm_Resize(xLong1, xLong2 - eSPTopY, eSPTopY)    ;* 0.8, 25;xLong2 * 0.1
        TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, xLong1 - AnimExtraPadding, xDefCtlHeight16 + eSPTopY + 34, 0, 0, $215)
      Case #Interface_Mode_Timer
        TimerListForm_Resize(xLong1, xLong2 - eSPTopY, eSPTopY)
        TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, xLong1 - AnimExtraPadding, eSPTopY + 54, 0, 0, $215)
      Case #Interface_Mode_Radio
        RadioForm_Resize(xLong1, xLong2 - eSPTopY, eSPTopY)
        TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, xLong1 - AnimExtraPadding, eSPTopY + 54, 0, 0, $215)
      Case #Interface_Mode_Wizard
        WizardForm_Resize(xLong1, xLong2 - eSPTopY, 0)
        TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, xLong1 - AnimExtraPadding, eSPTopY + 16, 0, 0, $215)
      Default
        If xDirListModeCur = 1
          xLong2 = xLong2 - eSPTopY * 2
          xLong3 = (xLong2 * xDirListTopHeight) / #xDirListDivTH
          If xLong3 < 0
            xLong3 = 0
            EndIf
          TrDeferWindowPos(xListHWnd(0), 0, 0, 0, xLong1, xLong3, $214 | SimpleResizeNoPos)
          SplitterMoveTopOrLeftPos = xLong3
          TrDeferWindowPos(HWndSplitterTH, 0, 0, SplitterMoveTopOrLeftPos, xLong1, eSPTopY, $214)
          TrDeferWindowPos(HWndSplitterMoveTH, 0, 0, SplitterMoveTopOrLeftPos, xLong1, eSPTopY, $214)
          xLong2 = xLong2 - xLong3
          If xLong2 < 0
            xLong2 = 0
            EndIf
          TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, xLong1 - AnimExtraPadding, xLong3 + eSPTopY + 8 * DPIScaleY, 0, 0, $215)
          TrDeferWindowPos(xListHWnd(2), 0, 0, xLong3 + eSPTopY, xLong1, xLong2, $214)
          ElseIf xDirListModeCur = 2
          xLong2 = xLong2 - eSPTopY ;* 2
          If xLong2 < 0
            xLong2 = 0
            EndIf
          xLong3 = xLong1 - eSPTopX
          xLong3 = (xLong3 * xDirListLeftWidth) / #xDirListDivLW
          If xLong3 < 0
            xLong3 = 0
            EndIf
          TrDeferWindowPos(xListHWnd(0), 0, 0, 0, xLong3, xLong2, $214 | SimpleResizeNoPos)
          SplitterMoveTopOrLeftPos = xLong3
          TrDeferWindowPos(HWndSplitterLW, 0, xLong3, 0, eSPTopX, xLong2, $214)
          TrDeferWindowPos(HWndSplitterMoveLW, 0, xLong3, 0, eSPTopX, xLong2, $214)
          xLong3 = xLong3 + eSPTopX
          xLong4 = xLong1 - xLong3
          If xLong4 < 0
            xLong4 = 0
            EndIf
          TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, xLong1 - AnimExtraPadding, 8 * DPIScaleY, 0, 0, $215)
          TrDeferWindowPos(xListHWnd(2), 0, xLong3, 0, xLong4, xLong2, $214)
          Else
          TrDeferWindowPos(xListHWnd(0), 0, 0, xDefCtlHeight16, xLong4, xLong3, $216)
          xLong2 = xLong2 - xDefCtlHeight16 - eSPTopY * 2
          If xLong2 < 0
            xLong2 = 0
            EndIf
          SplitterMoveTopOrLeftPos = xDefCtlHeight16
          If xBool1 Or xLong2 < 48
            TrDeferWindowPos(HWndSplitterTH, 0, 0, -SplitterMoveTopOrLeftPos, xLong1, eSPTopY, $214 | SimpleResizeNoPos)
            TrDeferWindowPos(HWndSplitterMoveTH, 0, 0, -SplitterMoveTopOrLeftPos, xLong1, eSPTopY, $214 | SimpleResizeNoPos)
            Else
            TrDeferWindowPos(HWndSplitterTH, 0, 0, SplitterMoveTopOrLeftPos, xLong1, eSPTopY, $214 | SimpleResizeNoPos)
            TrDeferWindowPos(HWndSplitterMoveTH, 0, 0, SplitterMoveTopOrLeftPos, xLong1, eSPTopY, $214 | SimpleResizeNoPos)
            EndIf
          TrDeferWindowPos(xListHWnd(2), 0, 0, xDefCtlHeight16 + eSPTopY, xLong1, xLong2, $214 | SimpleResizeNoPos)
          ;If InterfaceMode = #Interface_Mode_search
          ;  TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, xLong1 - AnimExtraPadding, xLong3 + eSPTop + 12 + 20, 0, 0, $215)
          ;  Else
            TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, xLong1 - AnimExtraPadding, xDefCtlHeight16 + eSPTopY + 8 * DPIScaleY, 0, 0, $215)
            TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_DirList), 0, 0, 0, xLong1, xDefCtlHeight16, $214 | SimpleResizeNoPos)
          ;  endif
          EndIf
        lPlayList_Height = xLong2
      EndSelect
    
    
    TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_CurSongPos), 0, 0, 24, xLong1, CurSongPosRealHeight, $216)
    ;MainForm_ePic(1).Width = xLong1
    SongPosScrollWidth = xLong1 ;MainForm_ePic(1).Width ;ScaleWidth
    If SongPosScrollWidth = 0
      SongPosScrollWidth = 1
      EndIf
;debug vKioskMode, MP3GetID3Tag, xLong1, xStaticIconsHWnd(#xStaticIcons_Tags), SpectrumWidth
    If vKioskMode
      If MP3GetID3Tag
        ;If SpectrumHeight > xDefCtlHeight16 + xDefHeight16
          ;xLong2 = SpectrumHeight
          ;Else
          ;xLong2 = xDefCtlHeight16 + xDefHeight16
          ;endif
        xLong3 = xLong1 - SpectrumWidth
        If xLong3 < SpectrumMinLeft
          xLong3 = SpectrumMinLeft
          EndIf
        ;TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Tags), 0, 0, 48, xLong3 - eSPTopX, xLong2, $216)
        TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Tags), 0, 0, 48, xLong3 - eSPTopX, xTagBoxHeight, $216)
        EndIf
      Else
      ;TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Tags), 0, 0, 48, xLong1, xDefCtlHeight16 + xDefHeight16, $216)
      TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Tags), 0, 0, 48, xLong1, xTagBoxHeight, $216)
      xLong3 = (xLong1 - SpectrumWidth + SpectrumMinLeft) / 2
      If xLong3 < SpectrumMinLeft
        xLong3 = SpectrumMinLeft
        EndIf
      EndIf
    TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Spectrum), 0, xLong3, SpectrumTop, SpectrumWidth, SpectrumHeight, $215)
    TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0, 0, xLong1, xDefCtlHeight16, $216)
    EndIf
;  UpdateWindow MainHWnd
  CompilerIf #HowToDeferWindowPos
    TrEndDeferWindowPos
    CompilerEndIf
;  Stop
  EndProcedure

Procedure MainForm_IconsMouseUpByHWnd(hWnd.i) ;, lParam.i)
  Define.i Index

  For Index = 0 To #xStaticIcons_Last
    If xStaticIconsHWnd(Index) = hWnd
      Select Index
        Case #xStaticIcons_Def0 To #xStaticIcons_Def5, #xStaticIcons_RepMode
          MainForm_IconsMouseUp(Index)
        EndSelect
      Break
      EndIf
    Next
  EndProcedure

Procedure SaveOpenURL(xURL.s)
  Define.i xLong1
  
  If Len(xURL) And UrlsAllowed
    xLong1 = FindString(xURL, "://")
    If xLong1
      Select LCase(Left(xURL, xLong1 - 1))
        Case "http", "https", "ftp"
          ;xLong1 = #True
        Default
          xLong1 = #False
        EndSelect
      Else
      xURL = "http://" + xURL
      xLong1 = #True
      EndIf
    If xLong1
      If Not ShellExecute_(MainHWnd, @"Open", @xURL, 0, 0, 5)
        SetUnicodeClipboard(xURL)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure SplitterMoveTH(y.i)
  Define.i xLong1
  Define.RECT xType1
  
  y = y + SplitterMoveTopOrLeftPos
  GetClientRect_(MainHWnd, xType1)
  xLong1 = xType1\Bottom - PanelSizeNow - eSPTopY * 2
  If xLong1 < 1
    xLong1 = 1
    EndIf
  If y > xDefCtlHeight16
    SplitterPreResult = (y * #xDirListDivTH) / xLong1
    If SplitterPreResult < #xDirListMinTH
      SplitterPreResult = -1
      ElseIf SplitterPreResult > #xDirListMaxTH
      SplitterPreResult = #xDirListMaxTH
      EndIf
    Else
    SplitterPreResult = -1
    EndIf
  If SplitterPreResult > 0
    If SplitterPreResult > #xDirListMaxTH
      SplitterPreResult = #xDirListMaxTH
      EndIf
    xLong1 = (xLong1 * SplitterPreResult) / #xDirListDivTH
    If xLong1 < 0
      xLong1 = 0
      EndIf
    Else
    xLong1 = xDefCtlHeight16
    EndIf
  SetWindowPos_(HWndSplitterMoveTH, 0, 0, xLong1, 0, 0, $215)
  EndProcedure

Procedure SplitterMoveLW(x.i)
  Define.i xLong1
  Define.RECT xType1

  ;If x & $8000
  ;  x = $FFFF8000 | (x & $7FFF)
  ;  EndIf
  x = x + SplitterMoveTopOrLeftPos
  GetClientRect_(MainHWnd, xType1)
  xLong1 = xType1\Right - eSPTopY ;- PanelSizeNow - eSPTopY * 2
  If xLong1 < 1
    xLong1 = 1
    EndIf
  SplitterPreResult = (x * #xDirListDivLW) / xLong1
  If SplitterPreResult < #xDirListMinLW
    SplitterPreResult = #xDirListMinLW
    ElseIf SplitterPreResult > #xDirListMaxLW
    SplitterPreResult = #xDirListMaxLW
    EndIf
  xLong1 = (xLong1 * SplitterPreResult) / #xDirListDivLW
  If xLong1 < 0
    xLong1 = 0
    EndIf
  
  SetWindowPos_(HWndSplitterMoveLW, 0, xLong1, 0, 0, 0, $215)
  EndProcedure

Procedure MainForm_xPauseClick()
  If Not (PlayerIsLocked Or xAutoDoing)
    If xPStateIconPlaying
      MainForm_LockMe(#True)
      If xPStateIconPaused
        xPStateIconPaused = #False
        MainForm_UpdateMainIcon()
        ForceLoudestTear = CurrentSongID
        ShowIRI()
        If xGenFading Or Not Tear_StepT(CurrentSongID) = 0
          If Tear_StepT(CurrentSongID) = 0
            Tear_Volume(CurrentSongID) = 0
            ctSSLayer_SetVolume(SongPointer(CurrentSongID), 0)
            ctSSLayer_SetPause(SongPointer(CurrentSongID), #False)
            EndIf
          Tear_StartDropping(CurrentSongID, xSongIsMidi, 12, 0, #SimpleFadingTotalTime, 1)
          Else
          ctSSLayer_SetVolume(SongPointer(CurrentSongID), xSetVolume)
          ctSSLayer_SetPause(SongPointer(CurrentSongID), #False)
          Tear_Volume(CurrentSongID) = 1
          EndIf
        xEndSongTimerEventTime = GetTickTimeMS()
        LastPosTime = xEndSongTimerEventTime
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("Sound unpaused")
          CompilerEndIf
        Else
        xEndSongTimerEventTime = -1
        xPStateIconPaused = #True
        MainForm_UpdateMainIcon()
        
        If xGenFading Or Not Tear_StepT(CurrentSongID) = 0
          If Tear_StepT(CurrentSongID) = 0
            Tear_Volume(CurrentSongID) = 1
            EndIf
          Tear_StartDropping(CurrentSongID, xSongIsMidi, 2, 0, #SimpleFadingTotalTime, 0)
          ;If xGenFading 
          ;  DoFading -1
          ;  endif
          Else
          ctSSLayer_SetPause(SongPointer(CurrentSongID), #True)
          Tear_Volume(CurrentSongID) = 0
          EndIf
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("Sound paused")
          CompilerEndIf
        EndIf
      MainForm_LockMe(#False)
      Else
      If xPStateIconPaused
        xPStateIconPaused = #False
        MainForm_UpdateMainIcon()
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure GetOptimalPLMaxCount()
  CompilerIf #UseFileLogging
    Static xSecondRun.i
    CompilerEndIf
  CompilerIf #PB_Compiler_Unicode
    Define.MEMORYSTATUSEX xType1
    Define.MEMORYSTATUS xType2
  
    xType1\dwLength = SizeOf(MEMORYSTATUSEX)
    PLCountMax = GlobalMemoryStatusEx(@xType1)
    If PLCountMax
      If xType1\ullTotalPhys & $ffffffff80000000
        PLCountMax = $7FFFFFFF ; sign limit, decreased later
        Else
        PLCountMax = xType1\ullTotalPhys
        EndIf
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  Total physical memory: " + SizeToXiBString(xType1\ullTotalPhys))
        CompilerEndIf
      Else
      GlobalMemoryStatus_(@xType2)
      If xType2\dwTotalPhys & $80000000
        PLCountMax = $7FFFFFFF
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  more than 2 GiB total")
          CompilerEndIf
        Else
        PLCountMax = xType2\dwTotalPhys
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  total Physical: " + SizeToXiBString(xType2\dwTotalPhys))
          CompilerEndIf
        EndIf
      EndIf
    PLCountMax = PLCountMax / 256 / #PLISize ;len PLI
    CompilerEndIf
    
  If PLCountMax < #PLCountMax95
    PLCountMax = #PLCountMax95
    ElseIf PLCountMax & $80000000
    PLCountMax = $7ffffff0
    ElseIf PLCountMax > $7ffffff0
    PLCountMax = $7ffffff0
    EndIf
  CompilerIf #UseFileLogging
    If xSecondRun
      PLCountMax = xSecondRun
      Else
      xSecondRun = PLCountMax
      EndIf
    CompilerIf #PB_Compiler_Unicode
      MainForm_ctConsoleA_AddLog("  Real array size: " + StrU(PLCountMax))
      CompilerElse
      MainForm_ctConsoleA_AddLog("Windows 9x / ansi, fixed array size (" + StrU(PLCountMax) + ")")
      CompilerEndIf
    CompilerEndIf
  PLCountWarn = PLCountMax * 0.925
  EndProcedure

Procedure.i PrevInstanceEx(xChar1.s)
  Define.i xResult
  Define.i xLong1
  ;define.i xLong2
  Define.COPYDATASTRUCT cds
  
  xLong1 = FindWindow_(#CalaymClassNameMsg, #CalaymClassTitleMsg)
  If Not xLong1 = 0
    xChar1 = FilteredCMD(xChar1)
    cds\cbData = Len(xChar1) << 1
    If cds\cbData
      cds\lpData = LocalAlloc_(0, cds\cbData + 2)
      If cds\lpData
        RtlMoveMemory_(cds\lpData, @xChar1, cds\cbData)
        PokeW(cds\lpData + cds\cbData, 0)
        SendMessage_(xLong1, $4A, 0, @cds)
        LocalFree_(cds\lpData)
        EndIf
      Else
      SendMessage_(xLong1, $111, 600, 0)
      EndIf
    xResult = #True
    EndIf
  ProcedureReturn xResult
  EndProcedure

CompilerIf #UseFileLogging
  Procedure SSDebuggerCB(*StrAW, Flags.i)
    ;If Flags & $10
      If Flags & 1
        MainForm_ctConsoleA_AddLog("  " + PeekS(*StrAW))
        Else
        MainForm_ctConsoleA_AddLog("ctSSLay: " + PeekS(*StrAW))
        EndIf
      ;EndIf
    EndProcedure
  CompilerEndIf

Procedure.i SSMultiLoader()
  Define.i xResult
  Define.i xLong1

  
  xResult = ctSSLayer_LoadVB(xRealBaseFile + "lay")
  If xResult < 1
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
      xLong1 = ctSSLayer_LoadVB("ctssly64.dll")
      CompilerElse
      xLong1 = ctSSLayer_LoadVB("ctssly32.dll")
      CompilerEndIf
    If xLong1 = -1
      xResult = -1
      CompilerIf Not #PB_Compiler_Processor = #PB_Processor_x64
        xLong1 = 0
        CompilerEndIf
      ElseIf xLong1
      xResult = xLong1
      EndIf
    If Not xResult
#DONT_RESOLVE_DLL_REFERENCE = 1
      xResult = LoadLibraryEx_(xRealBaseFile + "lay", 0, #DONT_RESOLVE_DLL_REFERENCE | #LOAD_LIBRARY_AS_DATAFILE)
      If Not xResult
        CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
          xResult = LoadLibraryEx_("ctssly64.dll", 0, #DONT_RESOLVE_DLL_REFERENCE | #LOAD_LIBRARY_AS_DATAFILE)
          CompilerElse
          xResult = LoadLibraryEx_("ctssly32.dll", 0, #DONT_RESOLVE_DLL_REFERENCE | #LOAD_LIBRARY_AS_DATAFILE)
          If Not xResult
            xResult = LoadLibraryEx_("ctsslay.dll", 0, #DONT_RESOLVE_DLL_REFERENCE | #LOAD_LIBRARY_AS_DATAFILE)
            EndIf
          CompilerEndIf
        EndIf
      If xResult
        FreeLibrary_(xResult)
        xResult = -2
        EndIf
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure ErMustQuit()
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  quitting")
    CompilerEndIf
  xInfoQuit = #True
  DoEvents()
  MainForm_UnloadP()
  ;UnloadP
  ;ProcedureReturn!!!!!!
  EndProcedure

Procedure ErMustQuit2()
  xInfoQuit = #True
  ;ProcedureReturn!!!!!!
  EndProcedure


Procedure InitOutOfSession()
  Define.i xLong1

  OutOfSession_MySessionID = -1
  xLong1 = GetModuleHandle_(@"kernel32.dll")
  If xLong1
    xLong1 = GetProcAddress(xLong1, "ProcessIdToSessionId")
    If xLong1
      If CallFunctionFast(xLong1, GetCurrentProcessId_(), @OutOfSession_MySessionID)
        OutOfSession_MySessionID & $ffffffff
        Else
        OutOfSession_MySessionID = -1
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure.i WTSGetActiveConsoleSessionId(*Value)
  Define.i xResult

  xResult = GetModuleHandle_(@"kernel32.dll")
  If xResult
    xResult = GetProcAddress(xResult, "WTSGetActiveConsoleSessionId")
    If xResult
      PokeI(*Value, CallFunctionFast(xResult) & $ffffffff)
      xResult = #True
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.i NotOutOfSession()
  Define.i xLong1
  
  If WTSGetActiveConsoleSessionId(@xLong1)
;Debug "SessionID: "+Str(xLong1) + ", MySession: " + Str(OutOfSession_MySessionID)
    If Not xLong1 = -1
      If xLong1 = OutOfSession_MySessionID
        NotOutOfSessionOld = #True
        Else
        NotOutOfSessionOld = #False
        EndIf
      EndIf
    xLong1 = NotOutOfSessionOld
    Else
    xLong1 = #True
    NotOutOfSessionOld = #True
    EndIf
  ProcedureReturn xLong1
  EndProcedure

Procedure RePosWindow()
  Define.RECT xType1
  
  If xMWinPos\Right = -1 Or xMWinPos\Bottom = -1
    GetWindowRect_(GetDesktopWindow_(), @xType1)
    xMWinPos\Right = (xType1\Right - xType1\left) >> 1
    xMWinPos\Bottom = ((xType1\Bottom - xType1\Top) * 3) >> 2 ; /4
    xMWinPos\left = xType1\left + (xType1\Right - xType1\left - xMWinPos\Right) >> 1
    xMWinPos\Top = xType1\Top + (xType1\Bottom - xType1\Top - xMWinPos\Bottom) >> 1
    SetWindowPos_(MainHWnd, 0, xMWinPos\left, xMWinPos\Top, xMWinPos\Right, xMWinPos\Bottom, $214)
    Else
    CheckValidScreen(#False)
    EndIf
  EndProcedure

Procedure GetIsAutoRun()
  Define.i xLong1
  Define.s xChar1
  
  Reg_IsAutoRun = #False
  If RegOpenKeyEx_($80000001, @"Software\Microsoft\Windows\CurrentVersion\Run", 0, 1, @xLong1)
    xChar1 = LoadResString(3500)
    xChar1 = RegQueryValueEx_String(xLong1, @xChar1)
    If Len(xChar1)
      Reg_IsAutoRun = #True
      EndIf
    RegCloseKey_(xLong1)
    EndIf
  EndProcedure

Procedure MainForm_ApplyProcessMode()
  RadioApiMenu(330, 333, 330 + xProcessMode)
  
  If SoundSchemePointerMode = 2 Or (SoundSchemePointerMode = 1 And xProcessMode = 2)
    ;shouldquiet
    If Not *SoundSchemePointer
      *SoundSchemePointer = SoundSchemes_ReadAll(".Current")
      If *SoundSchemePointer
        If SoundSchemes_Write(*SoundSchemePointer, #CalaymBackupSchemeREGName, LoadResString(3579))
          SoundSchemes_ClearAll(".Current", #False)
          EndIf
        EndIf
      EndIf
    ElseIf *SoundSchemePointer
    ;shouldactivate
    MainForm_RestoreScheme()
    EndIf
  TestRestoreReg(#False)
  EndProcedure

Procedure SetPanelSize()
  Define.i xLong1
  
  If MP3GetID3Tag
    xLong1 = PanelSizeTags
    Else
    xLong1 = PanelSizeDef
    EndIf
  
  If Not xLong1 = PanelSizeNow
    PanelSizeNow = xLong1
    MainForm_ResizePlayer(#True)
    EndIf
  EndProcedure

Procedure CalcCrossFadeConsts()
  #CrossFadeOverlap = 80
  Define.i xLong1
  Define.i xLong2
  
  For xLong1 = 0 To #xFadeConstsX
    xLong2 = xLong1 + #xFadeConsts1
    CrossFadeTimeDelay(xLong1) = MulDiv_(xLong2 * 1000, (100 - #CrossFadeOverlap), 200)
    CrossFadeTimeSingle(xLong1) = xLong2 * 1000 - CrossFadeTimeDelay(xLong1)
      
    CrossFadeMinTime(xLong1) = xLong2 * 3000 + #CrossFadeWaitSeek + 5000 ; 12 - 66
    CrossFadeNewMinMinTime(xLong1) = CrossFadeTimeSingle(xLong1) * 2 + #CrossFadeWaitSeek + 4000
      CrossFadeMinRemainTime(xLong1) = CrossFadeTimeSingle(xLong1)
      CrossFadeMaxPos(xLong1) = xLong2 * 1000 + 1500
      CrossFadeMinPos(xLong1) = CrossFadeMaxPos(xLong1) + 2250 + xLong2 * 200 ; *200 = 1/5 -> 0.4 - 4 seks
      
    xLong2 = (xLong2 / 10)
    CrossFadeMinPatterns(xLong1) = 10 + xLong2
    CrossFadeNewMinMinPatterns(xLong1) = 3 + xLong2
      CrossFadeMaxPattern(xLong1) = 2 + xLong2
      CrossFadeMinPattern(xLong1) = 3 + xLong2
      CrossFadeMinRemainPatterns(xLong1) = 2 + xLong2
    Next
  EndProcedure

Procedure MainForm_ApplyRepMode()
  Define.i xBool1
  RadioApiMenu(110, 112, 110 + xRep)
  
  If xRep
    xBool1 = #True
    EndIf
  MainForm_EnableApiMenu(322, xBool1)
  MainForm_EnableApiMenu(119, xBool1)
  CheckApiMenu(119, IntroModeActive)
  
  If CurMusic = #ctSSLayer_MusicTypeTracker And Not xSongIsMidi
    If ((xRep = 0) And PlNextSong = "")
      xBool1 = #True
      Else
      xBool1 = #False
      EndIf
    ctSSLayer_UpdateLooping(SongPointer(CurrentSongID), xBool1)
    EndIf
  
  If IntroModeActive
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_RepMode, *DynButtonsResXRepBMP, DynButtonsResXRepLen, $10000000 + xRep * $1000000)
    Else
    MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_RepMode, *DynButtonsResXRepBMP, DynButtonsResXRepLen, xRep * $1000000)
    EndIf
  If IntroModeActive
    xBool1 = 1
    Else
    xBool1 = 0
    EndIf
  SetToolTip(#xStaticIcons_RepMode, ReplaceString(LoadResString(1160), "$", LoadResString(1162 + xRep * 2 + xBool1)), xModeTTText)
  EndProcedure

Procedure HandleSett(xChar1.s)
  Define.i xLong1
  Define.i xLong2
  Define.s xChar2

  Repeat
    xLong1 = FindString(xChar1, ",")
    If xLong1 = 0
      Break
      EndIf
    xChar2 = Left(xChar1, xLong1 - 1)
    Select xChar2
    ;sett
      Case "sng": xRep = 0: MainForm_ApplyRepMode()
      Case "all": xRep = 1: MainForm_ApplyRepMode()
      Case "rnd": xRep = 2: MainForm_ApplyRepMode()
      
      Case "ap0":
        If Not vKioskMode
          xAutoPlayback = #False
          xReAutoPlay = #False
          EndIf
      Case "ap1"
        If Not vKioskMode
          xAutoPlayback = #True
          xReAutoPlay = #True
          EndIf
      
      Case "fd0": xGenFading = #False
      Case "fd1": xGenFading = #True
      
      Case "nop": xProcessMode = 0: MainForm_ApplyProcessMode()
      Case "crf": xProcessMode = 1: MainForm_ApplyProcessMode()
      Case "mdm": xProcessMode = 2: MainForm_ApplyProcessMode()
      Case "stp": xProcessMode = 3: MainForm_ApplyProcessMode()
      
      Case "pds": PlDClickAction = 0
      Case "pde": PlDClickAction = 1
      Case "pdn": PlDClickAction = 2
      
      Case "rp0": xRemovePlayedSongs = #False
      Case "rp1": xRemovePlayedSongs = #True
      Case "rs0": xRemoveSkippedSongs = #False
      Case "rs1": xRemoveSkippedSongs = #True
      Case "rm0": xRemoveMissingSongs = #False
      Case "rm1": xRemoveMissingSongs = #True
      
      ; 3 kiosk extra settings:
      ;Case "msg"
      ;  If vKioskMode
      ;    xIRMode = 2
      ;    endif
      ;Case "vol"
      ;  If vKioskMode
      ;    vCanVolume = #True
      ;    EndIf
      
      Default
        If Left(xChar2, 3) = "vol"
          xLong2 = Val(Mid(xChar2, 4))
          If (xLong2 > 0 And Not xLong2 > 100) Or (xLong2 = 0 And xChar2 = "vol0")
            DoVolume(xLong2 * 2.55, #True)
            EndIf
          EndIf
        If Left(xChar2, 3) = "drl"
          xLong2 = Val(Mid(xChar2, 4))
          If xLong2 = 0 And xChar2 = "drl0"
            xDirListModeCur = 0
            xDirListModeSet = 0
            ElseIf Right(xChar2, 1) = "%"
            If Not (xLong2 < #xDirListMinLW Or xLong2 > #xDirListMaxLW)
              xDirListLeftWidth = Abs(xLong2)
              xDirListModeCur = 2
              xDirListModeSet = 2
              EndIf
            ElseIf Not (xLong2 < #xDirListMinTH Or xLong2 > #xDirListMaxTH)
            xDirListTopHeight = Abs(xLong2)
            xDirListModeCur = 1
            xDirListModeSet = 1
            EndIf
          EndIf
      EndSelect
    xChar1 = Mid(xChar1, xLong1 + 1)
    ForEver
  EndProcedure

Procedure MainForm_DropFiles(hDrop.i, lParamKeyStates.i) ;, Message.i, wParam0.i, lParamKeyStates.i)
  Define.i xCount
  Define.i xLong1
  Define.i hBuff
  Define.s xChar1
  Define.i xLong2


  
  ;Shift
  ;Shift = -CLng(IsShiftPressed)
  ;lParamKeyStates = (lParamKeyStates & 6) ; msshift 4 mkrbutton 2
  xCount = DragQueryFileCount(hDrop)
  If xCount
    If OLEDropMemory
      BinaryBuffer_Discard(OLEDropMemory)
      OLEDropMemory = 0
      EndIf
    hBuff = BinaryBuffer_Create()
    If hBuff
      BinaryBuffer_WriteMemEx(hBuff, 0, 4)
      xCount = xCount - 1
      BinaryBuffer_WriteMemEx(hBuff, @lParamKeyStates, 4)
      For xLong1 = 0 To xCount
        xChar1 = DragQueryFile(hDrop, xLong1)
        If Len(xChar1)
          BinaryBuffer_WriteStringLP(hBuff, xChar1)
          xLong2 + 1
          EndIf
        Next
      If xLong2
        xLong1 = BinaryBuffer_GetMemPtr(hBuff, 0, 4)
        If xLong1 And BinaryBuffer_IsOK(hBuff)
;Debug "Writing " + Str(xLong2) + " to " + Hex(xLong1)
          PokeL(xLong1, xLong2)
          OLEDropMemory = hBuff
          hBuff = 0
          PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 1)
          EndIf
        EndIf
      If hBuff
        BinaryBuffer_Discard(hBuff)
        EndIf
      EndIf
    EndIf
  DragFinish_(hDrop)
  EndProcedure

Procedure MainForm_ToggleDirList(UpdateWin.i, SetMenu.i)
  Define.i xBool1

  If SetMenu
    RadioApiMenu(424, 427, 424 + xDirListModeSet)
    EndIf
  If xDirListModeCur > 0
    If xDirListModeCur = 1
      If (Not xDirListTopHeight = #xDirListMaxTH)
        xBool1 = #True
        EndIf
      ElseIf xDirListModeCur = 2
      If (Not xDirListLeftWidth = #xDirListMaxLW)
        xBool1 = #True
        EndIf
      EndIf
    ShowWindow_(xListHWnd(0), 0)
    SetWindowLong_(xListHWnd(0), -16, $46000100)
    SetWindowLong_(xListHWnd(0), -20, $200)
    ShowWindow_(xStaticIconsHWnd(#xStaticIcons_DirList), 0)
    SetWindowPos_(xListHWnd(0), 0, 0, 0, 0, 0, $335)
    If Not InterfaceMode = #Interface_Mode_Wizard
      ShowWindow_(xListHWnd(0), 5)
      EndIf
    Else
    ShowWindow_(xListHWnd(0), 0)
    SetWindowLong_(xListHWnd(0), -16, $46000100)
    SetWindowLong_(xListHWnd(0), -20, $20201)
    SetWindowPos_(xListHWnd(0), 0, 0, xDefCtlHeight16, 0, 0, $335)
    SetWindowPos_(xListHWnd(2), 0, 0, xDefCtlHeight16 + eSPTopY, 300, 200, $215)
    If Not InterfaceMode = #Interface_Mode_Wizard
      ShowWindow_(xStaticIconsHWnd(#xStaticIcons_DirList), 5)
      EndIf
    EndIf
  MainForm_EnableApiMenu(429, xBool1)
  MainForm_EnableApiMenu(428, xBool1)

  If Not InterfaceMode = #Interface_Mode_Wizard
    If xDirListModeCur = 2
      If Not HWndSplitterLW = 0
        ShowWindow_(HWndSplitterLW, 5)
        EndIf
      If Not HWndSplitterMoveLW = 0
        ShowWindow_(HWndSplitterMoveLW, 5)
        EndIf
      If Not HWndSplitterTH = 0
        ShowWindow_(HWndSplitterTH, 0)
        EndIf
      If Not HWndSplitterMoveTH = 0
        ShowWindow_(HWndSplitterMoveTH, 0)
        EndIf
      Else
      If Not HWndSplitterTH = 0
        ShowWindow_(HWndSplitterTH, 5)
        EndIf
      If Not HWndSplitterMoveTH = 0
        ShowWindow_(HWndSplitterMoveTH, 5)
        EndIf
      If Not HWndSplitterLW = 0
        ShowWindow_(HWndSplitterLW, 0)
        EndIf
      If Not HWndSplitterMoveLW = 0
        ShowWindow_(HWndSplitterMoveLW, 0)
        EndIf
      EndIf
    EndIf
  If UpdateWin
    MainForm_ResizePlayer(#False)
    MainForm_xBuildDirs()
    EndIf
  EndProcedure

Procedure CheckHideWizard()
  If InterfaceMode = #Interface_Mode_Wizard
    If Not (PLCount = 0)
      ToggleInterface(#Interface_Mode_None)
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_xBuildDirs()
  Define.i xLong1
  Define.i xLong2
  Define.i xLong5
  Define.i xLong6
  Define.i xBool1
  ;Dim xType1 As POINT
  
  If xDirListModeCur = 0 And InterfaceMode = #Interface_Mode_None
    ShowWindow_(xListHWnd(0), 0)
    DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
    EndIf
  ;eDropDown(0).Clear
  SendMessage_(xListHWnd(0), $184, 0, 0)
  xDirCount = 0
  xDirListEffDirs = 0
  If PLCount = 0
    SendMessage_(xListHWnd(2), $194, 0, 0)
    SendMessage_(xListHWnd(0), $194, 0, 0)
    If LEDMode And LEDState = $10
      LEDState = 3
      EndIf
    Else
    If LockWinUpd
      LockWindowUpdate_(xListHWnd(0))
      EndIf
    For xLong1 = 0 To PLCount - 1
CompilerIf #BoldDirs = 98
      xLong2 = PLI(xLong1)\pxWidthLg + (PLI(xLong1)\DirDepthFlags & #PLI_Depth) * 20
      If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
        xBool1 = #True
        If PLI(xLong1)\pxWidthSm > xLong6
          xLong6 = PLI(xLong1)\pxWidthSm
          EndIf
CompilerElse
      xLong2 = PLIPxLg(xLong1) + (PLIDF(xLong1) & #PLI_Depth) * 20
      If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
        xBool1 = #True
        If PLIPxSm(xLong1) > xLong6
          xLong6 = PLIPxSm(xLong1)
          EndIf
CompilerEndIf
        SendMessage_(xListHWnd(0), #LB_ADDSTRING, 0, xLong1)
        xDirPath(xDirCount) = xLong1
        xDirCount = xDirCount + 1
        ElseIf xBool1
        xBool1 = #False
        xDirListEffDirs = xDirListEffDirs + 1
        EndIf
      If xLong2 > xLong5
        xLong5 = xLong2
        EndIf
      Next
    xDirPath(xDirCount) = PLCount
    SendMessage_(xListHWnd(2), $194, 28 + #lWidth + xLong5, 0)
    SendMessage_(xListHWnd(0), $194, 28 + #lWidth + xLong6, 0)
    If LEDMode And LEDState = 3
      MainForm_UpdateMainIcon()
      EndIf
    EndIf
    
  If LockWinUpd
    LockWindowUpdate_(0)
    EndIf
    
  If xDirCount < 2
    EnableWindow_(xListHWnd(0), 0)
    
    MainForm_EnableApiMenu(420, #False)
    EnableWindow_(xListHWnd(0), 0)
    If xDirCount = 0
      ;eLabel(8)\Caption = ""
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("ClearDirCap due xBuildDirs")
        CompilerEndIf
      MainForm_SetDirCaption("")
      EndIf
    Else
    EnableWindow_(xListHWnd(0), 1)
;    eButton(0).Enabled = #True
    ;mTMenu(8).Enabled = #True
    MainForm_EnableApiMenu(420, #True)
    EnableWindow_(xListHWnd(0), 1)
    EndIf
  
  If (PLCount > PLCountWarn)
    xWarnOverload = #True
    Else
    xWarnOverload = #False
    EndIf
  If (xWarnOverload XOr xOldWarnOverload)
    ;debug "#######", xOldWarnOverload,xOldWarnOverload
    MainForm_EnableApiMenu(10, xOldWarnOverload)
    MainForm_EnableApiMenu(11, xOldWarnOverload)
    MainForm_EnableApiMenu(12, xOldWarnOverload)
    CompilerIf #NoDroppingIfOverloaded
      If Not vKioskMode
        If xWarnOverload
          ;RevokeDragDrop(MainHWnd)
          DragAcceptFiles_(MainHWnd, #False)
          Else
          ;RegisterDragDrop(MainHWnd, ObjPtr(DragClass))
          DragAcceptFiles_(MainHWnd, #True)
          EndIf
        EndIf
      CompilerEndIf
    xOldWarnOverload = xWarnOverload
    MainForm_UpdateMainIcon()
    EndIf
  
  If xDirListModeSet = 3
    If xDirListEffDirs > #xDirListEffMax2
      If Not xDirListModeCur = 2
        xDirListModeCur = 2
        MainForm_ToggleDirList(#True, #False)
        EndIf
CompilerIf #AutoDirPosOnTop
      ElseIf xDirListEffDirs > xDirListEffMax1
      If Not xDirListModeCur = 1
        xDirListModeCur = 1
        MainForm_ToggleDirList(#True, #False)
        EndIf
CompilerEndIf
      ElseIf Not xDirListModeCur = 0
      xDirListModeCur = 0
      MainForm_ToggleDirList(#True, #False)
      EndIf
    EndIf
  
  MainForm_CheckDir(#True)
  CheckHideWizard()
  EndProcedure

Procedure AddDriveMenuCaption(hMenu.i, InsertMenuID.i, xIndex.i, xDriveType.i, AddLeadMenuID.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.s xChar1
  Define.s MemName
  CompilerIf #LoadShellDriveIcons
    Define.MENUITEMINFO xType1
    CompilerEndIf

  xLong1 = SetErrorMode_(1)
  xChar1 = Mid(CDDriveLetters, xIndex + 1, 1) + ":\"
  xLong4 = GetVolumeInformation_(@xChar1, *ptrTemp, #ptrTempSizeXAW, 0, xLong2, xLong3, 0, 0)
  SetErrorMode_(xLong1)
  If xLong4
    MemName = PeekS(*ptrTemp)
    If Len(MemName)
      MemName = ReplaceString(LoadResString(1051), "$V", MemName)
      EndIf
    EndIf
  CompilerIf #LoadShellDriveIcons
    Select xDriveType
      Case 5: xLong3 = 0
      Case 3: xLong3 = 1
      Case 2: xLong3 = 2
      EndSelect
    If xLong4 = 0 Or Len(MemName) = 0
      MemName = LoadResString(1052 + xLong3)
      EndIf
    CompilerElse
    If xLong4 = 0 Or Len(MemName) = 0
      Select xDriveType
        Case 5: xLong4 = 1052
        Case 3: xLong4 = 1053
        Case 2: xLong4 = 1054
        EndSelect
      MemName = LoadResString(xLong4)
      EndIf
    CompilerEndIf
  xChar1 = Left(xChar1, 1)
  MemName = ReplaceString(MemName, "$L", UCase(xChar1))
  MemName = ReplaceString(MemName, "$l", LCase(xChar1))
  CompilerIf #LoadShellDriveIcons
    ShellDrvDCap(xIndex) = MemName
    ShellDrvDIco(xIndex) = xLong3
    InsertMenu_(hMenu, AddLeadMenuID, $4100, InsertMenuID, InsertMenuID)
    With xType1
      \cbSize = 44 ;Len(xType1) w/o 98
      \fMask = $100 ;$120
      \fType = $100
      ;.hbmpItem = ShellDrvIcons(xLong3)
      ;debug "Size: " + Str(Len(xType1))
      ;Stop
      EndWith
    SetMenuItemInfo_(hMenu, InsertMenuID, #False, @xType1)
    CompilerElse
    InsertMenu_(hMenu, AddLeadMenuID, 0, InsertMenuID, @MemName)
    CompilerEndIf
  EndProcedure

Procedure MainForm_XMenuRefresherDevices_ProcessMenu(xLong1.i, xDevicesCount.i, hMenu.i, LeadMenuID.i, InsertMenuID.i)
  Define.i xLong4
  Define.s xChar1

  If hMenu
;    hMenu.i, MenuID.i,    Caption.s, InsertAfter.i
; -> hMenu,   InsertAfter, 0,         MenuID,       @Caption)

    If Not ((GetMenuState_(hMenu, LeadMenuID, 0) & $ffffffff) = $ffffffff And (GetMenuState_(hMenu, InsertMenuID, 0) & $ffffffff) = $ffffffff)
      If xDevicesCount
        xChar1 = LoadResString(1055)
        InsertMenu_(hMenu, InsertMenuID, 0, LeadMenuID, @xChar1)
        EndIf
      For xLong4 = InsertMenuID + xDevicesCount - 1 To InsertMenuID Step -1
        DeleteMenu_(hMenu, xLong4, 0)
        Next
      If xLong1
        For xLong4 = 0 To xLong1 - 1
          AddDriveMenuCaption(hMenu, xLong4 + InsertMenuID, xLong4, MainForm_XMenuRefresherDevicesIIDs(xLong4), LeadMenuID)
          Next
        DeleteMenu_(hMenu, LeadMenuID, 0)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_XMenuRefresherDevices()
  Define.i xLong1
  Define.i xLong2
  Define.i xLong4
  Define.i LeadMenuID
  Define.i InsertMenuID
  Static xDevicesCount
  Define.i xBool1

  If Not (FindString(CommandX, "/DD") = 0 And vKioskMode)
    xBool1 = #True
    EndIf
  If xBool1 Or FindString(CommandX, "/CD")
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Detecting CD drives")
      CompilerEndIf
    xLong1 = GetLogicalDrives_()
    CDDriveLetters = ""
    
    For xLong2 = #FirstNonFloppy To 25
      If (xLong1 & (1 << xLong2))
        Select GetDriveType_(Chr(65 + xLong2) + ":")
          Case 2
            If xBool1
              MainForm_XMenuRefresherDevicesIIDs(Len(CDDriveLetters)) = 2
              CDDriveLetters = CDDriveLetters + Chr(xLong2 + 65)
              EndIf
          Case 3
            If xBool1
              If IsRemoveableDrive(xLong2)
                MainForm_XMenuRefresherDevicesIIDs(Len(CDDriveLetters)) = 3
                CDDriveLetters = CDDriveLetters + Chr(xLong2 + 65)
                EndIf
              EndIf
          Case 5
            MainForm_XMenuRefresherDevicesIIDs(Len(CDDriveLetters)) = 5
            CDDriveLetters = CDDriveLetters + Chr(xLong2 + 65)
          EndSelect
        EndIf
      Next
    CompilerIf #UseFileLogging
      Else
      MainForm_ctConsoleA_AddLog("Detecting CD drives ignored (kiosk mode)")
      CompilerEndIf
    EndIf
  
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  Detected: " + CDDriveLetters)
    CompilerEndIf
  xLong1 = Len(CDDriveLetters)
  For xLong2 = 0 To #xMenuCountX
    MainForm_XMenuRefresherDevices_ProcessMenu(xLong1, xDevicesCount, xMenu(xLong2), 1023, 1970)
    MainForm_XMenuRefresherDevices_ProcessMenu(xLong1, xDevicesCount, xMenu(xLong2), 2023, 2970)
    Next
      
  xDevicesCount = xLong1
  If xLong1
    xLong1 = #True
    EndIf
  MainForm_EnableApiMenu(21, xLong1)
  MainForm_EnableApiMenu(22, xLong1)
  EndProcedure

Procedure MainForm_XMenuRefresherFileDir_ProcessMenu(xCount.i, IsPl, xMenuHwnd.i, LeadMenuID.i, InsertMenuID.i)
  Define.i xLong1
  Define.s xChar1

  If xMenuHwnd
    If Not ((GetMenuState_(xMenuHwnd, LeadMenuID, 0) & $ffffffff) = $ffffffff And (GetMenuState_(xMenuHwnd, InsertMenuID, 0) & $ffffffff = $ffffffff))
      If MainForm_XMenuRefresherFileDir_Counts(IsPl)
        xChar1 = LoadResString(1050)
        InsertMenu_(xMenuHwnd, InsertMenuID, 0, LeadMenuID, @xChar1)
        EndIf
      For xLong1 = InsertMenuID + MainForm_XMenuRefresherFileDir_Counts(IsPl) - 1 To InsertMenuID Step -1
        DeleteMenu_(xMenuHwnd, xLong1, 0)
        Next
      If xCount
        For xLong1 = 0 To xCount - 1
          InsertMenu_(xMenuHwnd, LeadMenuID, 0, InsertMenuID + xLong1, @vPLX(IsPl * #vPLXMax + xLong1))
          Next
        DeleteMenu_(xMenuHwnd, LeadMenuID, 0)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure.i AllowedItemPLFast(ShortFilename.s)
  Define.i xResult

  Select GetExtensionPart(ShortFilename)
    Case "m3u", "pls", "aap"
      xResult = #True
    Case "m3u8", "xspf", "aimppl", "plc", "wpl"
      CompilerIf #PB_Compiler_Unicode
        xResult = #True
        CompilerEndIf
    EndSelect
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_XMenuRefresherFileDir()
  Define.i xMenuIDX
  Define.i xMenuHwnd
  Define.i hFindFile
  Define.WIN32_FIND_DATA xType1
  Define.i LeadMenuID
  Define.i InsertMenuID
  Define.i IsPl
  Define.i xCount
  Define.i xLong1

  For IsPl = 0 To 2
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Detecting files / updating menu (" + Str(IsPl) + ")")
      CompilerEndIf
    
    xType1\dwFileAttributes = $2F
    If IsPl = 0
      If Not xNoPLMenu
; playlistformatsimport
        hFindFile = FindFirstFile_(vPLXMain + "*.*", @xType1)
        LeadMenuID = 1033
        InsertMenuID = 3000
        EndIf
      ElseIf IsPl = 1
      If Not xNoPresets
        hFindFile = FindFirstFile_(vPLXMain + "*.cps", @xType1)
        LeadMenuID = 1463
        InsertMenuID = 4000
        EndIf
      Else
      If Not xNoTimers
        hFindFile = FindFirstFile_(vPLXMain + "*.cpt", @xType1)
        LeadMenuID = 1445
        InsertMenuID = 5000
        EndIf
      EndIf
    xCount = 0
    If Not hFindFile = -1
      If IsPl = 0
        Repeat
          If AllowedItemPLFast(PeekS(@xType1\cFileName))
            If Not (xType1\dwFileAttributes & $10)
              vPLX(IsPl * #vPLXMax + xCount) = PeekS(@xType1\cFileName)
              xCount = xCount + 1
              EndIf
            EndIf
          If xCount = #vPLXMax
            Break
            EndIf
          Until FindNextFile_(hFindFile, xType1) = 0
        Else
        Repeat
          If Not (xType1\dwFileAttributes & $10)
            vPLX(IsPl * #vPLXMax + xCount) = PeekS(@xType1\cFileName)
            xCount = xCount + 1
            EndIf
          If xCount = #vPLXMax
            Break
            EndIf
          Until FindNextFile_(hFindFile, xType1) = 0
        EndIf
      FindClose_(hFindFile)
      SortArray(vPLX(), #PB_Sort_Ascending | #PB_Sort_NoCase, IsPl * #vPLXMax, xCount - 1)
      For xMenuIDX = 0 To #xMenuCountX
        xMenuHwnd = xMenu(xMenuIDX)
        MainForm_XMenuRefresherFileDir_ProcessMenu(xCount, IsPl, xMenuHwnd, LeadMenuID, InsertMenuID)
        Next
      If xTimerEditing
        xMenuHwnd = xTimerPLMenu(IsPl)
        LeadMenuID = 2750 + IsPl * 10
        InsertMenuID = 3000 + IsPl * 100
        MainForm_XMenuRefresherFileDir_Counts(IsPl) = xTimerPLMenuLoaded(IsPl)
        xTimerPLMenuLoaded(IsPl) = xCount
        MainForm_XMenuRefresherFileDir_ProcessMenu(xCount, IsPl, xMenuHwnd, LeadMenuID, InsertMenuID)
        EndIf
      hFindFile = -1
      EndIf
    MainForm_XMenuRefresherFileDir_Counts(IsPl) = xCount
    Next
  EndProcedure

CompilerIf #UseFileLogging
  Procedure MainForm_PrintCDDARev()
    If CDDAUse
      If CDDAJitter
        MainForm_ctConsoleA_AddLog("    CDDA: on, JitterCorrection: On")
        Else
        MainForm_ctConsoleA_AddLog("    CDDA: on, JitterCorrection: Off")
        EndIf
      Else
      If CDDAJitter
        MainForm_ctConsoleA_AddLog("    CDDA: off, JitterCorrection: On")
        Else
        MainForm_ctConsoleA_AddLog("    CDDA: off, JitterCorrection: Off")
        EndIf
      EndIf
    EndProcedure
  CompilerEndIf

Procedure UpdatePriority(NewPriority.i)
  Select NewPriority
    Case -2: PlayerPriority = $40 ;idle
    Case -1
      CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
        PlayerPriority = $4000
        CompilerElse
        If IsMinWindows2000W
          PlayerPriority = $4000
          Else
          PlayerPriority = $20
          EndIf
        CompilerEndIf
    Case 0: PlayerPriority = $20
    Case 1
      CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
        PlayerPriority = $8000
        CompilerElse
        If IsMinWindows2000W
          PlayerPriority = $8000
          Else
          PlayerPriority = $20
          EndIf
        CompilerEndIf
    Case 2: PlayerPriority = $80 ;high
    Case 3: PlayerPriority = $100 ;realtime
    EndSelect
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("updating priority (Process " + Hex(GetCurrentProcessId_()) + ")")
    CompilerEndIf
  SetPriorityClass_(GetCurrentProcess_(), PlayerPriority)
  PlayerPriority = NewPriority
  EndProcedure

Procedure xInitMe(hWndCaller.i, FailSave.i, SpecMode.i, InitRun.i)
  Define.i xLong1
  ;define.i xLong2
  ;define.s xChar1

  DoEvents()
  If xNoSpektrumOnStartup
    PlayerPriority = 0
    EndIf
  Repeat
    xLong1 = ctSSLayer_GetDeviceFromSSLID(@xOutputSSLID)
    If xLong1 = -1
      xLong1 = 0
      EndIf
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Preparing sound system (" + GetDeviceName(xLong1) + ")")
      CompilerEndIf
    
    If ctSSLayer_Init(xLong1, MainHWnd, CDDAUse, CDDAJitter)
      CompilerIf #UseFileLogging
        ctSSLayer_SetDebugger(@SSDebuggerCB())
        CompilerEndIf
    ;If #False
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  Device: " + GetDeviceName(xLong1))
        MainForm_PrintCDDARev()
        CompilerEndIf
      If PlayerPriority
        UpdatePriority(PlayerPriority)
        EndIf
      KeepMusicAliveTime = ctSSLayer_CanUseItem($C)
      MainForm_DesireSpectrumState(#True, #True)
      If Not ctSSLayer_CanUseItem($10) = 0
        CompilerIf #UseFileLogging
          If ctSSLayer_CanUseItem($10) = 1
            MainForm_ctConsoleA_AddLog("Activating endsong callback support (partially supported by sound system)")
            Else
            MainForm_ctConsoleA_AddLog("Activating endsong callback support")
            EndIf
          CompilerEndIf
        ctSSLayer_SetEndCallback(xStaticIconsHWnd(#xStaticIcons_ShowIR), $111, -2)
        CompilerIf #UseFileLogging
          Else
          MainForm_ctConsoleA_AddLog("No endsong callback support")
          CompilerEndIf
        EndIf
      Break
      Else
;lbl1:
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  Error starting system")
        CompilerEndIf
      GenericMessageHandler_Param = 2101
      GlobalXInitRun = InitRun
      Select LoadResEx_Dialog(hWndCaller, 2101, 2090, 2091, @GenericMessageHandler())
        ;Case 1890 ;retry
        ;Case 1892 ;next
        Case 2091 ;quit!
          If InitRun
            xInfoQuit = #True
            If xCmdSaveSet
              If FailSave
                MainForm_SaveSettings(1, SpecMode)
                Else
                MainForm_SaveSettings(0, SpecMode)
                EndIf
              EndIf
            ctSSLayer_UnLoadVB()
            MainForm_UnloadP()
            Break
            EndIf
        EndSelect
      EndIf
    ForEver
  EndProcedure

Procedure UpdateMenuCaption(MenuID.i, Kbd_Def.i, Kbd_Gbl.i)
  Define.i xLong1
  Define.i xLong2
  ;Static xLong3.i
  ;Static xChar1.s
  ;Static xChar2.s
  
  xLong2 = -1
  ;If Kbd_Def = -1
    ;Kbd_Def = 0
    ;Else
    ;Kbd_Def = xKey(Kbd_Def)
    ;endif
  If Not Kbd_Def = -1
    If xKey(Kbd_Def) = 0
      Kbd_Def = -1
      EndIf
    EndIf
  If Not Kbd_Gbl = -1
    If xKey(Kbd_Gbl) = 0
      Kbd_Gbl = -1
      EndIf
    EndIf
  
  For xLong1 = 0 To #xMenuCountX
    If Kbd_Def = -1
      SetMenuShortcut(xMenu(xLong1), 1000 + MenuID, "")
      Else
      SetMenuShortcut(xMenu(xLong1), 1000 + MenuID, ExtKbdEx(Kbd_Def))
      EndIf
    If Kbd_Gbl = -1
      SetMenuShortcut(xMenu(xLong1), 2000 + MenuID, "")
      Else
      SetMenuShortcut(xMenu(xLong1), 2000 + MenuID, ExtKbdEx(Kbd_Gbl))
      EndIf
    Next
  EndProcedure

Procedure.s MainForm_xTimerDisplay(Index.i, Mode.i, *CheckIsOk)
  Define.s xResult
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.i xLong5
  Define.s xChar1
  Define.s xChar2
  Define.i CheckIsOk
  
  If *CheckIsOk
    CheckIsOk = PeekI(*CheckIsOk)
    EndIf
  
  xLong1 = FindString(xTimerEv(Index), "=")
  If xLong1
    xResult = Trim(Left(xTimerEv(Index), xLong1 - 1))
    EndIf
  
  If Len(xResult) = 0 Or CheckIsOk
    xChar1 = xTimerEv(Index) + #TimerSepp
    Repeat
      xLong2 = FindString(xChar1, #TimerSepp, xLong1 + 1)
      If xLong2 = 0
        If xLong1 = 0
          CheckIsOk = #False
          EndIf
        Break
        Else
        If xLong5 = #xTimerEvMaxSubEvents
          Else
          xLong5 = xLong5 + 1
          xChar2 = Mid(xChar1, xLong1 + 1, xLong2 - xLong1 - 1)
          xLong3 = FindString(xChar2, ",")
          If xLong3 = 0
            xLong4 = Val(xChar2)
            If xLong4 < 1 Or xLong4 > 299
              xResult = xResult + "; ???"
              CheckIsOk = #False
              ElseIf Not ValidSetupKey(xLong4)
              CheckIsOk = #False
              Else
              xResult = xResult + "; " + LoadResString(3700 + xLong4)
              If TimerHasSubFile(xLong4)
                CheckIsOk = #False
                ;Else
                EndIf
              EndIf
            Else
            xLong4 = Val(Left(xChar2, xLong3 - 1))
            If xLong4 < 1 Or xLong4 > 299
              xResult = xResult + "; ???"
              CheckIsOk = #False
              ElseIf Not ValidSetupKey(xLong4)
              CheckIsOk = #False
              Else
              xResult = xResult + "; " + LoadResString(3700 + xLong4)
              If TimerHasSubFile(xLong4)
                xChar2 = Trim(Mid(xChar2, xLong3 + 1))
                If Len(xChar2) = 0
                  CheckIsOk = #False
                  xTimerDisplayLastParamValue = xTimerDisplayLastParamValue + ", ???"
                  Else
                  xTimerDisplayLastParamValue = xTimerDisplayLastParamValue + ", " + xChar2
                  EndIf
                Else
                CheckIsOk = #False
                EndIf
              EndIf
            EndIf
          EndIf
        xLong1 = xLong2
        EndIf
      ForEver
    If *CheckIsOk
      PokeI(*CheckIsOk, CheckIsOk)
      EndIf
    xResult = Mid(xResult, 3)
    xTimerDisplayLastParamValue = Mid(xTimerDisplayLastParamValue, 3)
    EndIf
    
  
  
  
  GrabError()
  xLong1 = (xTimerEvTime(Index) - GetLocalTimeHM() + 1440) % 1440
  If xLong1 = 0 And xTimerEvTime(Index) + 1 = LastDoneTimer
    xLong1 = 1440
    EndIf
  If Mode = 2
    xResult = ReplaceString(LoadResString(2651), "$A", xResult)
    xResult = ReplaceString(xResult, "$T", Right("00" + Str(Int(xTimerEvTime(Index) / 60)), 2) + ":" + Right("00" + Str(xTimerEvTime(Index) % 60), 2))
    xResult = ReplaceString(xResult, "$M", Right("00" + Str(Int(xLong1 / 60)), 2) + ":" + Right("00" + Str(xLong1 % 60), 2))
    ElseIf Mode = 1
    xResult = Right("00" + Str(Int(xTimerEvTime(Index) / 60)), 2) + ":" + Right("00" + Str(xTimerEvTime(Index) % 60), 2) + #TAB$ + xResult
    xResult + #TAB$ + ReplaceString(LoadResString(2655), "$", Right("00" + Str(Int(xLong1 / 60)), 2) + ":" + Right("00" + Str(xLong1 % 60), 2))
    If Len(xTimerDisplayLastParamValue)
      xResult = xResult + #TAB$ + xTimerDisplayLastParamValue
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_SetTimerImage()
Define.s xChar1
Define.i xLong1

If xTimerEvCount = 0
  xChar1 = LoadResString(2650)
  MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_TimerInd, *xTimerIconBMP, xTimerIconLen, 0)
  CheckApiMenu(441, #False)
  MainForm_EnableApiMenu(443, #False)
  MainForm_EnableApiMenu(444, #False)
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Timer disabled")
    CompilerEndIf
  Else
  xTimerTimeTimerTime = GetTickTimeMS()
  MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_TimerInd, *xTimerIconBMP, xTimerIconLen, $10000000)
  CheckApiMenu(441, #True)
  If vKioskMode Or xSecureMode
    xLong1 = #False
    Else
    xLong1 = #True
    EndIf
  MainForm_EnableApiMenu(443, xLong1)
  If vKioskMode
    xLong1 = #False
    Else
    xLong1 = #True
    EndIf
  MainForm_EnableApiMenu(444, xLong1)
  CompilerIf #UseFileLogging And #TimeTestDebug
    xTimerDisplayLastParamValue = ""
    MainForm_ctConsoleA_AddLog("Timer changed: " + MainForm_xTimerDisplay(0, 2, 0))
    CompilerEndIf
  xTimerDisplayLastParamValue = ""
  xChar1 = MainForm_xTimerDisplay(0, 2, 0)
  EndIf
SetToolTip(#xStaticIcons_TimerInd, xChar1, ReplaceString(ReplaceString(ReplaceString(ReplaceString(LoadResString(2652), "$W", ExtKbdEx(#KbdC_OTimerEdit)), "$L", ExtKbdEx(#KbdC_OTimerImport)), "$S", ExtKbdEx(#KbdC_OTimerExport)), "$C", ExtKbdEx(#KbdC_OTimerClear)))
EndProcedure

Procedure MainForm_UpdateMenus()
  Define.i xLong1
  Define.s xChar1


  ;If xCmdQuitMode = 2
  ;  Else
  
  If xHasNextSong
    If Not vKioskMode
      SetToolTip(#xStaticIcons_Def3, LoadResString(1127), ExtKbdEx(#KbdC_CStop))
      SetToolTip(#xStaticIcons_Def5, ReplaceString(LoadResString(1137), "$", PlNextSongCap), ExtKbdEx(#KbdC_CEnd))
      EndIf
    ;mPMenu(4)\Caption = ExtKbd(1421, #KbdC_PFindCurrent)
    ElseIf Not vKioskMode
    SetToolTip(#xStaticIcons_Def3, LoadResString(1125), ExtKbdEx(#KbdC_CStop))
    SetToolTip(#xStaticIcons_Def5, LoadResString(1135), ExtKbdEx(#KbdC_CEnd))
    ;mPMenu(4)\Caption = ExtKbd(1420, #KbdC_PFindCurrent)
    EndIf


  UpdateMenuCaption(10, #KbdC_FAddFileS, -1)
  UpdateMenuCaption(11, #KbdC_FAddDir, -1)
  UpdateMenuCaption(12, #KbdC_FAddPList, -1)
  UpdateMenuCaption(22, #KbdC_FRefreshCD, -1)
  UpdateMenuCaption(30, #KbdC_FNewPL, -1)
  UpdateMenuCaption(31, #KbdC_FLoadPL, -1)
  ;UpdateMenuCaption(32,#KbdC_FLoadPLMenu
  UpdateMenuCaption(36, #KbdC_FLoadPLDefault, -1)
  UpdateMenuCaption(34, #KbdC_FReloadPL, -1)
  UpdateMenuCaption(40, #KbdC_FSavePL, -1)
  UpdateMenuCaption(41, #KbdC_FSavePLas, -1)
  UpdateMenuCaption(50, #KbdC_FClearPL, -1)
  UpdateMenuCaption(60, #KbdC_FQuitSD, #KbdC_GQuit)
  
  UpdateMenuCaption(101, #KbdC_CPrev, #KbdC_GPrev)
  If xKey(#KbdC_GPlay) = 0
    UpdateMenuCaption(102, #KbdC_CPlay, #KbdC_GPlayPause)
    Else
    UpdateMenuCaption(102, #KbdC_CPlay, #KbdC_GPlay)
    EndIf
  If xKey(#KbdC_CPause) = 0
    UpdateMenuCaption(103, #KbdC_CPause, #KbdC_GPlayPause)
    Else
    UpdateMenuCaption(103, #KbdC_CPause, #KbdC_GPause)
    EndIf
  UpdateMenuCaption(104, #KbdC_CStop, #KbdC_GStop)
  UpdateMenuCaption(105, #KbdC_CNext, #KbdC_GNext)
  UpdateMenuCaption(106, #KbdC_CEnd, #KbdC_GEnd)
  UpdateMenuCaption(110, #KbdC_CRepSingle, #KbdC_GRepSingle)
  UpdateMenuCaption(111, #KbdC_CRepAll, #KbdC_GRepAll)
  UpdateMenuCaption(112, #KbdC_CRepRnd, #KbdC_GRepRnd)
  UpdateMenuCaption(113, #KbdC_CRepToggle, #KbdC_GRepToggle)
  UpdateMenuCaption(119, #KbdC_CIntroMode, #KbdC_GIntroMode)
  UpdateMenuCaption(120, #KbdC_CSeekB, #KbdC_GSeekB)
  UpdateMenuCaption(121, #KbdC_CSeekF, #KbdC_GSeekF)
    UpdateMenuCaption(131, #KbdC_CCSSelFile, 0)
    UpdateMenuCaption(132, #KbdC_CCSRemFile, #KbdC_GRemFile)
    UpdateMenuCaption(133, #KbdC_CCSDelFile, #KbdC_GDelFile)
    UpdateMenuCaption(134, #KbdC_CCSExplorer, #KbdC_GExplorer)
  
  
  
  UpdateMenuCaption(201, #KbdC_PPlaySkip, -1)
  UpdateMenuCaption(202, #KbdC_PPlayEnd, -1)
  UpdateMenuCaption(203, #KbdC_PPlayNext, -1)
  UpdateMenuCaption(210, #KbdC_PFindCurrent, -1)
  UpdateMenuCaption(211, #KbdC_PFind, -1)
  UpdateMenuCaption(212, #KbdC_PFindNext, -1)
  UpdateMenuCaption(213, #KbdC_PFindQuick, -1)
  UpdateMenuCaption(214, #KbdC_PSelRnd, -1)
  UpdateMenuCaption(220, #KbdC_PInvSel, -1)
  UpdateMenuCaption(221, #KbdC_PRemSongs, -1)
  UpdateMenuCaption(222, #KbdC_PRem, -1)
  UpdateMenuCaption(223, #KbdC_PCopyPLEnd, -1)
  UpdateMenuCaption(224, #KbdC_PCrop, -1)
  UpdateMenuCaption(230, #KbdC_PDelFiles, -1)
  UpdateMenuCaption(250, #KbdC_PExplorer, -1)

;  UpdateMenuCaption(301, #KbdC_OFading, 0
  UpdateMenuCaption(301, #KbdC_OFading, -1)
  UpdateMenuCaption(302, #KbdC_OSpektrum, -1)
  UpdateMenuCaption(303, #KbdC_OFileInfos, -1)
  UpdateMenuCaption(310, #KbdC_OFollowSong, -1)
  UpdateMenuCaption(320, #KbdC_ORemMissing, -1)
  UpdateMenuCaption(321, #KbdC_ORemSkipped, -1)
  UpdateMenuCaption(322, #KbdC_ORemPlayed, -1)
  UpdateMenuCaption(330, #KbdC_ONoEndMode, -1)
  UpdateMenuCaption(331, #KbdC_OXFade, -1)
  UpdateMenuCaption(332, #KbdC_OMDMode, -1)
  UpdateMenuCaption(333, #KbdC_OStopEach, -1)
  UpdateMenuCaption(339, #KbdC_OEndModeTggle, -1)
    UpdateMenuCaption(341, #KbdC_CVolUp, #KbdC_GVolUp)
    UpdateMenuCaption(342, #KbdC_CVolDown, #KbdC_GVolDown)
    For xLong1 = 0 To 10
      ;mCVolume(xLong1 + 3)\Caption = ExtKbd(1560 + xLong1, xLong1 + #KbdC_CVolMute)
      UpdateMenuCaption(345 + xLong1, #KbdC_CVolMute + xLong1, -1)
      Next
  UpdateMenuCaption(360, #KbdC_CMoreSetts, -1)
  
  UpdateMenuCaption(406, #KbdC_OInternetRadio, #KbdC_GIRadio)
  UpdateMenuCaption(407, #KbdC_OInternetRadioRe, #KbdC_GIRadioRe)
  UpdateMenuCaption(408, #KbdC_OInternetRadioHP, #KbdC_GIRadioHP)
  
  UpdateMenuCaption(411, #KbdC_OAutoRF, #KbdC_GAutoRF)
  UpdateMenuCaption(412, #KbdC_OAutoRFAlt, #KbdC_GAutoRFAlt)
  UpdateMenuCaption(413, #KbdC_OAutoRFRem, -1)
  UpdateMenuCaption(414, #KbdC_OAutoRFRemI, -1)
  UpdateMenuCaption(415, #KbdC_OAutoRFSetup, -1)
  UpdateMenuCaption(419, 0, #KbdC_GAbortReading) ;unused!
  UpdateMenuCaption(420, #KbdC_PGotoDir, -1)
      UpdateMenuCaption(424, #KbdC_ODirCombo, -1)
      UpdateMenuCaption(425, #KbdC_ODirTop, -1)
      UpdateMenuCaption(426, #KbdC_ODirLeft, -1)
      UpdateMenuCaption(427, #KbdC_ODirAuto, -1)
      UpdateMenuCaption(423, #KbdC_ODirToggle, -1)
      UpdateMenuCaption(429, #KbdC_ODirInc, -1)
      UpdateMenuCaption(428, #KbdC_ODirDec, -1)
  UpdateMenuCaption(421, #KbdC_CPrevSongs, -1)
  ;mTMenu(10)\Caption = ExtKbd(1640, #KbdC_OTimerMenu)
      UpdateMenuCaption(441, #KbdC_OTimerEdit, -1)
      UpdateMenuCaption(442, #KbdC_OTimerImport, -1)
      UpdateMenuCaption(443, #KbdC_OTimerExport, -1)
      UpdateMenuCaption(444, #KbdC_OTimerClear, -1)
  ;mTMenu(11)\Caption = ExtKbd(1645, #KbdC_OTimerClear)
  UpdateMenuCaption(450, #KbdC_OResetSnd, #KbdC_GResetSND)
  UpdateMenuCaption(455, #KbdC_OVolCtrl, #KbdC_GVolCtrl)
  ;mTMenu(15)\Caption = ExtKbd(1670, #KbdC_OPresetMenu)
      UpdateMenuCaption(461, #KbdC_OPresetSave, -1)
      UpdateMenuCaption(462, #KbdC_OPresetLoad, -1)
  UpdateMenuCaption(470, #KbdC_OSaveSetts, -1)
  ;UpdateMenuCaption(330, #KbdC_CVolMenu, #KbdC_GShowVolMenu

  ;UpdateMenuCaption(500, #KbdC_IInfoMenu, 0
    UpdateMenuCaption(501, #KbdC_IHelp, -1)
    UpdateMenuCaption(502, #KbdC_IAbout, -1)
  
  
  
  
  UpdateMenuCaption(800, -1, #KbdC_GShowPlayer)
  UpdateMenuCaption(810, -1, #KbdC_GShowTitle) ;Unused!
  
  
  
  
;  On Error Resume Next
  If (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
    ResetStreamTT()
    EndIf

  xChar1 = LoadResString(1106)
    xChar1 = ReplaceString(xChar1, "$G", ExtKbdEx(#KbdC_PGotoDir))
    xChar1 = ReplaceString(xChar1, "$D", ExtKbdEx(#KbdC_ODirCombo))
    xChar1 = ReplaceString(xChar1, "$L", ExtKbdEx(#KbdC_ODirLeft))
    xChar1 = ReplaceString(xChar1, "$T", ExtKbdEx(#KbdC_ODirTop))
    xChar1 = ReplaceString(xChar1, "$A", ExtKbdEx(#KbdC_ODirAuto))
    xChar1 = ReplaceString(xChar1, "$M", ExtKbdEx(#KbdC_ODirToggle))
    xChar1 = ReplaceString(xChar1, "$E", ExtKbdEx(#KbdC_ODirInc))
    xChar1 = ReplaceString(xChar1, "$S", ExtKbdEx(#KbdC_ODirDec))
    SetToolTip(#xStaticIcons_DirList, LoadResString(1105), xChar1)

  If vKioskMode
    SetToolTip(#xStaticIcons_CurSongPos, LoadResString(1172), "")
    SetToolTip(#xStaticIcons_Spectrum, LoadResString(1176), "")
    SetToolTip(#xStaticIcons_Tags, LoadResString(1180), "")
    Else
    SetToolTip(#xStaticIcons_CurSongPos, LoadResString(1170), ReplaceString(ReplaceString(LoadResString(1171), "$L", ExtKbdEx(#KbdC_CSeekB)), "$R", ExtKbdEx(#KbdC_CSeekF)))
    SetToolTip(#xStaticIcons_Spectrum, LoadResString(1175), ExtKbdEx(#KbdC_OSpektrum))
    SetToolTip(#xStaticIcons_Tags, LoadResString(1180), ExtKbdEx(#KbdC_OFileInfos))
    EndIf
  CurSongToolTip1 = LoadResString(1107)
  CurSongToolTip2 = ReplaceString(ReplaceString(ReplaceString(ReplaceString(ReplaceString(LoadResString(1108), "$P", ExtKbdEx(#KbdC_CPrevSongs)), "$S", ExtKbdEx(#KbdC_CCSSelFile)), "$R", ExtKbdEx(#KbdC_CCSRemFile)), "$D", ExtKbdEx(#KbdC_CCSDelFile)), "$X", ExtKbdEx(#KbdC_CCSExplorer))
  SetToolTip(#xStaticIcons_CurSong, ReplaceString(CurSongToolTip1, "$M", FormatToolTip1), CurSongToolTip2 + FormatToolTip2)
  
  
  SetToolTip(#xStaticIcons_Def0, LoadResString(1110), ExtKbdEx(#KbdC_CPrev))
  SetToolTip(#xStaticIcons_Def1, LoadResString(1115), ExtKbdEx(#KbdC_CPlay))
  SetToolTip(#xStaticIcons_Def2, LoadResString(1120), ExtKbdEx(#KbdC_CPause))
  SetToolTip(#xStaticIcons_Def4, LoadResString(1130), ExtKbdEx(#KbdC_CNext))
  xVolTTText = ReplaceString(ReplaceString(ReplaceString(ReplaceString(ReplaceString(LoadResString(1151), "$+", ExtKbdEx(#KbdC_CVolUp)), "$-", ExtKbdEx(#KbdC_CVolDown)), "$M", ExtKbdEx(#KbdC_CVolMute)), "$F", ExtKbdEx(#KbdC_CVolFull)), "$V", "$")
  SetToolTip(#xStaticIcons_Volume, ReplaceString(LoadResString(1150), "$", Str((xSetVolume * 100) / 255)), xVolTTText)
  
  xModeTTText = ReplaceString(ReplaceString(ReplaceString(ReplaceString(ReplaceString(LoadResString(1161), "$S", ExtKbdEx(#KbdC_CRepSingle)), "$A", ExtKbdEx(#KbdC_CRepAll)), "$R", ExtKbdEx(#KbdC_CRepRnd)), "$I", ExtKbdEx(#KbdC_CIntroMode)), "$M", "$")
  
  If IntroModeActive
    xLong1 = 1
    Else
    xLong1 = 0
    EndIf
  SetToolTip(#xStaticIcons_RepMode, ReplaceString(LoadResString(1160), "$", LoadResString(1162 + xRep * 2 + xLong1)), xModeTTText)
  MainForm_SetTimerImage()
  If GlobalKeys
    MainForm_SetGlobalKeys(#False)
    MainForm_SetGlobalKeys(#True)
    EndIf
  EndProcedure

Procedure.i AllowedItem(Filename.s, MustExist.i)
  Define.i xResult

CompilerIf #CanEnumComputerShares
  If Left(Filename, 2) = "\\" And FindString(Filename, "\", 3) = 0
    ;AllowedItem = 0
    ; computer sharing parend, e.g. \\LAPTOP
CompilerEndIf
    If MustExist
      If GetFileAttributes_(@Filename) & $10
        ProcedureReturn 0
        EndIf
      EndIf
    Filename = GetExtensionPart(Filename)
    If FindString(xSupportedFiles, #UsedTypesVBNullChar + Filename + #UsedTypesVBNullChar)
      xResult = 1
      Else
; playlistformatsimport
      Select Filename
        Case "m3u", "pls", "aap"
          xResult = 255
        Case "m3u8", "xspf", "aimppl", "plc", "wpl"
          CompilerIf #PB_Compiler_Unicode
            xResult = 255
            CompilerElse
            If Not MustExist
              xResult = 255
              EndIf
            CompilerEndIf
        Case "cpt"
          xResult = 254
        Case "ini", "cps"
          xResult = 253
        Default
          xResult = -1
        EndSelect
      EndIf
CompilerIf #CanEnumComputerShares
    EndIf
CompilerEndIf
  ProcedureReturn xResult
  EndProcedure

Procedure SetAutoDoing(xBool1.i)
  If xBool1 XOr xAutoDoing
    xAutoDoing = xBool1
    If xAutoDoing And Not vKioskMode
      MainForm_EnableApiMenu(419, #True)
      Else
      MainForm_EnableApiMenu(419, #False)
      EndIf
    If xBool1
      MainForm_SetDirCaption("")
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("ClearDirCap due SetAutoDoing")
        CompilerEndIf
      If xDirListModeCur = 0
        If IsWindowVisible_(xListHWnd(0))
          ShowWindow_(xListHWnd(0), 0)
          ;DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
          EndIf
        EndIf
      Else
      If Not (xHiddenAutoDoing Or xPStateIconSndcard Or xPStateIconStartup Or AllTears_TypesCount > AnimateForTearCountX)
        DoAnimateReadDir(0)
        EndIf
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("WantDirCap from SetAutoDoing (force)")
        If PLClearCounter < PLCount
          PLClearCounter = PLCount
          EndIf
        CompilerEndIf
      MainForm_CheckDir(#True)
      EndIf
    If xBool1
      EnableWindow_(xListHWnd(0), #False)
      Else
      EnableWindow_(xListHWnd(0), #True)
      EndIf
    If AutoRefreshApplyHWnd
      If xAutoDoing
        EnableWindow_(AutoRefreshApplyHWnd, #False)
        Else
        EnableWindow_(AutoRefreshApplyHWnd, #True)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure SetNextSong(SetNow.i)
  If SetNow
    xHasNextSong = #True
    If vKioskMode
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def3, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $13000000)
      MainForm_EnableApiMenu(104, #True)
      SetToolTip(#xStaticIcons_Def3, ReplaceString(LoadResString(1142), "$", PlNextSongCap), ExtKbdEx(#KbdC_CStop))
      Else
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def5, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $13000000)
      SetToolTip(#xStaticIcons_Def3, LoadResString(1127), ExtKbdEx(#KbdC_CStop))
      SetToolTip(#xStaticIcons_Def5, ReplaceString(LoadResString(1137), "$", PlNextSongCap), ExtKbdEx(#KbdC_CEnd))
      EndIf
    SilentPlNext = #False
    CheckApiMenu(106, #True)
    If CurMusic = #ctSSLayer_MusicTypeTracker And Not xSongIsMidi
      ctSSLayer_UpdateLooping(SongPointer(CurrentSongID), #False)
      EndIf
    Else
    xHasNextSong = #False
    If vKioskMode
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def3, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $3000000)
      MainForm_EnableApiMenu(104, #False)
      SetToolTip(#xStaticIcons_Def3, LoadResString(1140), ExtKbdEx(#KbdC_CStop))
      Else
      MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def5, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $3000000)
      SetToolTip(#xStaticIcons_Def3, LoadResString(1125), ExtKbdEx(#KbdC_CStop))
      SetToolTip(#xStaticIcons_Def5, LoadResString(1135), ExtKbdEx(#KbdC_CEnd))
      EndIf
    PlNextSong = ""
    PlNextSongCap = ""
    SilentPlNext = #False
    CheckApiMenu(106, #False)
    If CurMusic = #ctSSLayer_MusicTypeTracker And Not xSongIsMidi
      If xRep
        SetNow = #False
        Else
        SetNow = #True
        EndIf
      ctSSLayer_UpdateLooping(SongPointer(CurrentSongID), SetNow)
      EndIf
    EndIf
  EndProcedure

Procedure ClearPLEx()
  SendMessage_(xListHWnd(2), $184, 0, 0)
  SendMessage_(xListHWnd(2), $194, 0, 0)
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("ClearDirCap due ClearPLEx")
    CompilerEndIf
  MainForm_SetDirCaption("")
  xDirCount = 0
  ;eDropDown(0).Clear
  SendMessage_(xListHWnd(0), $184, 0, 0)
  SendMessage_(xListHWnd(0), $194, 0, 0)
  xDirListEffDirs = 0

  If xDirListModeSet = 3
    If Not xDirListModeCur = 0
      xDirListModeCur = 0
      MainForm_ToggleDirList(#True, #False)
      EndIf
    EndIf
  EndProcedure

Procedure RealPLAdd(xFirst.i)
  Define.i xLong1
  Define.i xDC1.i
  Define.i xDC2.i
  Define.i xDCD.i
  Define.i xDCB.i
  Define.i xFntD.i
  Define.i xFntB.i
  Define.i xFntS.i
  
  xDC1 = CreateCompatibleDC_(0)
  If xDC1 = 0
    xDCD = xSharedDC
    xDCB = xSharedDC
    Else
    xDCD = xDC1
    xFntD = SelectObject_(xDC1, hFontPLLg)
    xDC2 = CreateCompatibleDC_(0)
    If xDC2 = 0
      xDCB = xDC1
      Else
      xDCB = xDC2
      xFntB = SelectObject_(xDC2, hFontPLLgB)
      EndIf
    EndIf
  
  If LockWinUpd
    LockWindowUpdate_(xListHWnd(2))
    EndIf
  
  xFntS = SelectObject_(xSharedDC, hFontPLSm)
  
  If ShowFullPath
    For xLong1 = xFirst To PLCount - 1
      CompilerIf #BoldDirs = 98
        If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
          PLI(xLong1)\pxWidthLg = GetTextOutWidth(xDCB, PLI(xLong1)\Caption)
          PLI(xLong1)\pxWidthSm = GetTextOutWidth(xSharedDC, PLI(xLong1)\Filename)
          Else
          PLI(xLong1)\pxWidthLg = GetTextOutWidth(xDCD, PLI(xLong1)\Caption)
          EndIf
        CompilerElse
        If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
          PLIPxLg(xLong1) = GetTextOutWidth(xDCB, PLICap(xLong1))
          PLIPxSm(xLong1) = GetTextOutWidth(xSharedDC, PLIFile(xLong1))
          Else
          PLIPxLg(xLong1) = GetTextOutWidth(xDCD, PLICap(xLong1))
          EndIf
        CompilerEndIf
      
      SendMessage_(xListHWnd(2), #LB_ADDSTRING, 0, xLong1)
      If xLong1 & $7f = 0
        If LockWinUpd = 0
          DoEventsEx_SleepPeriodical()
          ElseIf LockWinUpd = 1
          DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
          EndIf
        EndIf
      Next
    Else
    For xLong1 = xFirst To PLCount - 1
      CompilerIf #BoldDirs = 98
        If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
          PLI(xLong1)\pxWidthLg = GetTextOutWidth(xDCB, PLI(xLong1)\Caption)
          PLI(xLong1)\pxWidthSm = GetTextOutWidth(xSharedDC, PLI(xLong1)\Caption) + (PLI(xLong1)\DirDepthFlags & #PLI_Depth) * 20
          Else
          PLI(xLong1)\pxWidthLg = GetTextOutWidth(xDCD, PLI(xLong1)\Caption)
          EndIf
        CompilerElse
        If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
          PLIPxLg(xLong1) = GetTextOutWidth(xDCB, PLICap(xLong1))
          PLIPxSm(xLong1) = GetTextOutWidth(xSharedDC, PLICap(xLong1)) + (PLIDF(xLong1) & #PLI_Depth) * 20
          Else
          PLIPxLg(xLong1) = GetTextOutWidth(xDCD, PLICap(xLong1))
          EndIf
        CompilerEndIf
      
      SendMessage_(xListHWnd(2), #LB_ADDSTRING, 0, xLong1)
      If xLong1 & $7f = 0
        If LockWinUpd = 0
          DoEventsEx_SleepPeriodical()
          ElseIf LockWinUpd = 1
          DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
          EndIf
        EndIf
      Next
    EndIf
  
  SelectObject_(xSharedDC, xFntS)
  If Not xDC1 = 0
    SelectObject_(xDC1, xFntD)
    DeleteDC_(xDC1)
    If Not xDC2 = 0
      SelectObject_(xDC2, xFntB)
      DeleteDC_(xDC2)
      EndIf
    EndIf
    MainForm_xBuildDirs()
  EndProcedure

Procedure GenCalaymStructure(NoApply.i, ArraySize.i, SortNames.i)
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.i xLong5
  Define.i xLong6
  Define.s xChar1
  Define.s xChar2
  Define.s xChar3

;DoEventsEx_Sleep 5000

  
  If Not ArraySize = 0
    If SortNames ;!!!!! required to prevent wasting of dirs
      ;ArraySort_String_IC(sCharA1(), ArraySize)
      SortArray(sCharA1(), #PB_Sort_Ascending | #PB_Sort_NoCase, 0, ArraySize - 1)
      EndIf
    xLong6 = PLCount
    
    xChar1 = SimpleDir(sCharA1(0))
    xChar2 = LCase(xChar1) + "\"
    xLong3 = Len(xChar2)
    
    For xLong2 = 1 To ArraySize - 1
      If Not LCase(Left(sCharA1(xLong2), xLong3)) = xChar2
        While (Not (LCase(Left(sCharA1(xLong2), xLong3)) = xChar2 Or xChar1 = ""))
          xLong3 = InstrRevChar(xChar1, 92) ;"\"
          If xLong3 = 0
            xChar1 = ""
            Break
            EndIf
          xChar1 = Left(xChar1, xLong3 - 1)
          If xChar1 = "\" Or xChar1 = "\\"
            xChar1 = ""
            Break
            EndIf
          xChar2 = LCase(xChar1) + "\"
          xLong3 = Len(xChar2)
          Wend
        EndIf
      Next
    
    If SortNames
      For xLong2 = 0 To ArraySize - 2
        ;If StrComp(sCharA1(xLong2), sCharA1(xLong2 + 1), #PB_String_NoCase) = 0
        If CompareMemoryString(@sCharA1(xLong2), @sCharA1(xLong2 + 1), #PB_String_NoCase) = 0
          sCharA1(xLong2) = ""
          EndIf
        Next
      EndIf
    
    If xChar1 = ""
      xChar2 = ""
      xLong3 = 0
      Else
      CompilerIf #BoldDirs = 98
        PLI(PLCount)\Filename = xChar1
        PLI(PLCount)\Caption = xChar1
        PLI(PLCount)\DirDepthFlags = #PLI_IsDir | xLong4
        xLong4 = 1
        CompilerElse
        PLIFile(PLCount) = xChar1
        PLICap(PLCount) = xChar1
        PLIDF(PLCount) = #PLI_IsDir | xLong4
        xLong4 = 1
        CompilerEndIf
      PLCount = PLCount + 1
      If PLCount < PLCountMax
        For xLong5 = 0 To ArraySize - 1
          If Not Len(sCharA1(xLong5)) = 0
            xChar3 = LCase(SimpleDir(sCharA1(xLong5))) + "\"
            If xChar3 = xChar2
              CompilerIf #BoldDirs = 98
                PLI(PLCount)\Filename = sCharA1(xLong5)
                PLI(PLCount)\Caption = SimpleFile(sCharA1(xLong5))
                PLI(PLCount)\DirDepthFlags = xLong4 ;+ 1
                CompilerElse
                PLIFile(PLCount) = sCharA1(xLong5)
                PLICap(PLCount) = SimpleFile(sCharA1(xLong5))
                PLIDF(PLCount) = xLong4 ;+ 1
                CompilerEndIf
              PLCount = PLCount + 1
              sCharA1(xLong5) = ""
              ElseIf Not Left(xChar3, xLong3) = xChar2
              Break
              EndIf
            EndIf
          Next
        EndIf
      EndIf
    
    If PLCount = PLCountMax
      For xLong2 = 0 To ArraySize - 1
        If Not Len(sCharA1(xLong2)) = 0
          xChar1 = LCase(SimpleDir(sCharA1(xLong2))) + "\"
          If Not xChar1 = xChar2
            ;is more parent?
            If Not Left(xChar1, xLong3) = xChar2
              While (Not Left(xChar1, xLong3) = xChar2)
                xLong4 = xLong4 - 1
                xLong3 = InstrRevChar(xChar2, 92, xLong3 - 1) ; "\"
                If xLong3 = 0
                  xChar2 = ""
                  Break
                  Else
                  xChar2 = Left(xChar2, xLong3)
                  If xChar2 = "\\"
                    xChar2 = "": xLong3 = 0
                    EndIf
                  EndIf
                Wend
              EndIf
            If Not xChar1 = xChar2
              ;is a subdir of current!
              If Left(xChar1, xLong3) = xChar2
                xChar1 = Mid(sCharA1(xLong2), xLong3 + 1) ; + "\" ;last "\" is filename seperator
                ;If Not xLong3 = 0
                  ;xLong3 = xLong3 - 1
                  ;EndIf
                Repeat
                  xLong5 = FindString(xChar1, "\")
                  If xLong5 = 1
                    xLong5 = FindString(xChar1, "\", 3)
                    EndIf
                  If xLong5 = 0
                    Break
                    EndIf
                  CompilerIf #BoldDirs = 98
                    PLI(PLCount)\Caption = Left(xChar1, xLong5 - 1)
                    PLI(PLCount)\DirDepthFlags = #PLI_IsDir | xLong4
                    xLong4 = xLong4 + 1
                    CompilerElse
                    PLICap(PLCount) = Left(xChar1, xLong5 - 1)
                    PLIDF(PLCount) = #PLI_IsDir | xLong4
                    xLong4 = xLong4 + 1
                    CompilerEndIf
                  xLong3 = xLong3 + xLong5
                  CompilerIf #BoldDirs = 98
                    PLI(PLCount)\Filename = Left(sCharA1(xLong2), xLong3 - 1)
                    CompilerElse
                    PLIFile(PLCount) = Left(sCharA1(xLong2), xLong3 - 1)
                    CompilerEndIf
                  xChar1 = Mid(xChar1, xLong5 + 1)
                  PLCount = PLCount + 1
                  If PLCount = PLCountMax
                    Break
                    EndIf
                  xChar2 = LCase(Left(sCharA1(xLong2), xLong3 - 1)) + "\"
                  
                  For xLong5 = xLong2 To ArraySize - 1
                    If Not sCharA1(xLong5) = ""
                      xChar3 = LCase(SimpleDir(sCharA1(xLong5))) + "\"
                      If xChar3 = xChar2
                        CompilerIf #BoldDirs = 98
                          PLI(PLCount)\Filename = sCharA1(xLong5)
                          PLI(PLCount)\Caption = SimpleFile(sCharA1(xLong5))
                          PLI(PLCount)\DirDepthFlags = xLong4 ; + 1
                          CompilerElse
                          PLIFile(PLCount) = sCharA1(xLong5)
                          PLICap(PLCount) = SimpleFile(sCharA1(xLong5))
                          PLIDF(PLCount) = xLong4 ; + 1
                          CompilerEndIf
                        PLCount = PLCount + 1
                        If Not xLong5 = xLong2
                          sCharA1(xLong5) = ""
                          EndIf
                        ElseIf Not Left(xChar3, xLong3) = xChar2
                        Break
                        EndIf
                      EndIf
                    Next
                  ForEver
                EndIf
              EndIf
            If PLCount = PLCountMax
              Break
              EndIf
            xChar2 = LCase(SimpleDir(sCharA1(xLong2))) + "\"
            xLong3 = Len(xChar2)
            EndIf
          EndIf
        Next
      EndIf

    If PLCount = PLCountMax
      While PLCount
CompilerIf #BoldDirs = 98
        If (PLI(PLCount - 1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
        If (PLIDF(PLCount - 1) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
          PLCount = PLCount - 1
          Else
          Break
          EndIf
        Wend
      EndIf
    
    If Not NoApply
      RealPLAdd(xLong6)
      EndIf
    EndIf
  ;Erase sCharA1()
  ;Dim sCharA1(sCharA1MaxX)
  EndProcedure

Procedure RemoveFromSearch(Index.i)
  Define.i xLong1
  Define.i xLong2

  If InterfaceMode = #Interface_Mode_Search
    For xLong1 = 0 To xSearchCount - 1
      If xSearch(xLong1) = Index
        ;PLRemoveShifted1 = xLong2
        RemoveListItemMS(Interface_Control(#Interface_Control_Search_Results), xLong2)
        ElseIf xSearch(xLong1) > Index
        xSearch(xLong2) = xSearch(xLong1) - 1
        xSearchSortAlias(xLong2) = xSearchSortAlias(xLong1)
        SendMessage_(Interface_Control(#Interface_Control_Search_Results), $19A, xLong2, xLong2)
        xLong2 = xLong2 + 1
        Else
        xSearch(xLong2) = xSearch(xLong1)
        xSearchSortAlias(xLong2) = xSearchSortAlias(xLong1)
        SendMessage_(Interface_Control(#Interface_Control_Search_Results), $19A, xLong2, xLong2)
        xLong2 = xLong2 + 1
        EndIf
      Next
    xSearchCount = xLong2
    EndIf
  EndProcedure

CompilerIf #UseFileLogging
  Procedure CheckSync()
    Define.i xBool1
    Define.i xLong1
    
    If PLCount = SendMessage_(xListHWnd(2), #LB_GETCOUNT, 0, 0)
      xBool1 = #True
      For xLong1 = 0 To PLCount - 1
CompilerIf #BoldDirs = 98
        If Not SendMessage_(xListHWnd(2), #LB_GETITEMDATA, xLong1, 0) = xLong1
          Debug "OutOfSync (" + Str(xLong1) + ", but is " + Str(SendMessage_(xListHWnd(2), #LB_GETITEMDATA, xLong1, 0)) + ")"
          Debug "  Affects / " + PLI(xLong1)\Filename
          Debug "      File: " + PLI(xLong1)\Caption
CompilerElse
        If Not SendMessage_(xListHWnd(2), #LB_GETITEMDATA, xLong1, 0) = xLong1
          Debug "OutOfSync (" + Str(xLong1) + ", but is " + Str(SendMessage_(xListHWnd(2), #LB_GETITEMDATA, xLong1, 0)) + ")"
          Debug "  Affects / " + PLIFile(xLong1)
          Debug "      File: " + PLICap(xLong1)
CompilerEndIf
          xBool1 = #False
          EndIf
        Next
      EndIf
    If Not xBool1
      MainForm_ctConsoleA_AddLog("###### Playlist out of sync !!!!")
      MessageBox_(MainHWnd, @"Playlist out of sync, please clear playlist; please report this error", @"Warning", #MB_ICONEXCLAMATION)
      EndIf
    EndProcedure
  CompilerEndIf

Procedure CheckEmptyNodes(NoUpdateList.i, UpdateBeginn.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xCaret
  Define.i xCaretOld
  
  If LockWinUpd And Not NoUpdateList
    LockWindowUpdate_(xListHWnd(2))
    EndIf
  
  xCaret = SendMessage_(xListHWnd(2), #LB_GETCARETINDEX, 0, 0)
  xCaretOld = xCaret
  
  UpdateBeginn = -1
  ;If NoUpdateList
    ;If UpdateBeginn = -1
    ;xLong1 = -1
    ;xLong2 = PLCount - 1
    ;PLCount = 0
    xLong1 = UpdateBeginn
    xLong2 = PLCount - 1
    PLCount = UpdateBeginn + 1
    While xLong1 <> xLong2
      xLong1 = xLong1 + 1
      ;For xLong1 = PLCount - 1 To 0 Step -1
CompilerIf #BoldDirs = 98
      If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
      If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
        If xLong1 = xLong2
          While PLCount
CompilerIf #BoldDirs = 98
            If (PLI(PLCount - 1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
            If (PLIDF(PLCount - 1) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
              PLCount = PLCount - 1
              If Not NoUpdateList
                ;RemoveListItemMS
                RemoveFromSearch(PLCount)
                ;PLRemoveShifted1 = PLCount
                ;PLRemoveShifted2 = xLong1
                SendMessage_(xListHWnd(2), #LB_DELETESTRING, PLCount, 0)
                If xCaret >= PLCount
                  xCaret = xCaret - 1
                  EndIf
                If LockWinUpd = 0
                  DoEventsEx_SleepPeriodical()
                  ElseIf LockWinUpd = 1
                  DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
                  EndIf
                EndIf
              Else
              Break
              EndIf
            Wend
          If Not NoUpdateList
            ;RemoveListItemMS
            RemoveFromSearch(PLCount)
            ;PLRemoveShifted1 = PLCount
            ;PLRemoveShifted2 = xLong1
            SendMessage_(xListHWnd(2), #LB_DELETESTRING, PLCount, 0)
            If xCaret >= PLCount
              xCaret = xCaret - 1
              EndIf
            If LockWinUpd = 0
              DoEventsEx_SleepPeriodical()
              ElseIf LockWinUpd = 1
              DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
              EndIf
            EndIf
          Break
          Else
          CompilerIf #BoldDirs = 98
            CopyStructureEx(PLI(xLong1), PLI(PLCount), tPlaylistItem)
            SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
            CompilerElse
            PLIFile(PLCount) = PLIFile(xLong1)
            PLICap(PLCount) = PLICap(xLong1)
            PLIDF(PLCount) = PLIDF(xLong1)
            PLIPxLg(PLCount) = PLIPxLg(xLong1)
            PLIPxSm(PLCount) = PLIPxSm(xLong1)
            SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
            CompilerEndIf
          PLCount = PLCount + 1
          While PLCount
CompilerIf #BoldDirs = 98
            If (PLI(xLong1 + 1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir And (PLI(PLCount - 1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
              If (PLI(PLCount - 1)\DirDepthFlags & #PLI_Depth) < (PLI(xLong1 + 1)\DirDepthFlags & #PLI_Depth)
CompilerElse
            If (PLIDF(xLong1 + 1) & #PLI_IsDir) = #PLI_IsDir And (PLIDF(PLCount - 1) & #PLI_IsDir) = #PLI_IsDir
              If (PLIDF(PLCount - 1) & #PLI_Depth) < (PLIDF(xLong1 + 1) & #PLI_Depth)
CompilerEndIf
                Break
                Else
                PLCount = PLCount - 1
                If Not NoUpdateList
                  ;RemoveListItemMS
                  RemoveFromSearch(PLCount)
                  ;PLRemoveShifted1 = PLCount
                  ;PLRemoveShifted2 = xLong1
                  SendMessage_(xListHWnd(2), #LB_DELETESTRING, PLCount, 0)
                  If xCaret >= PLCount
                    xCaret = xCaret - 1
                    EndIf
                  If LockWinUpd = 0
                    DoEventsEx_SleepPeriodical()
                    ElseIf LockWinUpd = 1
                    DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
                    EndIf
                  EndIf
                EndIf
              Else
              Break
              EndIf
            Wend
          EndIf
        Else
        CompilerIf #BoldDirs = 98
          CopyStructureEx(PLI(xLong1), PLI(PLCount), tPlaylistItem)
          SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
          CompilerElse
          PLIFile(PLCount) = PLIFile(xLong1)
          PLICap(PLCount) = PLICap(xLong1)
          PLIDF(PLCount) = PLIDF(xLong1)
          PLIPxLg(PLCount) = PLIPxLg(xLong1)
          PLIPxSm(PLCount) = PLIPxSm(xLong1)
          SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
          CompilerEndIf
        If PLCurItem = xLong1
          PLCurItem = PLCount
          EndIf
        If PLNext = xLong1
          PLNext = PLCount
          EndIf
        PLCount = PLCount + 1
        EndIf
      Wend
    ;PLRemoveShifted1 = $7FFFFFFF
  
  If Not (PLCount = 0 Or xCaret = xCaretOld)
    If xCaret > PLCount - 1
      xCaret = PLCount - 1
      EndIf
    If xCaret < 0
      xCaret = 0
      EndIf
    SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xCaret, 0)
    EndIf
  
  ; Always required as this func. is called after items are removed,
  ; but not checked before because this func. also may have to do...
  ; -> This func. Always has to do !!!
  If Not NoUpdateList
    MainForm_xBuildDirs()
    EndIf
  
  CompilerIf #UseFileLogging
    If Not NoUpdateList
      CheckSync()
      EndIf
    CompilerEndIf
  EndProcedure

Procedure InitCPList()
  ;CPListText = etext.Text
  If Not CPListMustDo
    xSearchError = LoadResString(2320)
    CPListMustDo = #True
    CPListTime = GetTickTimeMS()
    SendMessage_(Interface_Control(#Interface_Control_Search_Results), $184, 0, 0)
    EnableWindow_(Interface_Control(#Interface_Control_Search_Results), 0)
    EnableWindow_(Interface_Control(#Interface_Control_Search_Play), 0)
    EnableWindow_(Interface_Control(#Interface_Control_Search_Select), 0)
    CompilerIf #True
      ;SendMessage_String(Interface_Control(#Interface_Control_Search_Results), #LB_ADDSTRING, 0, -1)
      SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_ADDSTRING, 0, -1)
      CompilerElse
      SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_ADDSTRING, 0, @xSearchError)
      CompilerEndIf
    EndIf
  EndProcedure

Procedure InitResearchClear()
  If InterfaceMode = #Interface_Mode_Search
    InitCPList()
    EndIf
  ;CheckWizard
  EndProcedure

Procedure SortSearchResults()
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.i xLong5
  Define.i ElementsToSort

  ElementsToSort = xSearchCount - 1
  For xLong2 = 0 To ElementsToSort
    xSearchSortAlias(xLong2) = xLong2
    CompilerIf #BoldDirs = 98
      xSearchSortCap(xLong2) = PLI(xSearch(xLong2))\Caption
      If (PLI(xSearch(xLong2))\DirDepthFlags & #PLI_IsDir) = 0
        xSearchSortDir(xLong2) = -3
        ElseIf PLIconFolder = 0
        xSearchSortDir(xLong2) = #PLIconFolderFake
        Else
        xSearchSortDir(xLong2) = PLIconFolder
        EndIf
      CompilerElse
      xSearchSortCap(xLong2) = PLICap(xSearch(xLong2))
      If (PLIDF(xSearch(xLong2)) & #PLI_IsDir) = 0
        xSearchSortDir(xLong2) = -3
        ElseIf PLIconFolder = 0
        xSearchSortDir(xLong2) = #PLIconFolderFake
        Else
        xSearchSortDir(xLong2) = PLIconFolder
        EndIf
      CompilerEndIf
    Next
  Repeat
    xLong1 = 3 * xLong1 + 1
    Until xLong1 > ElementsToSort
  Repeat
    xLong1 = Int(xLong1 / 3)
    For xLong2 = xLong1 To ElementsToSort
      xLong4 = xSearchSortAlias(xLong2)
      xLong5 = xSearch(xLong2)
      xLong3 = xLong2 - xLong1
      While xLong3 > 0
        ;If StrComp(xSearchSortCap(xSearchSortAlias(xLong3)), xSearchSortCap(xLong4), #PB_String_NoCase) < 1
        If CompareMemoryString(@xSearchSortCap(xSearchSortAlias(xLong3)), @xSearchSortCap(xLong4), #PB_String_NoCase) < 1
          Break
          EndIf
        xSearchSortAlias(xLong3 + xLong1) = xSearchSortAlias(xLong3)
        xSearch(xLong3 + xLong1) = xSearch(xLong3)
        xLong3 - xLong1
        Wend
      xSearchSortAlias(xLong3 + xLong1) = xLong4
      xSearch(xLong3 + xLong1) = xLong5
      Next
    Until xLong1=0
  EndProcedure

Procedure MainForm_TrySearch(Force.i) ;(TryAddList As Boolean)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.i xLong5
  Define.i xLong6
  Define.s xChar1
  Define.i xBool2
  Dim xLongA1.i(15)
  Dim xCharA1.s(15)
  Dim xCharA2.s(15)
  
  If Force Or Not (PlayerIsLocked Or xAutoDoing)
    SendMessage_(Interface_Control(#Interface_Control_Search_Results), $184, 0, 0)
    xSearchCount = 0
    If Len(Trim(CPListText)) = 0
      xLong5 = -3
      Else
      xSearchCount = 0
      xChar1 = LCase(CPListText) + ";"
      xLong3 = -1
      Repeat
        xLong1 = FindString(xChar1, ";")
        If xLong1 = 0
          Break
          EndIf
        xCharA1(xLong2) = Trim(Left(xChar1, xLong1 - 1))
        If Not xCharA1(xLong2) = ""
          Select Asc(xCharA1(xLong2))
            Case 43 ;+
              xCharA1(xLong2) = LTrim(Mid(xCharA1(xLong2), 2))
              If Not xCharA1(xLong2) = ""
                xLongA1(xLong2) = 1
                xLong3 = xLong2
                xBool2 = #True
                xLong2 = xLong2 + 1
                EndIf
            Case 45 ;-
              xCharA1(xLong2) = LTrim(Mid(xCharA1(xLong2), 2))
              If Not xCharA1(xLong2) = ""
                xLongA1(xLong2) = 2
                xLong2 = xLong2 + 1
                EndIf
            Default
              If Not xCharA1(xLong2) = ""
                xLongA1(xLong2) = 0
                If Not xBool2
                  xLong3 = xLong2
                  EndIf
                xCharA2(xLong6) = xCharA1(xLong2)
                xLong6 = xLong6 + 1
                xLong2 = xLong2 + 1
                EndIf
            EndSelect
          If xLong2 = 16
            xLong5 = -2
            Break
            EndIf
          EndIf
        xChar1 = Mid(xChar1, xLong1 + 1)
        ForEver
      ;If xLong3 = -1
      ;  endif
      
      If Not (xLong2 = 0 Or xLong3 = -1 Or xLong2 = 16)
        xLong2 = xLong2 - 1
        For xLong1 = 0 To PLCount - 1
CompilerIf #BoldDirs = 98
          If FindString(LCase(PLI(xLong1)\Caption), xCharA1(xLong3), 1, #PB_String_NoCase) Or (xLong6 > 1 And Not xBool2)
CompilerElse
          If FindString(LCase(PLICap(xLong1)), xCharA1(xLong3), 1, #PB_String_NoCase) Or (xLong6 > 1 And Not xBool2)
CompilerEndIf
            xLong5 = 0
            ; 0 = or found
            ; 1 = need
            ; 2 = must not
            
            ; 0 = init
            ;-1 = nomatch
            ;-2 = parseerror
            ; 1 = limitedfound
            For xLong4 = 0 To xLong2
CompilerIf #BoldDirs = 98
              If FindString(PLI(xLong1)\Caption, xCharA1(xLong4), 1, #PB_String_NoCase) = 0
CompilerElse
              If FindString(PLICap(xLong1), xCharA1(xLong4), 1, #PB_String_NoCase) = 0
CompilerEndIf
                If xLongA1(xLong4) = 1
                  xLong5 = -1
                  Break
                  EndIf
                ElseIf xLongA1(xLong4) = 0
                xLong5 = 1
                ;ElseIf xLongA1(xLong4) = 1
                ElseIf xLongA1(xLong4) = 2
                xLong5 = -1
                Break
                EndIf
              Next
            If xLong5 = 1 Or (xLong5 = 0 And xLong6 = 0)
              If xSearchCount = #xSearchCountMax
                xSearchCount = #xSearchCountOver
                Break
                Else
                xSearch(xSearchCount) = xLong1
                ;If Asc(PLItem(xLong1)) = 0
                ;  xSearch(xSearchCount) = SimpleFile(PLItem(xLong1)) & vbNullChar & Mid(PLItem(xLong1), 3) & vbNullChar & Chr(1) & CStr(xLong1)
                ;  Else
                ;  xSearch(xSearchCount) = SimpleFile(PLItem(xLong1)) & vbNullChar & Mid(PLItem(xLong1), 3) & vbNullChar & vbNullChar & CStr(xLong1)
                ;  endif
                xSearchCount = xSearchCount + 1
                EndIf
              EndIf
            EndIf
          Next
        Else
        xLong5 = -2
        EndIf
      EndIf
    If (xSearchCount = 0 Or xSearchCount = #xSearchCountOver)
      EnableWindow_(Interface_Control(#Interface_Control_Search_Results), 0)
      EnableWindow_(Interface_Control(#Interface_Control_Search_Play), 0)
      EnableWindow_(Interface_Control(#Interface_Control_Search_Select), 0)
      Else
      EnableWindow_(Interface_Control(#Interface_Control_Search_Results), 1)
      EnableWindow_(Interface_Control(#Interface_Control_Search_Play), 1)
      EnableWindow_(Interface_Control(#Interface_Control_Search_Select), 1)
      EndIf
    SelectObject_(xSharedDC, hFontPLLgB)
    If xSearchCount = 0
      If xLong5 = -3
        xSearchError = LoadResString(2324)
        ElseIf xLong5 = -2
        xSearchError = LoadResString(2323)
        Else
        xSearchError = LoadResString(2321)
        EndIf
      xLong4 = GetTextOutWidth(xSharedDC, xSearchError)
      SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_ADDSTRING, 0, -1)
      Else
      If xSearchCount = #xSearchCountOver
        xSearchError = LoadResString(2322)
        xLong4 = GetTextOutWidth(xSharedDC, xSearchError)
        SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_ADDSTRING, 0, -1)
        Else
        
        
        SortSearchResults()
;        ArraySort_StringSearch
        
        
        For xLong1 = 0 To xSearchCount - 1
CompilerIf #BoldDirs = 98
          xChar1 = PLI(xSearch(xLong1))\Caption
          SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_ADDSTRING, 0, xLong1)
          xLong5 = PLI(xSearch(xLong1))\pxWidthLg
CompilerElse
          xChar1 = PLICap(xSearch(xLong1))
          SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_ADDSTRING, 0, xLong1)
          xLong5 = PLIPxLg(xSearch(xLong1))
CompilerEndIf
          If xLong5 > xLong4
            xLong4 = xLong5
            EndIf
          Next
        SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_SETCARETINDEX, 0, 0)
        SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_SETSEL, 1, 0)
        MainForm_CheckDir(#False)
        xLong4 = 24 + xLong4
        EndIf
      EndIf
    xLong4 = 4 + xLong4
    SendMessage_(Interface_Control(#Interface_Control_Search_Results), $194, #lWidth + xLong4, 0)
    ;eButton(3).Enabled = Not (xSearchOldQueriesCount = 0)
    
    CPListMustDo = #False
;    DoSearchAddEx ;TryAddList
    EndIf
  EndProcedure

Procedure InitResearch(Force.i)
  If InterfaceMode = #Interface_Mode_Search
    MainForm_TrySearch(Force)
    EndIf
  ;CheckWizard
  EndProcedure

Procedure CheckOldItems()
  Define.i xLong1
  
  CompilerIf #UseFileLogging
    Define.i xLong2
    CompilerEndIf
  
  If Not PLCurItem < PLCount
    PLCurItem = 0
    EndIf
  If Not PLNext < PLCount
    PLNext = 0
    EndIf
  
  If Not PLCount = 0
CompilerIf #BoldDirs = 98
    If Not UCase(PLI(PLCurItem)\Filename) = PLCurSong
CompilerElse
    If Not UCase(PLIFile(PLCurItem)) = PLCurSong
CompilerEndIf
      CompilerIf #UseFileLogging
        xLong2 = PLCurItem
        CompilerEndIf
      xLong1 = xFindSong()
      If Not xLong1 = 0
        PLCurItem = xLong1
        EndIf
      If Not PLCurItem = 0
        Repeat
CompilerIf #BoldDirs = 98
          If (PLI(PLCurItem)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
          If (PLIDF(PLCurItem) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
            PLCurItem = PLCurItem + 1
            Else
            Break
            EndIf
          ForEver
        EndIf
      CompilerIf #UseFileLogging
        If Not xLong2 = PLCurItem
          MainForm_ctConsoleA_AddLog("CheckOldItems procedur (PLCurItem: " + Str(xLong2) + " -> " + Str(PLCurItem) + ")")
          EndIf
        CompilerEndIf
      EndIf
    If Not PlNextSong = ""
CompilerIf #BoldDirs = 98
      If Not UCase(PLI(PLNext)\Filename) = PlNextSong
CompilerElse
      If Not UCase(PLIFile(PLNext)) = PlNextSong
CompilerEndIf
        CompilerIf #UseFileLogging
          xLong2 = PLNext
          CompilerEndIf
        PLNext = xFindSong(PlNextSong)
        CompilerIf #UseFileLogging
          If Not xLong2 = PLCurItem
            MainForm_ctConsoleA_AddLog("CheckOldItems procedur (PLNext: " + Str(xLong2) + " -> " + Str(PLNext) + ")")
            EndIf
          CompilerEndIf
        If PLNext = 0
          SetNextSong(#False)
          EndIf
        EndIf
      EndIf
    EndIf
  ;CheckWizard
  EndProcedure

Procedure xRemoveAutoRefresh(WhatToRemove.i, NoUpdating.i, NoCheckOldItems.i)
  Define.i xLong1
  Define.i xLong2
;define.s xChar1
  Define.i xCaret
  Define.i xCaretOld

  ReAutoPlayDR = #False
  
  If WhatToRemove = 0
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Removing Non-Refresh songs")
      CompilerEndIf
    Else
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Removing AutoRefresh songs")
      CompilerEndIf
    EndIf
  
  xLong1 = PLCount
  PLCount = 0
  If NoUpdating
    xLong2 = xLong1 - 1
    For xLong1 = 0 To xLong2
CompilerIf #BoldDirs = 98
      If (PLI(xLong1)\DirDepthFlags & #PLI_IsAuto) = WhatToRemove
        CopyStructureEx(PLI(xLong1), PLI(PLCount), tPlaylistItem)
        SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
CompilerElse
      If (PLIDF(xLong1) & #PLI_IsAuto) = WhatToRemove
        PLIFile(PLCount) = PLIFile(xLong1)
        PLICap(PLCount) = PLICap(xLong1)
        PLIDF(PLCount) = PLIDF(xLong1)
        PLIPxLg(PLCount) = PLIPxLg(xLong1)
        PLIPxSm(PLCount) = PLIPxSm(xLong1)
        SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
CompilerEndIf
        PLCount = PLCount + 1
        EndIf
      Next
    Else
    InitResearchClear()
    If LockWinUpd
      LockWindowUpdate_(xListHWnd(2))
      EndIf
    xCaret = SendMessage_(xListHWnd(2), #LB_GETCARETINDEX, 0, 0)
    xCaretOld = xCaret
    xLong2 = xLong1 - 1
    For xLong1 = 0 To xLong2
CompilerIf #BoldDirs = 98
      If (PLI(xLong1)\DirDepthFlags & #PLI_IsAuto) = WhatToRemove
CompilerElse
      If (PLIDF(xLong1) & #PLI_IsAuto) = WhatToRemove
CompilerEndIf
        ;RemoveListItemMS
        ;PLRemoveShifted1 = PLCount
        ;PLRemoveShifted2 = xLong1
        SendMessage_(xListHWnd(2), #LB_DELETESTRING, PLCount, 0)
        If xCaret >= PLCount
          xCaret = xCaret - 1
          EndIf
        Else
        CompilerIf #BoldDirs = 98
          CopyStructureEx(PLI(xLong1), PLI(PLCount), tPlaylistItem)
          SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
          CompilerElse
          PLIFile(PLCount) = PLIFile(xLong1)
          PLICap(PLCount) = PLICap(xLong1)
          PLIDF(PLCount) = PLIDF(xLong1)
          PLIPxLg(PLCount) = PLIPxLg(xLong1)
          PLIPxSm(PLCount) = PLIPxSm(xLong1)
          SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
          CompilerEndIf
        PLCount = PLCount + 1
        EndIf
      CompilerIf #LockWinUpd = 0
        If xLong1 % $7f = 0
          DoEventsEx_SleepPeriodicalLW(0)
          EndIf
        CompilerEndIf
      Next
    ;PLRemoveShifted1 = $7FFFFFFF
    If Not (PLCount = 0 Or xCaret = xCaretOld)
      If xCaret > PLCount - 1
        xCaret = PLCount - 1
        EndIf
      If xCaret < 0
        xCaret = 0
        EndIf
      SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xCaret, 0)
      EndIf
    If LockWinUpd
      LockWindowUpdate_(0)
      EndIf
    InitResearch(#False)
    EndIf
  If Not NoCheckOldItems
    CheckOldItems()
    EndIf
  EndProcedure

Procedure ReadDirInit()
  If *TasBarPrg
    TaskBarProgress_SetProgress(*TasBarPrg, MainHWnd, 0, #xDefBWDifC)
    TaskBarProgress_SetState(*TasBarPrg, MainHWnd, #TBPF_Normal)
    TaskBarProgress_SetProgress(*TasBarPrg, MainHWnd, 0, #xDefBWDifC)
    EndIf
  xCurBWPos = 0
  xIsActiveBW = #True
  ;Form1.Visible = #True
  SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Anim), 0, 0, 0, 32, #AnimHeightAnimProg, $216)
  DoAnimateReadDir(0)
  EndProcedure

Procedure ReadDirDone()
  xIsActiveBW = #False
  ;DoAnimateReadDir(0)
  SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Anim), 0, 0, 0, 32, #AnimHeightAnimOnly, $216)
  DoAnimateReadDir(0)
  If *TasBarPrg
    TaskBarProgress_SetProgress(*TasBarPrg, MainHWnd, 0, #xDefBWDifC)
    TaskBarProgress_SetState(*TasBarPrg, MainHWnd, #TBPF_NoProgress)
    EndIf
  EndProcedure

Procedure ReadDirectory(BaseDir.s, Spaces.i, IsMainDir.i, AsAutoRefresh.i, xCur.i, xDif.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  ;Dim xLong5.i
  Define.i xLong10
  Define.i xLong11
  Define.s xChar1
  ;define.s xChar2
    
  CompilerIf #CanEnumComputerShares
    ;Static lpBuff.i
    Define.i cbBuff
    Define.sNETRESOURCE mvNetRes
    CompilerEndIf
  
  
  Define.s xChar3
  Static xArrayCount.i
  Define.i ReadDirectory_xArraySCount
  Define.WIN32_FIND_DATA xType1
  ;Dim xReadCDTracks As Boolean
  
  xLong11 = xArrayCount
  
  CompilerIf #BoldDirs = 98
    PLI(PLCount)\Filename = BaseDir
    CompilerElse
    PLIFile(PLCount) = BaseDir
    CompilerEndIf
  
  xChar1 = BaseDir
  If IsMainDir
    If Right(BaseDir, 1) = "\"
      BaseDir = Left(BaseDir, Len(BaseDir) - 1)
      EndIf
    Else
    xChar1 = SimpleFile(xChar1)
    EndIf
  
  CompilerIf #BoldDirs = 98
    PLI(PLCount)\Caption = xChar1
    PLI(PLCount)\DirDepthFlags = Spaces | #PLI_IsDir | AsAutoRefresh
    CompilerElse
    PLICap(PLCount) = xChar1
    PLIDF(PLCount) = Spaces | #PLI_IsDir | AsAutoRefresh
    CompilerEndIf
  PLCount = PLCount + 1
  xLong10 = PLCount
  Spaces = Spaces + 1

CompilerIf #CanEnumComputerShares
  If Left(BaseDir, 2) = "\\" And FindString(3, BaseDir, "\") = 0
    ;xChar1 = BaseDir
;    xLong1 = Len(BaseDir)
    With mvNetRes
      .dwScope = 2
      .dwType = 1
      .dwDisplayType = 2
      .dwUsage = 2
;      .lpRemoteName = LocalAlloc($40, xLong1 + 1)
      .lpRemoteName = LocalAllocFromString(BaseDir)
;      RtlMoveMemory(.lpRemoteName, BaseDir, xLong1)
      End With
    
    If Not mvNetRes.lpRemoteName = 0
      If IsUnicode
        xLong2 = WNetOpenEnumW($2, $1, 0, mvNetRes, xLong1)
        Else
        xLong2 = WNetOpenEnumA($2, $1, 0, mvNetRes, xLong1)
        EndIf
      LocalFree_(mvNetRes.lpRemoteName)
      If xLong2 = 0
        ;LocalFree_(mvNetRes.lpRemoteName)
        ;cbBuff = 1024
        ;lpBuff = LocalAlloc($40, cbBuff)
        Do
          xLong2 = $FFFFFFFF
          If IsUnicode
            cbBuff = ptrTempSizeXW
            xLong3 = WNetEnumResourceW(xLong1, xLong2, ptrTemp, cbBuff)
            Else
            cbBuff = ptrTempSizeX
            xLong3 = WNetEnumResourceA(xLong1, xLong2, ptrTemp, cbBuff)
            EndIf
          If xLong3 = 0
            For xLong3 = 0 To xLong2 - 1
              RtlMoveMemory(mvNetRes, (ptrTemp + xLong3 * sNETRESOURCE_Len), sNETRESOURCE_Len)
              xChar1 = LCase(Mid(PeekSA(mvNetRes.lpRemoteName), Len(BaseDir) + 2))
              If (Left(xChar1, 1) = "."
                ElseIf (Left(xChar1, 1) = "#" Or Left(xChar1, 1) = "_") And IgnoreUnderscored
                ElseIf xArrayCount < sCharA1Max
                sCharA1(xArrayCount) = BaseDir + "\" & xChar1
                xArrayCount = xArrayCount + 1
                EndIf
              Next
            EndIf
          Loop Until xLong2 = 0
        WNetCloseEnum(xLong1)
        ;LocalFree lpBuff
        ;Else
        ;LocalFree_(mvNetRes.lpRemoteName)
        EndIf
      EndIf
  
  
    Else
CompilerEndIf
    xType1\dwFileAttributes = $3F
    xLong1 = FindFirstFile_(BaseDir + "\*.*", @xType1)
    If Not xLong1 = -1
      Repeat
        xChar1 = PeekS(@xType1\cFileName)
;Debug "Parsing " + BaseDir + ", " + xChar1
        If Left(xChar1, 1) = "."
          ElseIf ((xType1\dwFileAttributes & 2) Or Left(xChar1, 1) = "#" Or Left(xChar1, 1) = "_") And IgnoreUnderscored
          ElseIf (xType1\dwFileAttributes & $10)
          If (xType1\dwFileAttributes & $14) = $10 And xArrayCount < sCharA1Max
            sCharA1(xArrayCount) = BaseDir + "\" + xChar1
            xArrayCount = xArrayCount + 1
            EndIf
          ElseIf ReadDirectory_xArraySCount < #ReadDirectory_xArraySMax
          If AllowedItemSongFast(xChar1, #False)
            ReadDirectory_xArrayS(ReadDirectory_xArraySCount) = xChar1
            ReadDirectory_xArraySCount = ReadDirectory_xArraySCount + 1
            EndIf
          EndIf
        If ((ReadDirectory_xArraySCount + xArrayCount) & $3f) = 3
          DoEventsEx_SleepPeriodicalLW(0)
          EndIf
        Until FindNextFile_(xLong1, xType1) = 0
      FindClose_(xLong1)
      EndIf
CompilerIf #CanEnumComputerShares
    EndIf
CompilerEndIf

DoEventsEx_SleepPeriodicalLW(0)

;If xReadCDTracks


xChar3 = BaseDir + "\"

If xSorting
  ;ArraySort_String_IC(ReadDirectory_xArrayS(), ReadDirectory_xArraySCount)
  SortArray(ReadDirectory_xArrayS(), #PB_Sort_Ascending | #PB_Sort_NoCase, 0, ReadDirectory_xArraySCount - 1)
  EndIf
For xLong1 = 0 To ReadDirectory_xArraySCount - 1
  xChar1 = ReadDirectory_xArrayS(xLong1)
  CompilerIf #BoldDirs = 98
    PLI(PLCount)\Filename = xChar3 + ReadDirectory_xArrayS(xLong1)
    PLI(PLCount)\Caption = ReadDirectory_xArrayS(xLong1)
    PLI(PLCount)\DirDepthFlags = Spaces | AsAutoRefresh
    CompilerElse
    PLIFile(PLCount) = xChar3 + ReadDirectory_xArrayS(xLong1)
    PLICap(PLCount) = ReadDirectory_xArrayS(xLong1)
    PLIDF(PLCount) = Spaces | AsAutoRefresh
    CompilerEndIf
  PLCount = PLCount + 1
  If PLCount = PLCountMax
    Break
    EndIf
  If xLong1 % $1f = 0
    DoEventsEx_SleepPeriodicalLW(0)
    If AbortReading
      Break
      EndIf
    EndIf
  Next

DoEventsEx_SleepPeriodicalLW(0)

If PLCount < PLCountMaxX And Not AbortReading
  If xSorting
    ;ArraySort_String_StartPos_IC(sCharA1(), xArrayCount - xLong11, xLong11)
    SortArray(sCharA1(), #PB_Sort_Ascending | #PB_Sort_NoCase, xLong11, xArrayCount - xLong11 - 1)
    EndIf
  xLong2 = xArrayCount - 1
  For xLong1 = xLong11 To xLong2
    DoEventsEx_SleepPeriodicalLW(0)
    If AbortReading Or PLCount > PLCountMaxX2
      Break
      EndIf
    ReadDirectory(sCharA1(xLong1), Spaces, 0, AsAutoRefresh, Int(xCur + (xDif * (xLong1 - xLong11)) / (xArrayCount - xLong11)), Int(xDif / (xArrayCount - xLong11)))
    Next
  xCurBWPos = xCur + xDif
  EndIf

If xLong10 = PLCount
  PLCount = PLCount - 1
  EndIf

xArrayCount = xLong11
;If xlong11 = 0
;  Erase sCharA1()
;  endif

;endif
EndProcedure

Procedure.i RandomSong()
  Define.i xResult
  Define.i xLong1
  
  If Not PLCount = 0
    If xRemovePlayedSongs And xRemoveSkippedSongs
      GrabError()
      Repeat
        xResult = Int(GetLocalTimeHMS_HS() + URndDnP(PLCount)) % PLCount
        CompilerIf #BoldDirs = 98
          If (PLI(xResult)\DirDepthFlags & #PLI_IsDir) = 0
            Break
            EndIf
          CompilerElse
          If (PLIDF(xResult) & #PLI_IsDir) = 0
            Break
            EndIf
          CompilerEndIf
        ForEver
      Else
      xLong1 = Int(PLCount / #RandomizerPattern)
      Repeat
        xResult = URndDnP(xLong1 + 1)
        RndPLPattern(xResult) = (RndPLPattern(xResult) + 1) % #RandomizerPattern
        xResult = xResult * #RandomizerPattern + RndPatternAlias(RndPLPattern(xResult))
        If xResult < PLCount
          CompilerIf #BoldDirs = 98
            If (PLI(xResult)\DirDepthFlags & #PLI_IsDir) = 0
              Break
              EndIf
            CompilerElse
            If (PLIDF(xResult) & #PLI_IsDir) = 0
              Break
              EndIf
            CompilerEndIf
          EndIf
        ForEver
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure CheckReplay()
  If ((xAutoPlayback And xReAutoPlay) Or ReAutoPlayDR) And Not (xPStateIconPaused Or xPStateIconPlaying Or PLCount = 0 Or PlayerIsLocked Or xAutoDoing Or OutOfSessionHasPaused)
    If xRep = 2
      PLCurItem = RandomSong()
      EndIf
    MainForm_IconsMouseUp(1)
    ;CheckReplay = xPStateIconPlaying
    EndIf
  xAutoPlaybackLastRetryTime = GetTickTimeMS()
  EndProcedure

Procedure MainForm_xAutoRefreshNow(xSkipFindSong.i, ForceNow.i, NoPListAdding.i, NoRemove.i, ReSetAutoDirsAPI.i)
  Define.i xLong1
  Define.i xLong2
  
  ReAutoPlayDR = #False
  If Not xAutoDoing Or ForceNow
  ;  Do While xAutoDoing: DoEvents(): Loop
    MainForm_LockMe(#True)
    
    If Not NoPListAdding
      InitResearchClear()
      EndIf
    If xAutoDirCount = 0
      If ForceNow And Not NoRemove
        SetAutoDoing(#True)
        xRemoveAutoRefresh(#PLI_IsAuto, NoPListAdding, #False)
        SetAutoDoing(#False)
        EndIf
      If Not NoPListAdding
        MainForm_xBuildDirs()
        EndIf
      MainForm_LockMe(#False)
      If Not NoPListAdding
        InitResearch(#False)
        EndIf
      
      
      
      
      Else
    
      xPStateIconRefreshing = #True
      MainForm_UpdateMainIcon()
      DoEvents()
      xLong1 = 0
      SetAutoDoing(#True)
      If Not NoPListAdding
        ClearPLEx()
        EndIf
      If Not NoRemove
        xRemoveAutoRefresh(0, #True, #True)
        EndIf
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Performing autorefresh")
        CompilerEndIf
    
    
      AbortReading = #False
      If ReSetAutoDirsAPI
        MainForm_SetAutoDirs(#False)
        EndIf
      ReadDirInit()
      For xLong1 = 0 To xAutoDirCount - 1
        ;AbortReading = #False
        ReadDirectory(xAutoDir(xLong1), 0, #True, #PLI_IsAuto, Int((#xDefBWDifL * xLong1) / xAutoDirCount), Int(#xDefBWDifL / xAutoDirCount))
        If AbortReading
          Break ;;;;;;;;;;;;;
          EndIf
        Next
      ReadDirDone()
      If ReSetAutoDirsAPI
        MainForm_SetAutoDirs(#True)
        EndIf
    
      If Not NoPListAdding
        RealPLAdd(0)
        EndIf
    
      xPStateIconRefreshing = #False
      MainForm_UpdateMainIcon()
      SetAutoDoing(#False)
      
      If Not (xSkipFindSong Or NoPListAdding)
        xLong1 = xFindSong()
        If Not xLong1 = 0
          PLCurItem = xLong1
          xLong2 = xFollowCurSongLastDiff
          xMarkSong(xLong1, #False, #False)
          xFollowCurSongLast = GetTickTimeMS()
          If xLong1 < #xFollowCurSongLastDiffDef
            xFollowCurSongLastDiff = #xFollowCurSongLastDiffDef
            Else
            xFollowCurSongLastDiff = xLong2
            EndIf
          EndIf
        EndIf
      MainForm_LockMe(#False)
      If Not NoPListAdding
        InitResearch(#False)
        CheckReplay()
        EndIf
      EndIf
    
    CheckOldItems()
    xAutoRefreshTimerEventTime(0) = GetTickTimeMS()
    xAutoRefreshTimerEventTime(1) = xAutoRefreshTimerEventTime(0)
    EndIf
  EndProcedure

Procedure.i GetRealIndex(*Index, SongName.s)
  Define.i xResult
  Define.i xLong1
  Define.i Index
  
  If PLCount = 0
    Index = 0
    Else
    Index = PeekI(*Index)
    If Not Index < PLCount
      Index = PLCount - 1
      EndIf
    If Index < 0
      Index = 0
      Else
CompilerIf #BoldDirs = 98
      If PLI(Index)\Filename = SongName
CompilerElse
      If PLIFile(Index) = SongName
CompilerEndIf
        xResult = #True
        Else
        xLong1 = xFindSong(SongName)
        If Not xLong1 = 0
          Index = xLong1
          xResult = #True
          EndIf
        EndIf
      EndIf
    EndIf
  PokeI(*Index, Index)
  ProcedureReturn xResult
  EndProcedure

Procedure CheckShowWizard()
  If Not (vKioskMode Or xSecureMode)
    If (PLCount = 0)
      If InterfaceMode = #Interface_Mode_None
        ToggleInterface(#Interface_Mode_Wizard)
        EndIf
      ElseIf InterfaceMode = #Interface_Mode_Wizard
      ToggleInterface(#Interface_Mode_None)
      EndIf
    EndIf
  EndProcedure

Procedure AutoSwitchIRadioCheck(CanWizard.i)
  If Not (PLCount Or xAutoDirCount Or vKioskMode)
    If xAutoSwitchIRadioOEPl And xRadioCount
      If Not InterfaceMode = #Interface_Mode_Radio
        ToggleInterface(#Interface_Mode_Radio)
        EndIf
      ElseIf CanWizard
      CheckShowWizard()
      EndIf
    EndIf
  EndProcedure

Procedure ClearOverload()
  If (xWarnOverload Or xOldWarnOverload) And Not (PLCount > PLCountWarn)
    CompilerIf #NoDroppingIfOverloaded
      If xWarnOverload And Not vKioskMode
        ;RegisterDragDrop(MainHWnd, ObjPtr(DragClass))
        DragAcceptFiles_(MainHWnd, #True)
        xWarnOverload = #False
        EndIf
      CompilerElse
      xWarnOverload = #False
      CompilerEndIf
    MainForm_EnableApiMenu(10, #True)
    MainForm_EnableApiMenu(11, #True)
    MainForm_EnableApiMenu(12, #True)
    xOldWarnOverload = #False
    MainForm_UpdateMainIcon()
    EndIf
  EndProcedure

Procedure MainForm_PlayNext(UserDoes.i, xStep.i, DoCrossFade.i, ForceFadeOut.i)
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  Define.s xChar2
  
  If Not (PlayerIsLocked Or xAutoDoing)
    If xPStateIconPaused
      xPStateIconPaused = #False
      xPStateIconPlaying = #False
      
      ;added here beta 43 to prevent fadout when paused and skipping
      MainForm_xEndSong(#False, #False, #False, #False)
      
      xReAutoPlay = #False
      ReAutoPlayDR = #False
      MainForm_UpdateMainIcon()
      If Not PlNextSong = ""
        SetNextSong(#False)
        EndIf
      DoCrossFade = #False
      EndIf
  
    If PLCount = 0 And xAutoDirCount
      MainForm_xAutoRefreshNow(#False, #False, #False, #True, #False)  ;#False
      EndIf
    If Not PLCount = 0
      MainForm_LockMe(#True)
      If xRep = 0 And PlNextSong = "" And Not UserDoes
        xLong1 = PLCurItem
  CompilerIf #BoldDirs = 98
        If Not LCase(PLI(PLCurItem)\Filename) = LCase(PLCurSong)
  CompilerElse
        If Not LCase(PLIFile(PLCurItem)) = LCase(PLCurSong)
  CompilerEndIf
          PLCurItem = xFindSong()
          If PLCurItem = 0
            PLCurItem = xLong1
            EndIf
          EndIf
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("PlayNext0")
    CompilerEndIf
        If xPlayItem(UserDoes | ForceFadeOut, #False, DoCrossFade, UserDoes, #False, "")
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("PlayNext1")
    CompilerEndIf
          MainForm_LockMe(#False)
          ProcedureReturn
          EndIf
        PLCurItem = xLong1
        EndIf
      
      If xStep = -1
        If Not PlNextSong = ""
          SetNextSong(#False)
          EndIf
        Else
        xLong2 = PLCurItem
        xChar1 = PLCurSong
        xChar2 = PLCurSongDisplay
        If Not PlNextSong = ""
  CompilerIf #BoldDirs = 98
          If PLI(PLNext)\Filename = PlNextSong
  CompilerElse
          If PLIFile(PLNext) = PlNextSong
  CompilerEndIf
            SetNextSong(#False)
            PLCurItem = PLNext
            ;If xPlayItem(#True, #False, DoCrossFade, UserDoes, #False)
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("PlayNext2")
    CompilerEndIf
            If xPlayItem(UserDoes | ForceFadeOut, #False, DoCrossFade, UserDoes, #False, "")
              MainForm_LockMe(#False)
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("PlayNext3")
    CompilerEndIf
              ProcedureReturn
              EndIf
            Else
            xLong1 = xFindSong(PlNextSong)
            SetNextSong(#False)
            If Not xLong1 = 0
              PLCurItem = xLong1
              EndIf
            ;If xPlayItem(#True, #False, DoCrossFade, UserDoes, #False)
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("PlayNext4")
    CompilerEndIf
            If xPlayItem(UserDoes | ForceFadeOut, #False, DoCrossFade, UserDoes, #False, "")
              MainForm_LockMe(#False)
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("PlayNext5")
    CompilerEndIf
              ProcedureReturn
              EndIf
            EndIf
          SetNextSong(#False)
          PLCurItem = xLong2
          PLCurSong = xChar1
          PLCurSongDisplay = xChar2
          EndIf
        EndIf
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("PlayNext6 (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
    CompilerEndIf
      If UserDoes Or ForceFadeOut
        xLong1 = #True
        Else
        xLong1 = #False
        EndIf
        
      If (DoCrossFade And Not ForceFadeOut)
        xLong2 = #True
        Else
        xLong2 = #False
        EndIf
      xFindNextItem(xStep, #False, xLong1, #False, xLong2)
      ;;;;;; DoCrossfade is only used in CheckAfter, ProcessMode 1, and userdoes is passed
      ;;;;;; UserDoes (UserDoes or ForceFadeOut)  will be sent as CanFade to xFindNextItem
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("PlayNext7 (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
    CompilerEndIf
      MainForm_LockMe(#False)
      EndIf
    EndIf
  EndProcedure

Procedure.i AddFDirNowSub(xChar1.s)
  Define.i xResult
  Define.i xLong1

  xLong1 = PLCount
  xLastDir = xChar1
  If Len(xChar1) = 3
    xChar1 = Left(xChar1, 2)
    EndIf
  xPStateIconRefreshing = #True
  MainForm_UpdateMainIcon()
  AbortReading = #False
  MainForm_LockMe(#True)
  DoEvents()
  ReadDirInit()
  ReadDirectory(xChar1, 0, #True, 0, 0, #xDefBWDifL)
  ReadDirDone()
  If Not xLong1 = PLCount
    InitResearchClear()
    RealPLAdd(xLong1)
    xResult = #True
    EndIf
  MainForm_LockMe(#False)
  If Not xLong1 = PLCount
    InitResearch(#False)
    EndIf
  xPStateIconRefreshing = #False
  MainForm_UpdateMainIcon()
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_xPlayClick(NoFadeOut.i)
  If Not (PlayerIsLocked Or xAutoDoing)
    ;If Tear_Stept(CurrentSongID) = 0
      
      MainForm_LockMe(#True)
      xReAutoPlay = #True
      ;ShowIcon 0
      If (Tear_StepT(CurrentSongID) Or xGenFading) And xPStateIconPlaying And Not (CurMusic = #ctSSLayer_MusicTypeNone Or NoFadeOut)
        If Not (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
          If Tear_StepT(CurrentSongID) = 0
            Tear_Volume(CurrentSongID) = 1
            EndIf
          Tear_StartDropping(CurrentSongID, xSongIsMidi, 3, 0, #SimpleFadingTotalTime, 0)
          ;ShowIcon 0 ;;
          ;DoFading -1
          EndIf
        MainForm_LockMe(#False)
        ProcedureReturn
        EndIf
      xPStateIconPlaying = #True
      MainForm_UpdateMainIcon()
      If CurMusic = #ctSSLayer_MusicTypeNone
        If PLCount = 0 And xAutoDirCount
          MainForm_xAutoRefreshNow(#False, #False, #False, #True, #False)
          EndIf
        If PLCount = 0
          xPStateIconPlaying = #False
          MainForm_UpdateMainIcon()
          Else
          If Not (xPlayItem(#False, #False, #False, #True, #False, ""))
            ;If Not DontTryOtherSong
              xFindNextItem(1, #False, #False, #False, #False)
            ;  endif
            EndIf
          EndIf
        ElseIf Not (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
        MainForm_RestartEx()
        EndIf
      
      
      MainForm_EraseBackground(xStaticIconsHWnd(#xStaticIcons_CurSongPos))
      ;ePic(1).Line (0, 0)-(SongPosScrollWidth, 10), FLineColorX, BF
      xEndSongTimerEventTime = GetTickTimeMS()
      MainForm_LockMe(#False)
      ;Else
      ;If
      ;  Tear_StartDropping(CurrentSongID, xSongIsMidi, 3, 0, #SimpleFadingTotalTime, 0)
      ;  Else
      ;  Tear_StartDropping(CurrentSongID, xSongIsMidi, 3, 0, #SimpleFadingTotalTime, 0)
      ;  endif
      ;endif
    EndIf
  EndProcedure

Procedure StoreResume(ResumeNow.i, WaitTime.i)
  ;WaitTime: 0 = resume std
  ;          1 = resume next auto / nopause (for deleting old file / device has been removed)
  
  ;Static xLong1.i
  Static xLong2.i
  Static xBool1.i ; play
  Static xBool2.i ; paused
  Static xBool3.i
  Define.i xGotoBoolURLHack
  ;Dim xBool3 As Boolean

  If ResumeNow
    If WaitTime = 1
      If xBool2
        xReAutoPlay = #False
        ReAutoPlayDR = #False
        xBool1 = #False
        EndIf
      ElseIf xBool1 ;And Not xLong1 = 0
      xPStateIconPlaying = #True
      If xBool3
        If xPlayItem(#False, xGenFading, #False, #True, xBool2, PLCurFullURL)
          If Not CurMusic = #ctSSLayer_MusicTypeNone
            xGotoBoolURLHack = #True
            EndIf
          EndIf
        If Not xGotoBoolURLHack
          xBool2 = #False
          xLong2 = 0
          EndIf
        EndIf

      If Not xGotoBoolURLHack
        If xPlayItem(#False, xGenFading, #False, #True, xBool2, "")
          If Not CurMusic = #ctSSLayer_MusicTypeNone
            xGotoBoolURLHack = #True
            EndIf
          Else
          If xBool2
            WaitTime = 0
            xBool1 = #False
            Else
            WaitTime = 1
            EndIf
          xPStateIconPlaying = #False
          xReAutoPlay = #False
          ReAutoPlayDR = #False
          MainForm_UpdateMainIcon()
          ;;;;;;;If Not PlNextSong = "" ShowIcon 2
          EndIf
        EndIf
      
      If xGotoBoolURLHack
        xPStateIconPaused = xBool2
        MainForm_UpdateMainIcon()
        ;If Not (xLong2 < 0 Or xLong2 > PLCurSongLength - 1)
          ctSSLayer_SeekSong(SongPointer(CurrentSongID), xLong2)
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  IsPosition: " + Str(xLong2))
          CompilerEndIf
          ;endif
        If (xGenFading And Tear_StepT(CurrentSongID) = 0) And Not xBool2
          Tear_StartDropping(CurrentSongID, xSongIsMidi, 0, 0, #SimpleFadingTotalTime, 1)
          EndIf
        WaitTime = 0
        EndIf
      EndIf
    
    If WaitTime = 1
      xPStateIconPlaying = #False
      MainForm_LockMe(#False)
      If PlNextSong = ""
        If xRep = 2
          PLCurItem = RandomSong()
          Else
          If Not PLCurItem = 0
            PLCurItem = PLCurItem - 1
            EndIf
          xFindNextItem(1, #True, #False, #False, #False)
          EndIf
        Else
        MainForm_LockMe(#False)
        MainForm_PlayNext(#True, 1, #False, #False)
        EndIf
      EndIf
    If xBool1
      MainForm_xPlayClick(#False)
      EndIf
    
    
    Else
    If xPStateIconPlaying
      xLong2 = PLCurSongPos
      If (CurMusic = #ctSSLayer_MusicTypeNone)
        xBool1 = #False
        xBool2 = #False
        Else
        xBool1 = #True
        xBool2 = xPStateIconPaused
        EndIf
      If ((CurMusic = #ctSSLayer_MusicTypeStream) And (xSongIsMidi = 3))
        xBool3 = #True
        Else
        xBool3 = #False
        EndIf
      MainForm_xEndSong(#True, xPStateIconPaused, #False, #False)
      xPStateIconPlaying = #False
      MainForm_UpdateMainIcon()
      If Not (xPStateIconPaused Or WaitTime = 0)
        DoEventsEx(WaitTime)
        EndIf
      Else
      xBool1 = #False
      xBool2 = #False
      xBool3 = #False
      EndIf
    EndIf
;debug "Post:", xBool1, xBool2, xBool3, xLong2, PLCurFullURL
  EndProcedure

Procedure ResetSystem(ReInit.i, LockOnly.i)
  If ReInit
    If Not LockOnly
      StoreResume(#True, 0)
      EndIf
    LEDState = 0
    Else
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Preparing to close sound system")
      CompilerEndIf
    If Not LockOnly
      StoreResume(#False, 2000)
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_OutputChange(hWndCaller.i, FastInit.i, UpdatePlayerIcon.i)
  MainForm_LockMe(#True)
  SetAutoDoing(#True)
  If UpdatePlayerIcon
    xPStateIconSndcard = #True
    MainForm_UpdateMainIcon()
    EndIf
  MainForm_CheckDir(#True)

  If FastInit
    If CurMusic = #ctSSLayer_MusicTypeCDAudio
      ResetSystem(#False, #False)
      Tear_WaitFor(2)
      ctSSLayer_UpdateCDDA(CDDAUse, CDDAJitter)
      SetAutoDoing(#False)
      ResetSystem(#True, #False)
      Else
      ResetSystem(#False, #True)
      Tear_WaitFor(2)
      ctSSLayer_UpdateCDDA(CDDAUse, CDDAJitter)
      SetAutoDoing(#False)
      ResetSystem(#True, #True)
      EndIf
    Else
    ResetSystem(#False, #False)
    
    MainForm_DesireSpectrumState(#False, #True)
    If LEDMode
      LEDState = 2
      EndIf
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("  Closing sound system")
      CompilerEndIf
  
    Tear_WaitFor(-2)
    ctSSLayer_Close(0)
    ctSSLayer_RefreshDeviceList(MainHWnd)
    xInitMe(hWndCaller, #False, #False, #False)
    
    SetAutoDoing(#False)
    ResetSystem(#True, #False)
    EndIf

  ; > LEDState = 0
  If UpdatePlayerIcon
    xPStateIconSndcard = #False
    MainForm_UpdateMainIcon()
    EndIf
  
  DoEvents()
  MainForm_LockMe(#False)
  EndProcedure

Procedure.i AddFDirNowSubEx(xChar1.s, ResetPL.i)
  Define.i xResult

  SetAutoDoing(#True)
  
  If ResetPL
    If Not PlNextSong = ""
      SetNextSong(#False)
      EndIf
    PLCount = 0
;;;;;;;;    aaa
    PLCurItem = 0
    ClearOverload()
    ClearPLEx()
    EndIf
  
  If PLCount < PLCountMaxX
    xResult = AddFDirNowSub(xChar1)
    SetAutoDoing(#False)
    If xResult
      InitResearch(#False)
      EndIf
    CheckReplay()
    Else
    SetAutoDoing(#False)
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.i ShutdownDialogProc(HWndDialog.i, Msg.i, ControlID.i, ControlHWnd.i)
  Define.i xResult
  Define.s xChar1

  If Msg = $110
    ShutDownInitTime = GetTickTimeMS()
    hwndShutDownDialog = HWndDialog
    If KioskDown
      LoadResEx_Dialog_Enable(HWndDialog, 2959, #False)
      EndIf
    hwndShutDownProgress = GetDlgItem_(HWndDialog, 2950)
    xChar1 = LoadResString(2949 + QuitModePending)
    SetWindowText_(HWndDialog, @xChar1)
    ElseIf Msg = $111
    QuitModePending = 0
    xResult = 1
    ;ElseIf Msg = $12
    ;xResult = 0
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure StartShutDownStuff()
  WantsShutdownDialog = #False
  DialogTimer(#True)
  LoadResEx_Dialog(MainHWnd, 2950, 2959, 0, @ShutdownDialogProc())
  DialogTimer(#False)
  Select QuitMode
    Case 1
      MainForm_UnloadP()
    Case 2
      ShutdownWindowsEx(#SDWE_Hibernate)
      QuitMode = 0
    Case 3
      ShutdownWindowsEx(#SDWE_Standby)
      QuitMode = 0
    Case 4
      ShutdownWindowsEx(#SDWE_MonitorsOff)
      QuitMode = 0
    EndSelect
  EndProcedure

Procedure.i eTimerEvent(hWnd.i, Msg.i, idEvent.i, xLong1.i)
  CompilerIf #MultiGUITimer
    Static xBool1.i
    CompilerEndIf

  ;If IsDialoging
  ;  DoAnimateReadDir(1)
  ;  endif
  If WantsShutdownDialog And Not (xAutoDoing Or PlayerIsLocked)
    ;WantsShutdownDialog = #False
    StartShutDownStuff()
    EndIf
  
  CompilerIf #MultiGUITimer
  If Not (xTimer2 Or xBool1)
    CompilerElse
    If Not xTimer2
    CompilerEndIf
      CompilerIf #MultiGUITimer
        If xTimer2
          xBool1 = #True
          Else
          xTimer2 = #True
          EndIf
        CompilerElse
        xTimer2 = #True
        CompilerEndIf
    If InterfaceMode = #Interface_Mode_Timer
      SetWindowText_(TimerListUpdateHWnd, ReplaceString(LoadResString(2600), "$", GetTimeFormatNow()))
      EndIf


    MainForm_eTimerTime()
    
    
    If Not hwndShutDownDialog = 0
      xLong1 = GetElapsedTickTimeMS(ShutDownInitTime)
CompilerIf #MultiGUITimer
      If xLong1 >= #ShutDownTimerMax And Not (xBool1 Or xAutoDoing Or PlayerIsLocked)
CompilerElse
      If vShutDownDTimer >= xLong1 And Not (xAutoDoing Or PlayerIsLocked)
CompilerEndIf
        QuitMode = QuitModePending
        SendMessage_(hwndShutDownDialog, $10, 0, 0)
        ElseIf Not hwndShutDownProgress = 0
        SendMessage_(hwndShutDownProgress, 1026, Int(xLong1 / #ShutDownTimerMaxDiv), 0)
        EndIf
      EndIf
    
    CompilerIf #MultiGUITimer
      If xBool1
        xBool1 = #False
        Else
        xTimer2 = #False
        EndIf
      CompilerElse
      xTimer2 = #False
      CompilerEndIf
    EndIf
  EndProcedure

Procedure ResortTimers()
  Define.i xLong1
  Define.i xLong2
  Define.i xLong4
  Define.i xLong5
  Define.i xLong6
  Define.s xChar1
  
  GrabError()
  xLong2 = GetLocalTimeHMS_HS()
  If Not xTimerEvIR = -1
    If (xTimerEvTime(xTimerEvIR) - xLong2 + 1440) % 1440 > 150
      For xLong4 = xTimerEvTime(xTimerEvIR) To xTimerEvCount - 2
        xTimerEv(xLong4) = xTimerEv(xLong4 + 1)
        xTimerEvTime(xLong4) = xTimerEvTime(xLong4 + 1)
        Next
      xTimerEvIR = -1
      xTimerEvCount = xTimerEvCount - 1
      EndIf
    EndIf

  For xLong1 = 0 To xTimerEvCount - 2
    xLong5 = xLong1
    xLong6 = (xTimerEvTime(xLong5) - xLong2 + 1440) % 1440
    If xLong6 = 0 And xTimerEvTime(xLong5) + 1 = LastDoneTimer
      xLong6 = 1440
      EndIf
    For xLong4 = xLong1 + 1 To xTimerEvCount - 1
      If (xTimerEvTime(xLong4) - xLong2 + 1440) % 1440 < xLong6
        xLong5 = xLong4
        xLong6 = (xTimerEvTime(xLong5) - xLong2 + 1440) % 1440
        If xLong6 = 0 And xTimerEvTime(xLong5) + 1 = LastDoneTimer
          xLong6 = 1440
          EndIf
        EndIf
      Next
    If Not xLong5 = xLong1
      xChar1 = xTimerEv(xLong1)
      xLong6 = xTimerEvTime(xLong1)
      xTimerEv(xLong1) = xTimerEv(xLong5)
      xTimerEvTime(xLong1) = xTimerEvTime(xLong5)
      xTimerEv(xLong5) = xChar1
      xTimerEvTime(xLong5) = xLong6
      If xTimerEvIR = xLong1
        xTimerEvIR = xLong5
        ElseIf xTimerEvIR = xLong5
        xTimerEvIR = xLong1
        EndIf
      EndIf
    Next
  MainForm_SetTimerImage()
  EndProcedure

Procedure MainForm_LoadTimers(hWndOwner.i, xChar1.s, Silent.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xBool1
  Define.s xChar2
  Define.i hFile
  
  If Not TimerListForm_xLocked
    If AllowedItem(xChar1, #True) = 254
      hFile = TxtFileReader_FromFile(xChar1)
      If Not hFile = 0
        If TxtFileReader_NextLine(hFile)
          xChar1 = TxtFileReader_GetLineString(hFile)
          TimerForm_PrePreset()
          If xChar1 = #xTimerIDString
            If Not (xTimerEvIR = -1 Or Silent)
              If Not CalaymMessageBox(hWndOwner, LoadResString(1610), LoadResString(1600), 68) = #IDYES
                xTimerEvIR = -1
                EndIf
              EndIf
            If xTimerEvIR = -1
              xTimerEvCount = 0
              ;Erase xTimerEv
              ;Erase xTimerEvTime
              Else
              xTimerEv(0) = xTimerEv(xTimerEvIR)
              xTimerEvTime(0) = xTimerEvTime(xTimerEvIR)
              xTimerEvCount = 1
              xTimerEvIR = 0
              EndIf
            If InterfaceMode = #Interface_Mode_Timer
              SendMessage_(Interface_Control(#Interface_Control_Timer_List), $184, 0, 0)
              For xLong1 = 0 To #Interface_Control_Timer_RemoveAll
                EnableWindow_(Interface_Control(xLong1), #False)
                Next
              EndIf
            While TxtFileReader_NextLine(hFile)
              xChar1 = TxtFileReader_GetLineString(hFile)
              xLong1 = FindString(xChar1, ",")
              If Not xLong1 = 0
                xChar2 = Trim(Left(xChar1, xLong1 - 1))
                Select Left(xChar2, 1)
                  Case "+", "-"
                    xChar2 = Trim(Mid(xChar2, 2))
                  EndSelect
                If Len(xChar2) = 5 And Mid(xChar2, 3, 1) = ":"
                  xLong2 = Val(Left(xChar2, 2))
                  xLong3 = Val(Right(xChar2, 2))
                  If xLong2 > -1 And xLong2 < 24 And xLong2 > -1 And xLong3 < 60
                    xLong2 = xLong2 * 60 + xLong3
                    GrabError()
                    Select Left(Trim(xChar1), 1)
                      Case "+"
                        xTimerEvTime(xTimerEvCount) = (GetLocalTimeHMS_HS() + xLong2) % 1440
                      Case "-"
                        xTimerEvTime(xTimerEvCount) = (GetLocalTimeHMS_HS() - xLong2 + 1440) % 1440
                      Default
                        xTimerEvTime(xTimerEvCount) = xLong2
                      EndSelect
                    xTimerEv(xTimerEvCount) = Trim(Mid(xChar1, xLong1 + 1))
                    xBool1 = #True
                    
                    CompilerIf #UseFileLogging
                      MainForm_ctConsoleA_AddLog("Importing timer: " + xTimerEv(xTimerEvCount))
                      CompilerEndIf
                    
                    xTimerDisplayLastParamValue = ""
                    MainForm_xTimerDisplay(xTimerEvCount, 0, @xBool1)
                    
                    If xBool1
                      xTimerEvCount = xTimerEvCount + 1
                      CompilerIf #UseFileLogging
                        MainForm_ctConsoleA_AddLog("  ok")
                        CompilerEndIf
                      If (xTimerEvCount = #xTimerEvMax And xTimerEvIR = -1) Or xTimerEvCount = #xTimerEvMax + 1
                        CompilerIf #UseFileLogging
                          MainForm_ctConsoleA_AddLog("  (maximum reached)")
                          CompilerEndIf
                        Break
                        EndIf
        CompilerIf #UseFileLogging
                      Else
                      MainForm_ctConsoleA_AddLog("  failed")
        CompilerEndIf
                      EndIf
                    EndIf
                  EndIf
                EndIf
              Wend
            If InterfaceMode = #Interface_Mode_Timer
              TimerListForm_ListUpdate()
              EnableWindow_(Interface_Control(#Interface_Control_Timer_RemoveAll), #True)
              Else
              ResortTimers()
              EndIf
            EndIf
          EndIf
        TxtFileReader_Close(hFile)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure ShowInitInfo()
  GenericMessageHandler_Param = 2102
  DialogTimer(#True)
  LoadResEx_Dialog(MainHWnd, 2102, 2090, 2091, @GenericMessageHandler())
  DialogTimer(#False)
  EndProcedure

Procedure MainForm_StartPlayer()
  Define.s xChar1
  Define.s xChar2
  ;Define.s xChar3
  ;Define.s xChar4
  Define.i xLong1
  Define.i xLong2
  Define.i hFile
  Define.i xBool1_Spectrum
  Define.i xBool2_FailSave
  Define.i xBool3
  Define.i xBool4_HasBase
  Define.STARTUPINFO xType2
  Define.s CommandZ
  Define.i RestoreRegOnlyNow
  Define.InitCommonControlsExType xType1
  ;Dim xType1 As OSVERSIONINFO
  CompilerIf #UseFileLogging
    Define.s GBN1
    CompilerEndIf

  DPIScaleX = 1
  DPIScaleY = 1
  
  SetProcessDPIAware()
;  Stop
  xLong1 = GetDC_(0)
  If Not xLong1 = 0
    DPIScaleX = GetDeviceCaps_(xLong1, 88) / 96
    DPIScaleY = GetDeviceCaps_(xLong1, 90) / 96
    ReleaseDC_(0, xLong1)
    EndIf
  eSPTopX = 4 * DPIScaleX
  eSPTopY = 4 * DPIScaleY

  xType1\dwSize = SizeOf(InitCommonControlsExType)
  xType1\dwICC = #ICC_UPDOWN_CLASS | #ICC_DATE_CLASSES | #ICC_PROGRESS_CLASS; | ICC_TAB_CLASSES
  InitCommonControlsEx_(@xType1)

  ;ApplicationStart(LoadResEx_IconOS_WinVista)
  ;On Error Resume Next
  ;SetProcessDEPPolicy(0)
  ;On Error GoTo 0
  
  GetOptimalPLMaxCount()
  PLCountMaxX = PLCountMax - 1
  PLCountMaxX2 = PLCountMax - 2
  
  CompilerIf #BoldDirs = 98
    ReDim PLI(PLCountMaxX)
    CompilerElse
    ReDim PLIFile(PLCountMaxX)
    ReDim PLICap(PLCountMaxX)
    ReDim PLIDF(PLCountMaxX)
    ReDim PLIPxLg(PLCountMaxX)
    ReDim PLIPxSm(PLCountMaxX)
    CompilerEndIf
  
  
  
  RndPLPatternCount = (PLCountMaxX / #RandomizerPattern) + 1
  ReDim RndPLPattern(RndPLPatternCount)
  sCharA1Max = PLCountMax ; MaxInt
  sCharA1MaxX = sCharA1Max - 1
  Dim sCharA1(sCharA1MaxX)
  ReDim xDirPath(PLCountMaxX2)
  
  
  SetKeyConsts()
  
  
  xRealBaseFile = AppBase_GetByExt("")
  CommandZ = GetStrippedCommandLine()
  CommandX = UCase(CommandZ)
;  GBN2 = GetFileVersionField(#GetFileVersionField_ProductName) + " " + GetFileVersionField(#GetFileVersionField_ProductVersion) + #CR$ + ReplaceString(GetFileVersionField(#GetFileVersionField_LegalCopyright), "; ", #CRLF$)
  GBN2 = GetFileVersionField(#GetFileVersionField_FileDesc) + #CR$ + GetFileVersionField(#GetFileVersionField_FileVersion) + #CR$ + ReplaceString(GetFileVersionField(#GetFileVersionField_LegalCopyright), "; ", #CRLF$)
  CompilerIf #UseFileLogging
    GBN1 = GetFileVersionField(#GetFileVersionField_ProductName) + " " + GetFileVersionField(#GetFileVersionField_ProductVersion)
    CompilerEndIf

  If Len(Trim(CommandX)) = 0
    hFile = TxtFileReader_FromFile(xRealBaseFile + "cmd")
    If Not hFile = 0
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Reading command file (" + xRealBaseFile + "cmd" + ")")
        CompilerEndIf
      While TxtFileReader_NextLine(hFile)
        xChar1 = TxtFileReader_GetLineString(hFile)
        CommandX = Trim(CommandX) + " " + UCase(Trim(xChar1))
        CommandZ = CommandZ + " " + Trim(xChar1)
        Wend
CompilerIf #UseFileLogging
      TxtFileReader_Close(hFile)
      Else
      MainForm_ctConsoleA_AddLog("Error reading command file (" + xRealBaseFile + "cmd" + ")")
CompilerEndIf
      EndIf
    EndIf

  xLong1 = FindString(CommandX, "/BASE=")
  If xLong1
    xChar1 = Trim(Mid(CommandZ, xLong1 + 6))
    If Not Len(xChar1) = 0
      AppBase_SetByPathBaseFileCmdParam(xChar1)
      xLong1 = GetFileAttributes(SimpleDir(AppBase_GetByExt("exe")))
      If (xLong1 & $10) And Not xLong1 = -1
        xBool4_HasBase = #True
        Else
        AppBase_SetByFull(xRealBaseFile + "exe")
        EndIf
      EndIf
    EndIf

  If FindString(CommandX, "/PORTQUIT")
    xAutoUSBQuit = #True
    EndIf

  xLong1 = FindString(CommandX, "/PORTABLE")
  If xLong1
    ;xChar3 = AppBase_GetByExt("lng")
    ;xChar4 = AppBase_GetByExt("icl")
    xLong1 = 256
    If GetComputerName_(*ptrTemp, @xLong1)
      xChar1 = PeekS(*ptrTemp, xLong1)
      If Len(xChar1)
        xChar2 = AppBase_GetJustPath()
        If xChar2
          AppBase_SetByPathBaseFile(xChar2 + "\" + LCase(xChar1))
          Goto PortableSkip
          EndIf
        EndIf
      EndIf
    EndIf

CompilerIf #UseFileLogging
  If IsFileExists(AppBase_GetByExt("ini"))
    MainForm_ctConsoleA_AddLog("AppBase: Ini found!")
    Else
CompilerElse
  If Not IsFileExists(AppBase_GetByExt("ini"))
CompilerEndIf
    xChar2 = RegReadString("Software\Microsoft\Windows\CurrentVersion", "ProgramFilesDir")
    If Len(xChar2) = 0
      xChar2 = RegReadString("Software\Microsoft\Windows\CurrentVersion", "ProgramFilesPath")
      If Len(xChar2) = 0
        xChar2 = RegReadString("Software\Microsoft\Windows\CurrentVersion\SETUP\VarLDID", "28700")
        EndIf
      EndIf
    If Len(xChar2) = 0
      ;If xType1.dwPlatformId = $2
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("AppBase: Cannot detect programs dir!")
          CompilerEndIf
        Goto UseAppData
CompilerIf #UseFileLogging
      ;  Else
      ;  MainForm_ctConsoleA_AddLog("AppBase: Cannot detect programs dir, and is 9x")
  CompilerEndIf
      ;  endif
      Else
      If Not Right(xChar2, 1) = "\"
        xChar2 = xChar2 + "\"
        EndIf
      If LCase(Left(AppBase_GetPathBaseFile(), Len(xChar2))) = LCase(xChar2)
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("AppBase: Is within programs dir")
          CompilerEndIf
UseAppData:
        xChar1 = Trim(GetSpecialFolderPath(26, #True))
        If Not Len(xChar1) = 0
          If CreateDirectoryEx(xChar1 + "ctuser\Calaym")
            xBool4_HasBase = #False
            AppBase_SetByPathBaseFile(xChar1 + "ctuser\Calaym\Calaym")
            EndIf
          EndIf
CompilerIf #UseFileLogging
        Else
        MainForm_ctConsoleA_AddLog("AppBase: Is anywhere")
CompilerEndIf
        EndIf
      EndIf
    EndIf
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  " + AppBase_GetByExt("*"))
    CompilerEndIf
  
PortableSkip:
  
  
  CompilerIf #UseFileLogging
    LogFileLog = AppBase_GetByExt("dbg")
    hFile = TxtFileWriter_CreateFile(LogFileLog)
    If Not hFile = 0
      LogFileDoLog = #True
      TxtFileWriter_Close(hFile)
      MainForm_ctConsoleA_AddLog("Log file for " + GBN1)
      EndIf
    CompilerEndIf


  CompilerIf #UseFileLogging
    GetOptimalPLMaxCount()
    CompilerEndIf



  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Attempting to load language file...")
    CompilerEndIf
  
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  base0: " + AppBase_GetByExt("lng/icl"))
    CompilerEndIf

  
  If Not FindString(CommandX, "/UNINSTALLREG") = 0
    RestoreRegOnlyNow = 2
    Goto RestoreRegOnly1
    ElseIf Not FindString(CommandX, "/RESTOREREG") = 0
    RestoreRegOnlyNow = 1
    Goto RestoreRegOnly1
    EndIf

  If FindString(CommandX, "/MULTIINST") = 0
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Sending m3u command to previous instance")
      CompilerEndIf
    If PrevInstanceEx(CommandZ)
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  success")
        CompilerEndIf
      ErMustQuit2()
      ProcedureReturn
CompilerIf #UseFileLogging
      Else
      MainForm_ctConsoleA_AddLog("  no previous instance found")
CompilerEndIf
      EndIf
    EndIf







  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  If FindString(CommandX, "/KEEPLOGS") = 0
    LogFile = AppBase_GetByExt("log")
    hFile = TxtFileWriter_CreateFile(LogFile)
    If Not hFile = 0
      LogFileDo = #True
      TxtFileWriter_Close(hFile)
      EndIf
    Else
    LogFile = AppBase_GetPathBaseFile()
    LogFile = Left(LogFile, Len(LogFile) - 1)
    LogFileDo = #True
    LogFileMulti = #True
    EndIf
  
  
  
  
  
  
  
  
  



  









  
  
  
  
  
  
  
  CurShownToolTip = -1
  ;ToolTipInitTime = -1
  xCalaymClassAlign = -1
  ForceLoudestTear = -1

  For xLong1 = 0 To 4
    *FormatIconBmp(xLong1) = LoadResData_Copy(1900 + xLong1, 2, @FormatIconLen(xLong1))
    Next

  If *DynButtonsResXDefBMP
    LocalFree_(*DynButtonsResXDefBMP)
    EndIf
  *DynButtonsResXDefBMP = LoadResData_Copy(1005, 2, @DynButtonsResXDefLen)

  If *DynButtonsResXRepBMP
    LocalFree_(*DynButtonsResXRepBMP)
    EndIf
  *DynButtonsResXRepBMP = LoadResData_Copy(1010, 2, @DynButtonsResXRepLen)

  If *xTimerIconBMP
    LocalFree_(*xTimerIconBMP)
    EndIf
  *xTimerIconBMP = LoadResData_Copy(2600, 2, @xTimerIconLen)

  If FindString(CommandX, "/LOCKED")
    vKioskMode = #True
    xSecureMode = #True
    ElseIf FindString(CommandX, "/KIOSK")
    vKioskMode = #True
    xSecureMode = #True
    EndIf

  If FindString(CommandX, "/SECURE")
    xSecureMode = #True
    EndIf

  If FindString(CommandX, "/URL")
    UrlsAllowed = #True
    ElseIf Not (xSecureMode Or vKioskMode)
    UrlsAllowed = #True
    EndIf
  
  xSharedDC = CreateCompatibleDC_(0)
  xSharedDCOldFont = GetCurrentObject_(xSharedDC, 6)
  If Not MainForm_CreatePlayerForm()
    ErMustQuit2()
    ProcedureReturn
    EndIf
  
  GetWhiteBackGrnd() ;#True
   
   
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Loading & initializing layer")
    CompilerEndIf
  
  If FindString(CommandX, "/ENQUEUE")
    EnqueueFlag = #True
    EndIf
  If FindString(CommandX, "/SHELL")
    xShellMode = #True
    EndIf
  
  Repeat
    DoEvents()
    Select SSMultiLoader()
      Case -1
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  Error: Layer missing")
          CompilerEndIf
        GenericMessageHandler_Param = 2050
        If Not LoadResEx_Dialog(0, 2000, 2090, 2091, @GenericMessageHandler()) = 2090
          ErMustQuit()
          ProcedureReturn
          EndIf
      Case -2
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  Error: Layer cannot load")
          CompilerEndIf
        GenericMessageHandler_Param = 2051
        If Not LoadResEx_Dialog(0, 2000, 2090, 2091, @GenericMessageHandler()) = 2090
          ErMustQuit()
          ProcedureReturn
          EndIf
      Case 0
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  Error: Layer incompatible")
          CompilerEndIf
        GenericMessageHandler_Param = 2052
        If Not LoadResEx_Dialog(0, 2000, 2090, 2091, @GenericMessageHandler()) = 2090
          ErMustQuit()
          ProcedureReturn
          EndIf
      Default
        CompilerIf #UseFileLogging
          ctSSLayer_SetDebugger(@SSDebuggerCB())
          CompilerEndIf
        LayerHP = ctSSLayer_GetInfoString($40)
        ctSSLayer_PreInit(MainHWnd)
        xLong1 = ctSSLayer_CanUseItem($20)
        SSRestrictions = ""
        For xLong2 = $50 To $5F
          xChar1 = ctSSLayer_GetInfoString(xLong2)
          If Len(xChar1) = 0
            Break
            EndIf
          SSRestrictions = SSRestrictions + ", " + xChar1
          Next
        SSRestrictions = Mid(SSRestrictions, 3)
        If Len(SSRestrictions) = 0 And xLong1 = 13
          SSRestrictions = "???"
          EndIf
        CompilerIf #UseFileLogging
          If xLong1 < 20
            If Not xLong1 = 0
              xChar1 = "Respond"
              Goto ShareIniVer
              EndIf
            Else
            xChar1 = "Error"
ShareIniVer:
            If xLong1 < 10 Or xLong1 > 19
              xLong2 = 9
              Else
              xLong2 = xLong1
              EndIf
            MainForm_ctConsoleA_AddLog("  " + xChar1 + " (" + Str(xLong1) + ");" + ctSSLayer_GetInfoString($0) + " " + ctSSLayer_GetInfoString($30))
            MainForm_ctConsoleA_AddLog("  " + ReplaceString(LoadResString(2100 + xLong2), "$S", ctSSLayer_GetInfoString(5)))
            EndIf
          If Not Len(SSRestrictions) = 0
            MainForm_ctConsoleA_AddLog("  Restrictions: " + SSRestrictions)
            EndIf
          If xLong1 = 90
            MainForm_ctConsoleA_AddLog("  Possible dlls missing: " + ctSSLayer_GetInfoString($31))
            EndIf
          CompilerEndIf
        If Len(SSRestrictions) = 0
          SSRestrictions = "$I"
          Else
          SSRestrictions = ReplaceString(LoadResString(2102), "$R", SSRestrictions)
          EndIf
        
        GenericMessageHandler_Param = 2100 + xLong1
        If xLong1 < 20
          Break
          Else
          Select xLong1
            Case 20, 21
              xLong1 = 2120
              GenericMessageHandler_Param = 2120
            Case 30 To 32
              xLong1 = 2130
            Case 90
              xLong1 = 2190
            Default
              xLong1 = 2100 ; + xLong1
            EndSelect
          UnloadLayerOnDialog = #True
          If Not LoadResEx_Dialog(0, xLong1, 2090, 2091, @GenericMessageHandler()) = 2090
            If UnloadLayerOnDialog
              ctSSLayer_UnLoadVB()
              UnloadLayerOnDialog = #False
              EndIf
            ErMustQuit()
            ProcedureReturn
            EndIf
          EndIf
      EndSelect
    If UnloadLayerOnDialog
      ctSSLayer_UnLoadVB()
      UnloadLayerOnDialog = #False
      EndIf
    ForEver



;NoMustQuit
  MaxDeviceCount = ctSSLayer_CanUseItem($7)
  If MaxDeviceCount = 0
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("  Error: No sounddevices")
      CompilerEndIf
    DoEvents()
    GenericMessageHandler_Param = 2100
    LoadResEx_Dialog(0, 2100, 2180, 2091, @GenericMessageHandler())
    ctSSLayer_UnLoadVB()
    ErMustQuit()
    ProcedureReturn
    EndIf
 
 
 
 
 
 
 
 
 
 
;  ePic1TopX = 15
;  ePic1TopX2 = 28
  
  ;Randomize GetTickTimeMS()
  RndPatternAlias(0) = $4
  RndPatternAlias(1) = $0
  RndPatternAlias(2) = $6
  RndPatternAlias(3) = $2
  RndPatternAlias(4) = $B
  RndPatternAlias(5) = $9
  RndPatternAlias(6) = $D
  RndPatternAlias(7) = $7
  RndPatternAlias(8) = $F
  RndPatternAlias(9) = $1
  RndPatternAlias(10) = $C
  RndPatternAlias(11) = $5
  RndPatternAlias(12) = $8
  RndPatternAlias(13) = $A
  RndPatternAlias(14) = $3
  RndPatternAlias(15) = $E
   
  xUsedTypes = ctSSLayer_GetInfoString($19)
  For xLong1 = 0 To RndPLPatternCount
    RndPLPattern(xLong1) = URndDnP(#RandomizerPattern)
    Next
   
  
  xTimerEvIR = -1
  xProcID = GetCurrentProcessId_()
  
  
  DoEvents()
  
  
  GetDefControls(xKey())
  
  
  
  xOldIconState = -1
  CheckAccurate = #True
  UsePLSettings = #True
  ;xCurStreamChannelIndex = 0
  xTrayIconOld = 255
  xDelMode = #False
  xSetVolume = 200
  xTrackerSkipper(#ctSSLayer_MusicTypeStream) = -7
  xTrackerSkipper(#ctSSLayer_MusicTypeTracker) = 5
  xTrackerSkipper(#ctSSLayer_MusicTypeCDAudio) = 5
  IntroModeTime = #IntroModeTimeDef
  RandomPosOnTrackerSkipper = #True
  
  xModPanning = 75
  xAutoPlayback = #True
  xReAutoPlay = #True
  xDirListModeCur = 0
  xDirListModeSet = 3
  xDirListTopHeight = 4
  xDirListLeftWidth = 33
  
  xGenFading = #True
  CurrentFindMatchCase = #PB_String_NoCase
  MP3GetFormat = #True
  MP3GetID3Tag = #True
  ;xBool1_Spectrum = #False
  xFollowCurSong = #True
  xRemoveMissingSongs = #True
  ;RemoveMissingOnPLLoad = #True
  ShowFullPath = #False
  ShowFullTitle = #False
  xProcessMode = 1
  xTrayIconLeft = 1
  xTrayIconRight = 1
  PlDClickAction = 1
  
  xCrossFadeTimeM = 12 - #xFadeConsts1
  StartUpWindowMode = 1
  xRep = 2 ;random
  xAutoSwitchIRadioOEPl = #True
  xSearchAutoPlay = #True
  xSearchAutoClose = #True
  
  xRadioAutoClose = #True
  
  xSorting = #True
  SoundSchemePointerMode = 1

  OutOfSessionPause = #True
  InitOutOfSession()
  
  
  
  xTrayIconVisible = #True
  xMWinPos\left = -1
  xMWinPos\Right = -1
  xMWinPos\Top = -1
  xMWinPos\Bottom = -1
  RePosWindow()
  
RestoreRegOnly1:
  ;CommandZ = "/BASE=\TEST"
  ;CommandX = "/BASE=\TEST"
  
  
  If Not RestoreRegOnlyNow = 0
    Goto RestoreRegOnly2
    EndIf
  
  If vKioskMode
    xMenu(0) = LoadResEx_Menu(1010)
    xMenu(2) = LoadResEx_Menu(1130)
    ;xMenu(3) = LoadResEx_Menu(1130)
    xMenu(5) = LoadResEx_Menu(1070)
    xMenu(8) = LoadResEx_Menu(1075)
    Else
    xMenu(0) = LoadResEx_Menu(1000)
    xMenu(2) = LoadResEx_Menu(1100)
    xMenu(3) = LoadResEx_Menu(1110)
    xMenu(5) = LoadResEx_Menu(1060)
    xMenu(6) = LoadResEx_Menu(1140)
    xMenu(7) = LoadResEx_Menu(1141)
    xMenu(8) = LoadResEx_Menu(1065) ; 1000
    ;xPopupMenu(3) = CreatePopupMenu()
    EndIf
  xMenu(1) = LoadResEx_Menu(1050)
  xMenu(4) = LoadResEx_Menu(1120)
  If xMenu(0)
    SetMenu_(MainHWnd, xMenu(0))
    DrawMenuBar_(MainHWnd)
    CompilerIf #LoadShellDriveIcons
      If Not ShellDrvInited
        ShellDrvInitialize()
        EndIf
      CompilerEndIf
    EndIf
  
  For xLong1 = 1 To #xMenuCountX
    If xMenu(xLong1)
      xPopupMenu(xLong1) = MakePopupMenu(xMenu(xLong1))
;Debug Str(xMenu(xLong1)) + "/" + Str(xPopupMenu(xLong1))
      If Not xPopupMenu(xLong1)
        DestroyMenu_(xMenu(xLong1))
        xMenu(xLong1) = 0
        EndIf
      EndIf
    Next
  CompilerIf #LoadShellDriveIcons
    If Not ShellDrvInited
      ShellDrvInitialize()
      EndIf
    CompilerEndIf

  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Loading player form")
    CompilerEndIf



  If FindString(CommandX, "/LED")
    LEDMode = #True
    CompilerIf #PB_Compiler_Unicode
      ;= nt
      MapVirtualKeyA_H14 = MapVirtualKey_($14, 0)
      MapVirtualKeyA_H90 = MapVirtualKey_($90, 0)
      MapVirtualKeyA_H91 = MapVirtualKey_($91, 0)
      CompilerEndIf
    LEDState = $2
    SpectrumProcKb(0, 0, 0, 0)
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Starting LED timer")
      CompilerEndIf
    SetTimer_(MainHWnd, 0, #SpectrumProcIntervalKb, @SpectrumProcKb())
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("LED timer started")
      CompilerEndIf
    LEDState = 0
    EndIf


  If FindString(CommandX, "/HIDETASK") And xProcID
    RegisterServiceProcess(xProcID, 1)
    EndIf
  If FindString(CommandX, "/NOTASKMGR")
    SystemParametersInfo_(#SPI_SETSCREENSAVERRUNNING, #True, 1, 0)
    EndIf

  ;LoadResEx_SetDlgItemCaption(Me)
  LoadResEx_WindowIcon_MultiOS(MainHWnd, 1315, 1300, @SysTrayIcon)
  ;If MP3GetFormat
  ;  MainForm_DrawRawBMP_CalaymStatic(-1, FormatIcon(-1), 0)
  ;  endif

  MainForm_EnableApiMenu(407, #False)
  MainForm_EnableApiMenu(408, #False)
  
  MainForm_EnableApiMenu(411, #False)
  MainForm_EnableApiMenu(412, #False)
  MainForm_EnableApiMenu(413, #False)
  MainForm_EnableApiMenu(414, #False)
  MainForm_EnableApiMenu(420, #False)
  MainForm_EnableApiMenu(428, #False)
  MainForm_EnableApiMenu(429, #False)
  MainForm_EnableApiMenu(443, #False)
  MainForm_EnableApiMenu(444, #False)
  
  RadioApiMenu(425, 427, 425 + xDirListModeSet)

  ;EnableApiMenu 445, #False
  DoEvents()
  If Not FindString(CommandX, "/FAILSAVE") + FindString(CommandX, "/NOLOADSETTINGS") + FindString(CommandX, "/DEFAULT") = 0
    Goto Rs1
    EndIf

RestoreRegOnly2:

  hFile = TxtFileReader_FromFile(AppBase_GetByExt("ini"))
  If Not hFile = 0
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Reading setup file (" + AppBase_GetByExt("ini") + ")")
      CompilerEndIf
    While TxtFileReader_NextLine(hFile)
      xChar1 = TxtFileReader_GetLineString(hFile)
      xLong1 = FindString(xChar1 + "=", "=")
      If Not xLong1 = 0
        xChar2 = Mid(xChar1, xLong1 + 1)
        xChar1 = Left(xChar1, xLong1 - 1)
        xLong1 = Val(xChar2)
        If xLong1 > 0
          xBool3 = #True
          Else
          xBool3 = #False
          EndIf
        If UCase(Left(xChar1, 3)) = "KEY"
          ApplySpecKeyByStrAndMaybeReset(UCase(Mid(xChar1, 4)), UCase(xChar2))
          Else
          Select UCase(xChar1)
            Case "ALLOWFILEDELETING"
              xDelMode = xBool3
              ;EnableApiMenu 133, xDelMode
              ;EnableApiMenu 230, xDelMode
            Case "AUTOPLAY"
              xAutoPlayback = xBool3
              xReAutoPlay = xAutoPlayback
            Case "AUTOPAUSEONUSERSWITCH"
              OutOfSessionPause = xBool3
            Case "AUTOSWITCHIRADIOVIEW"
              xAutoSwitchIRadioOEPl = xBool3
            Case "BLOCKIDEWHILELOADING"
              xClassicBlockingOnLoad = xBool3
            Case "CDDA"
              CDDAUse = xBool3
            Case "CDDAJITTERCORRECTION"
              CDDAJitter = xBool3
            Case "CHECKACCURATESTREAMS"
              CheckAccurate = xBool3
            Case "CHECKSONGSONPLAYLISTLOAD"
              RemoveMissingOnPLLoad = xBool3
            Case "CROSSFADETIME"
              xLong1 = xLong1 - #xFadeConsts1
              If xLong1 < 0
                xCrossFadeTimeM = 0
                ElseIf xLong1 > #xFadeConstsX
                xCrossFadeTimeM = #xFadeConstsX
                Else
                xCrossFadeTimeM = xLong1
                EndIf
            Case "DIRECTORYLISTALIGNMENT"
              If xLong1 < 4 And Not xLong1 < 0
                If xLong1 = 3
                  If xDirListEffDirs > #xDirListEffMax2
                    xDirListModeCur = 2
CompilerIf #AutoDirPosOnTop
                    ElseIf xDirListEffDirs > xDirListEffMax1
                    xDirListModeCur = 1
CompilerEndIf
                    Else
                    xDirListModeCur = 0
                    EndIf
                  Else
                  xDirListModeCur = xLong1
                  EndIf
                xDirListModeSet = xLong1
                EndIf
            Case "DIRECTORYLISTTOPHEIGHT"
              If xLong1 > 0 And Not xLong1 > #xDirListMaxTH
                xDirListTopHeight = xLong1
                EndIf
            Case "DIRECTORYLISTLEFTWIDTH"
              If Not (xLong1 < #xDirListMinLW Or xLong1 > #xDirListMaxLW)
                xDirListLeftWidth = xLong1
                EndIf
            Case "DISABLEWINDOWSSOUNDS"
              If xLong1 < 3 And Not xLong1 < 0
                SoundSchemePointerMode = xLong1
                ;ApplyProcessMode
                EndIf
            Case "ELAPSEDTIME"
              xShowElapsed = xBool3
            Case "ENDSONGMODE"
              If xLong1 < 4 And Not xLong1 < 0
                xProcessMode = xLong1
                ;ApplyProcessMode
                EndIf
            Case "ENDSTREAMS"
              GetValidSkipper(#ctSSLayer_MusicTypeStream, xLong1)
            Case "ENDTRACKERS"
              GetValidSkipper(#ctSSLayer_MusicTypeTracker, xLong1)
            Case "ENDCDAUDIO"
              GetValidSkipper(#ctSSLayer_MusicTypeCDAudio, xLong1)
            Case "FADING"
              xGenFading = xBool3
            Case "FAILSAVE"
              If FindString(CommandX, "/NOFAILSAVE") = 0 And RestoreRegOnlyNow = 0
                xBool2_FailSave = xBool3
                EndIf
            Case "FOLLOWSONG"
              xFollowCurSong = xBool3
            Case "GETFILEFORMAT", "GETMP3FORMAT"
              MP3GetFormat = xBool3
              MP3GetFormatChanged(#False)
            Case "GETFILEINFOS"
              MP3GetID3Tag = xBool3
              If RestoreRegOnlyNow = 0
                If MP3GetID3Tag
                  ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Tags), 5)
                  Else
                  ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Tags), 0)
                  EndIf
                EndIf
            Case "GLOBALPLAYKEYS"
              GlobalKeys = xBool3
            Case "IGNOREUNDERSCORED"
              IgnoreUnderscored = xBool3
            Case "INTROMODE"
              If xLong1 < 0
                IntroModeActive = #False
                xLong1 = -xLong1
                Else
                IntroModeActive = #True
                EndIf
              If xLong1 < #IntroMdSkipperMinVal
                IntroModeTime = #IntroMdSkipperMinVal
                ElseIf xLong1 > #IntroMdSkipperMaxVal
                IntroModeTime = #IntroMdSkipperMaxVal
                Else
                IntroModeTime = xLong1
                EndIf
            Case "NOVERWARN": xNoVerWarnDLL = LCase(xChar2)
            Case "OUTPUTDEVICE"
              xOutputSSLID = xChar2
            Case "PLAYERWINDOWPOS"
              If RestoreRegOnlyNow = 0
                GetMyWindowPos(xChar2, xLong1)
                EndIf
            Case "PLAYERWINDOWSTATE"
              If xLong1 < 3 And Not xLong1 < -1
                StartUpWindowMode = xLong1
                EndIf
            Case "PLAYLISTDOUBLECLICK"
              If xLong1 < 3 And Not xLong1 < 0
                PlDClickAction = xLong1
                EndIf
            Case "PLAYLISTUPDATEINTERVAL"
              If xLong1 < 3 And Not xLong1 < 0
                LockWinUpd = xLong1
                EndIf
            Case "PRIORITY"
              If xLong1 < -2
                PlayerPriority = -2
                ElseIf xLong1 > 3
                PlayerPriority = 3
                Else
                PlayerPriority = xLong1
                EndIf
    CompilerIf #UseIRPlugins
            Case "RADIOWINDOWPOS"
              GetMyWindowPos(xMWindowID_IRadio, xChar2, xLong1)
    CompilerEndIf
            Case "RADIOAUTOCLOSE"
              xRadioAutoClose = xBool3
            Case "RANDOMSEEK"
              RandomPosOnTrackerSkipper = xBool3
            Case "REGISTERFOLDERS"
                For xLong2 = 0 To 3
                  If xLong1 & 1
                    RegFolderMode(xLong2) = #True
                    EndIf
                  xLong1 >> 1
                  Next
            Case "REMOVEMISSINGSONGS"
              xRemoveMissingSongs = xBool3
            Case "REMOVEPLAYEDSONGS"
              xRemovePlayedSongs = xBool3
            Case "REMOVESKIPPEDSONGS"
              xRemoveSkippedSongs = xBool3
            Case "REPEATMODE"
              If xLong1 < 3 And Not xLong1 < 0
                xRep = xLong1
                EndIf
            Case "SEARCHAUTOCLOSE"
              xSearchAutoClose = xBool3
            Case "SEARCHAUTOPLAY"
              xSearchAutoPlay = xBool3
            Case "SHOWFULLPATH"
              ShowFullPath = xBool3
            Case "SHOWFULLTITLE"
              ShowFullTitle = xBool3
  ;            compilerif #SelfPathElipse
  ;              ;NeedIRPathElipse = #True
  ;              compilerendif
            Case "SORTING"
              xSorting = xBool3
            Case "SPECTRUM"
              If xLong1 & 1
                xBool1_Spectrum = #True
                EndIf
              If xLong1 & 2
                xDeluxeSpectrum = #True
                EndIf
    ;        Case "TAGSFONT"
    ;          GrabPLFont 1, xChar2
            Case "TITLESPOSITION"
              If Not (xLong1 < 0 Or xLong1 > 15)
                xTitlesPos = xLong1
                EndIf
            Case "TITLESWHENMINIMIZED"
              If Not (xLong1 < 0 Or xLong1 > 2)
                xTitlesWhenMinimized = xLong1
                EndIf
            Case "TRACKERPANSEPERATION"
              If xLong1 < 0
                xModPanning = 0
                ElseIf xLong1 > 100
                xModPanning = 100
                Else
                xModPanning = xLong1
                EndIf
            Case "TRAYICON"
              xTrayIconVisible = xBool3
            Case "TRAYLEFTCLICK"
              If xLong1 < 7 And Not xLong1 < 0
                xTrayIconLeft = xLong1
                EndIf
            Case "TRAYMINIMIZE", "MINIMIZETOTRAY"
              xTrayIconEnabled = xBool3
            Case "TRAYRIGHTCLICK"
              If xLong1 < 3 And Not xLong1 < 0
                xTrayIconRight = xLong1
                EndIf
            Case "USEDFILETYPES"
                xUsedTypes = xChar2
            Case "USEPLAYLISTSETTINGS"
              UsePLSettings = xBool3
            Case "VOLUME"
              If xLong1 > 255
                xSetVolume = 255
                ElseIf xLong1 < 0
                xSetVolume = 0
                Else
                xSetVolume = xLong1
                EndIf
              PlayerIsLocked = #True
            CompilerIf #UseFileLogging
              Case ""
              Default
                MainForm_ctConsoleA_AddLog("Unknown tag: <" + xChar1 + "> (tag ignored)")
              CompilerEndIf
            EndSelect
          EndIf
        EndIf
      Wend
    
    TxtFileReader_Close(hFile)
CompilerIf #UseFileLogging
    Else
    MainForm_ctConsoleA_AddLog("Error reading setup file (" + AppBase_GetByExt("ini") + ")")
CompilerEndIf
    EndIf













Rs1:
  If Not RestoreRegOnlyNow = 0
    If RestoreRegOnlyNow = 2
      xChar1 = "Software\Microsoft\Windows\CurrentVersion\Run"
      If RegOpenKeyEx_($80000001, @xChar1, 0, 2, @xLong1)
        xChar1 = LoadResString(3500)
        RegDeleteValue_(xLong1, @xChar1)
        RegCloseKey_(xLong1)
        EndIf
      For xLong1 = 0 To 3
        RegFolderMode(xLong1) = #True
        Next
      EndIf
    MainForm_RestoreScheme()
    UpdateFolderReg(#False)
    TestRestoreReg(#True)
    xInfoQuit = #True
    ProcedureReturn
    EndIf
  
  GetIsAutoRun()
  
  
  MainForm_UpdateMyFont()
  UpdateFolderReg(#True)
  MainForm_ApplyProcessMode()
  
  MainForm_EnableApiMenu(133, xDelMode)
  MainForm_EnableApiMenu(230, xDelMode)
  CheckApiMenu(301, xGenFading)
  CheckApiMenu(310, xFollowCurSong)
  CheckApiMenu(303, MP3GetID3Tag)
  CheckApiMenu(320, xRemoveMissingSongs)
  CheckApiMenu(321, xRemoveSkippedSongs)
  CheckApiMenu(322, xRemovePlayedSongs)
  
  
  MainForm_LockMe(#True)
  xPStateIconStartup = #True
  MainForm_UpdateMainIcon()
  
  SetPanelSize()
  EnableWindow_(MainHWnd, 1)

  If StartUpWindowMode = -1
    GetStartupInfo_(@xType2)
    With xType2
      If (\dwFlags & #STARTF_USEPOSITION) = #STARTF_USEPOSITION
        xMWinPos\left = \dwX
        xMWinPos\Top = \dwY
        EndIf
      If (\dwFlags & #STARTF_USESIZE) = #STARTF_USESIZE
        xMWinPos\Right = \dwXSize
        xMWinPos\Bottom = \dwYSize
        EndIf
      CheckValidScreen(#False)
      If (\dwFlags & #STARTF_USESHOWWINDOW) = #STARTF_USESHOWWINDOW
        If (\wShowWindow & $6) = $6
          ;WindowState = 2
          ShowWindow_(MainHWnd, 3)
          ElseIf (\wShowWindow & $2) = $2
          ;WindowState = 1
          ShowWindow_(MainHWnd, 7)
          Else
          ShowWindow_(MainHWnd, 5)
          EndIf
        EndIf
      EndWith
    Else
    CheckValidScreen(#False)
    Select StartUpWindowMode
      Case 1
        ShowWindow_(MainHWnd, 7)
      Case 2
        ShowWindow_(MainHWnd, 3)
      Default
        ShowWindow_(MainHWnd, 5)
      EndSelect
    EndIf

  DoEvents()

  xTrayIconOld = 0
  MainForm_ShowTray(#False)




  If Not (FindString(CommandX, "/SHOWFAILSAVE") = 0 Or RestoreRegOnlyNow)
    xBool2_FailSave = #True
    EndIf
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Performing settings")
    CompilerEndIf
  CalcCrossFadeConsts()
  xLong1 = FindString(CommandX, "/LOCKED")
  If xLong1 = 0
    xLong1 = FindString(CommandX, "/KIOSK")
    Else
    xLong1 = xLong1 + 1
    EndIf

  
  
  If Not FindString(CommandX, "/NOSPECTRUM") = 0
    xNoSpectrumForce = #True
    xBool1_Spectrum = #False
    If Not xLong1 = 0
      CheckApiMenu(302, #False)
      MainForm_EnableApiMenu(302, #False)
      EndIf
    EndIf

  SetFormatToolTip(LoadResString(1900), "")
  If vKioskMode
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("  Applying kiosk mode settings")
      CompilerEndIf
    If Not FindString(CommandX, "/VOLUME") = 0
      vCanVolume = #True
      Else
      For xLong1 = 340 To 355
        MainForm_EnableApiMenu(xLong1, #False)
        Next
      EndIf
    If Mid(CommandX, xLong1 + 6, 1) = ":"
      xChar1 = Mid(CommandX, xLong1 + 7)
      xChar1 = LCase(Left(xChar1, FindString(xChar1 + " ", " ") - 1)) + ","
      HandleSett(xChar1)
      EndIf
    ;SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Tags), 0, 0, PanelSizeDef, 320, 24, $214)
    MainForm_EnableApiMenu(104, #False)
    MainForm_EnableApiMenu(405, #False)
    CanIRadio = #False
    MainForm_EnableApiMenu(406, #False)
    MainForm_EnableApiMenu(419, #False)
    MainForm_EnableApiMenu(450, #False)
    SetToolTip(#xStaticIcons_Def3, LoadResString(1140), ExtKbdEx(#KbdC_CStop))
    If Not PlDClickAction = 0
      MainForm_EnableApiMenu(201, #False)
      EndIf
    If PlDClickAction = 2
      MainForm_EnableApiMenu(202, #False)
      EndIf
    If xProcessMode = 3
      xProcessMode = 0
      EndIf
    IntroModeActive = #False
    xAutoPlayback = #True
    xReAutoPlay = #True
    xBool2_FailSave = #False
    Else
    ;Set DragClass = New IDropTargetClass
    ;DragClass\DragOver($F0F00F0F, @MainForm_DropFiles(), 0, #DROPEFFECT_NONE)
    ;RegisterDragDrop(MainHWnd, ObjPtr(DragClass))
    DragAcceptFiles_(MainHWnd, #True)
    EndIf


  CompilerIf #FlatCastCF17
    Set xFCI = CreateObject("FlP40.CCtrlProd")
    CompilerEndIf

  MainForm_ApplyRepMode()
  
  xLong1 = FindString(CommandX, "/SET")
  If Mid(CommandX, xLong1 + 4, 1) = ":" And Not (xLong1 = 0 Or vKioskMode)
    xChar1 = Mid(CommandX, xLong1 + 5)
    xChar1 = LCase(Left(xChar1, FindString(xChar1 + " ", " ") - 1)) + ","
    HandleSett(xChar1)
    EndIf
  
  
  xLong1 = #False
  If xDirListModeCur = 1
    If (xDirListModeCur > 0 And Not xDirListTopHeight = #xDirListMaxTH)
      xLong1 = #True
      EndIf
    ElseIf xDirListModeCur = 2
    If (xDirListModeCur > 0 And Not xDirListLeftWidth = #xDirListMaxLW)
      xLong1 = #True
      EndIf
    EndIf
  MainForm_EnableApiMenu(429, xLong1)
  MainForm_EnableApiMenu(428, xLong1)


  ;If xDirListModeCur > 0
  MainForm_ToggleDirList(#False, #True)

  If FindString(CommandX, "/NOMSG")
    xNoIRMode = #True
    EndIf

  MainForm_XMenuRefresherDevices()

  If Not FindString(CommandX, "/NOPLMENU") = 0
    xNoPLMenu = #True
    MainForm_EnableApiMenu(32, #False)
    EndIf
  
  If Not FindString(CommandX, "/NOSAVELIST") = 0
    If Not FindString(CommandX, "/NOSAVELISTMENU") = 0
      MainForm_EnableApiMenu(40, #False)
      MainForm_EnableApiMenu(41, #False)
      xNoSaveListMenu = 2
      Else
      xNoSaveListMenu = 1
      EndIf
    EndIf
  
  If FindString(CommandX, "/NOQUIT") = 0
    If FindString(CommandX, "/SHUTDOWN") = 0
      If FindString(CommandX, "/HIBERNATE") = 0
        If FindString(CommandX, "/STANDBY") = 0
          If xShellMode
            xCmdQuitMode = 2
            If xTrayIconEnabled
              xTrayIconEnabled = #False
              MainForm_ShowTray(#True)
              EndIf
            Else
            xCmdQuitMode = 3
            EndIf
          Else
          xCmdQuitMode = 5
          EndIf
        Else
        xCmdQuitMode = 4
        EndIf
      Else
      xCmdQuitMode = 1
      EndIf
    Else
    xNoQuitMenu = #True
    MainForm_EnableApiMenu(60, #False)
    EndIf

  ;If Not FindString(CommandX, "/SECURE") = 0 Or vKioskMode
  If xSecureMode
    ;xSecureMode = #True
    MainForm_EnableApiMenu(10, #False)
    MainForm_EnableApiMenu(12, #False)
    MainForm_EnableApiMenu(31, #False)
    MainForm_EnableApiMenu(41, #False)
    MainForm_EnableApiMenu(133, #False)
    MainForm_EnableApiMenu(134, #False)
    MainForm_EnableApiMenu(230, #False)
    MainForm_EnableApiMenu(250, #False)
    MainForm_EnableApiMenu(442, #False)
    MainForm_EnableApiMenu(443, #False)
    MainForm_EnableApiMenu(461, #False)
    MainForm_EnableApiMenu(462, #False)
    MainForm_EnableApiMenu(501, #False)
    EndIf
  
  If FindString(CommandX, "/URL") Or Not (xSecureMode Or vKioskMode)
    UrlsAllowed = #True
    EndIf
  If FindString(CommandX, "/DRAG") Or Not (xSecureMode Or vKioskMode)
    DragOut = #True
    EndIf
  
  If FindString(CommandX, "/NOSETUP")
    xNoSetup = #True
    MainForm_EnableApiMenu(415, #False)
    MainForm_EnableApiMenu(360, #False)
    xBool2_FailSave = #False
    EndIf
    
    
  xSupportedFilesS = #UsedTypesVBNullChar + ReplaceString(ReplaceString(ctSSLayer_GetInfoString($10), ",", #UsedTypesVBNullChar), ";", #UsedTypesVBNullChar)
  xSupportedFilesM = ReplaceString(ReplaceString(ctSSLayer_GetInfoString($12), ",", #UsedTypesVBNullChar), ";", #UsedTypesVBNullChar)
  xSupportedFiles = xSupportedFilesS + ReplaceString(ReplaceString(ctSSLayer_GetInfoString($11), ",", #UsedTypesVBNullChar), ";", #UsedTypesVBNullChar) + xSupportedFilesM
  xSupportedFilesM = #UsedTypesVBNullChar + xSupportedFilesM
  If ctSSLayer_CanUseItem($A) = 1
    xSupportedFiles = xSupportedFiles + "cda" + #UsedTypesVBNullChar
    EndIf
  xSupportedFiles = MainForm_ResortTypes(xSupportedFiles)
  
  CheckFileTypes()
    
  
  If FindString(CommandX, "/NOSAVESETTINGS")
    MainForm_EnableApiMenu(470, #False)
    ElseIf Not vKioskMode
    xCmdSaveSet = #True
    EndIf
  
  If xCmdSaveSet
    If xBool2_FailSave
      If (ctSSLayer_CanUseItem(4) = 1 Or MaxDeviceCount > 1) And Not (MaxDeviceCount = 0 Or ctSSLayer_CanUseItem($20) > 19)
        If FindString(CommandX, "/SHOWFAILSAVE")
          GenericMessageHandler_Param = 2071
          xAutoIgnoreTime = -1
          Else
          xAutoIgnoreTime = GetTickTimeMS()
          GenericMessageHandler_Param = 2070
          EndIf
        If LoadResEx_Dialog(MainHWnd, 2070, 2090, 2091, @GenericMessageHandler()) = 2091
          xInfoQuit = #True
          If LEDMode
            LEDState = 1
            KillTimer_(MainHWnd, 0)
            DoEvents()
            SpectrumProcKb(0, 0, 0, 0)
            EndIf
          ctSSLayer_UnLoadVB()
          ErMustQuit()
          ProcedureReturn
          EndIf
        EndIf
      Else
      MainForm_SaveSettings(1, xBool1_Spectrum)
      EndIf
    EndIf
  
  If Not FindString(CommandX, "/NOAUTOREFRESH") = 0
    xNoAutoRefresh = #True
    EndIf
  If xNoAutoRefresh Or Not FindString(CommandX, "/NOUSERAUTOREFRESH") = 0
    xNoAutoRefreshByUser = #True
    MainForm_EnableApiMenu(410, #False)
    MainForm_EnableApiMenu(411, #False)
    MainForm_EnableApiMenu(412, #False)
    MainForm_EnableApiMenu(413, #False)
    MainForm_EnableApiMenu(414, #False)
    MainForm_EnableApiMenu(415, #False)
    ;If Not vKioskMode
    ;  endif
    Else
    If Not FindString(CommandX, "/NOAUTOSETUP") = 0
      MainForm_EnableApiMenu(415, #False)
      xNoAutoSetup = #True
      ;If Not vKioskMode
        ;mTMenu(3).Visible = #False
        ;mTMenu(5).Visible = Not (xAutoDirCount = 0 Or vKioskMode)
      ;  endif
      EndIf
    EndIf
    
  
  
  DoEvents()
  
  If Not FindString(CommandX, "/NOPRESETS") = 0
    xNoPresets = #True
    MainForm_EnableApiMenu(460, #False)
    MainForm_EnableApiMenu(461, #False)
    MainForm_EnableApiMenu(462, #False)
    MainForm_EnableApiMenu(463, #False)
    EndIf
  
  If Not FindString(CommandX, "/NOTIMER") = 0
    xNoTimers = #True
    MainForm_EnableApiMenu(440, #False)
    MainForm_EnableApiMenu(441, #False)
    MainForm_EnableApiMenu(442, #False)
    MainForm_EnableApiMenu(443, #False)
    MainForm_EnableApiMenu(444, #False)
    MainForm_EnableApiMenu(445, #False)
    EndIf


  ctSSLayer_RefreshDeviceList(MainHWnd)
  xInitMe(MainHWnd, xBool2_FailSave, xBool1_Spectrum, #True)


  If xInfoQuit
    ErMustQuit()
    ProcedureReturn
    EndIf

  If ctSSLayer_CanUseItem($11) = 0
    MainForm_EnableApiMenu(405, #False)
    Else
    CanIRadio = #True
    EndIf

  If ctSSLayer_CanUseItem(0) = 0
    CDDAUse = #False
    CDDAJitter = #False
    ElseIf ctSSLayer_CanUseItem(0) = 1
    CDDAUse = #True
    EndIf
  If ctSSLayer_CanUseItem(1) = 0
    CDDAJitter = #False
    ElseIf ctSSLayer_CanUseItem(1) = 1
    CDDAJitter = #True
    EndIf
  If ctSSLayer_CanUseItem(3) = 0
    CheckAccurate = #False
    ElseIf ctSSLayer_CanUseItem(3) = 1
    CheckAccurate = #True
    EndIf
  If ctSSLayer_CanUseItem($12) = 0
    xClassicBlockingOnLoad = #True
    ElseIf ctSSLayer_CanUseItem($12) = 1
    xClassicBlockingOnLoad = #False
    EndIf

  DoEvents()
  
  MainForm_UpdateMenus()
  
  ReSetTearArrayCount()

  MainForm_DrawVolFaderA(xSetVolume); 2
  DoVolume(xSetVolume, #True)
  
  DoEvents()

  SetPanelSize()
  NewSongID = Tear_Create()



  SetTimer_(MainHWnd, 4, 100, @TearDown())



  If FindString(CommandX, "/NOLOADLIST") = 0
    If Len(xChar1)
      xChar1 = GetFullPathName(xChar1)
      If AllowedItem(xChar1, #True) = 255
        xBool3 = LoadPList(xChar1, #False, #True) ;Not xBool2)
        ElseIf AllowedItem(xChar1, #True) = 0
        xBool3 = AddFDirNowSubEx(xChar1, #False)
        EndIf
      EndIf
    If Not xBool3
      xChar1 = FilteredCMD(CommandZ)
      ;Stop
      If Len(xChar1)
        xChar1 = GetFullPathName(xChar1)
        If AllowedItem(xChar1, #True) = 255
          xBool3 = LoadPList(xChar1, #False, #True) ;Not xBool2)
          ElseIf AllowedItem(xChar1, #True) = 0
          xBool3 = AddFDirNowSubEx(xChar1, #False)
          EndIf
        EndIf
      If Not xBool3
        xCurPlistFilename = AppBase_GetByExt(#DefaultPLExtension)
        LoadPList(xCurPlistFilename, #False, #True) ;Not xBool2)
        xCurPlistFilenameSuggestNew = #True
        EndIf
      EndIf
    MainForm_LockMe(#True)
    EndIf
  
  
  
  DoEvents()
  
  
  
;  On Error GoTo 0
  CompilerIf #TrayIconViaTimerCheck
    xTrayIconCrashUpdateTimer = GetTickTimeMS()
    CompilerEndIf


  If Not xBool4_HasBase
    xChar1 = Trim(GetSpecialFolderPath(5, #False))
    If Len(xChar1) > 3
      If IsDirExists(xChar1 + "\Calaym")
        m3uList = xChar1 + "\Calaym"
        Else
        m3uList = xChar1
        EndIf
      EndIf
    EndIf
  
  If Len(m3uList) = 0
    xChar1 = AppBase_GetPathBaseFile()
    m3uList = SimpleDir(xChar1)
    EndIf
  

  
  vPLXMain = m3uList + "\"
  If Len(m3uList) = 2
    m3uList = m3uList + "\"
    EndIf
  PresetFile = m3uList
  TimerDir = m3uList
  xLastDirectory = m3uList
  
  MainForm_EnableApiMenu(33, #False)
  MainForm_EnableApiMenu(463, #False)
  MainForm_EnableApiMenu(445, #False)
  
  MainForm_XMenuRefresherFileDir() ;(#False)
  
  DoEvents()



  If FindString(CommandX, "/PLAY") Or (xAutoPlayback And Not (xBool2_FailSave Or xPStateIconPlaying))
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Starting playback")
      CompilerEndIf
    MainForm_LockMe(#False)
    MainForm_xPlayClick(#False)
    MainForm_LockMe(#True)
    EndIf

  If IsIconic_(MainHWnd)
    If xPStateIconPlaying
      If xTrayIconEnabled
        ShowWindow_(MainHWnd, 7)
        ShowWindow_(MainHWnd, 0)
        xTrayIconIndicator = #True
        EndIf
      Else
      ShowWindow_(MainHWnd, 9)
      DoEvents()
      If xTrayIconIndicator
        xTrayIconIndicator = #False
        MainForm_ShowTray(#True)
        Else
        SetForegroundWindow_(MainHWnd)
        SetWindowPos_(MainHWnd, -1, 0, 0, 0, 0, $3)
        SetWindowPos_(MainHWnd, -2, 0, 0, 0, 0, $3)
        DoEvents()
        SetForegroundWindow_(MainHWnd)
        ShowWindow_(MainHWnd, 9)
        EndIf
      EndIf
    EndIf

  DoEvents()
  If Not PLCurItem = 0
    xMarkSong(PLCurItem, #False, #False)
    EndIf
  DoEvents()
  MainForm_UpdateMainIcon()
  
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Starting timers / spectrum")
    CompilerEndIf
  
  SetTimer_(MainHWnd, 1, #GUIInterval, @eTimerEvent())
  xFindNtfy = FindFirstChangeNotification_(@vPLXMain, 0, 1)
  xTimerIsEnabled = #True


  If xNoSpektrumOnStartup
    xBool1_Spectrum = #False
    EndIf
  If ctSSLayer_CanUseItem(4)
    If xBool1_Spectrum
      CheckApiMenu(302, #True)
      xShowSpectrum = #True
      SetPanelSize()
      If LEDMode = 0
        ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Spectrum), 5)
        EndIf
      MainForm_DesireSpectrumState(#True, #True)
      Else
      CheckApiMenu(302, #False)
      EndIf
    Else
    MainForm_EnableApiMenu(302, #False)
    EndIf
  
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Performing misc options")
    CompilerEndIf
  
  CompilerIf Not #PB_Compiler_Processor = #PB_Processor_x64
    If IsFileExists(xRealBaseFile + "chm")
      xLong1 = LoadLibrary_("hhctrl.ocx")
      If Not xLong1 = 0
        xUseChmHelp = #True
        FreeLibrary_(xLong1)
        EndIf
      EndIf
    CompilerEndIf
  
  ; // notutorial
  
  xLong1 = FindString(CommandX, "/LOADTIMER")
  If Not (xNoTimers Or xLong1 = 0)
    xChar1 = Mid(CommandX + " ", xLong1 + 10)
    Select Left(xChar1, 1)
      Case ":", "="
        xChar1 = Trim(Mid(xChar1, 2))
        If Left(xChar1, 1) = Chr(34)
          xChar1 = Mid(xChar1, 2)
          xLong1 = FindString(xChar1, Chr(34))
          Else
          xLong1 = FindString(xChar1 + " ", " ")
          EndIf
        If Not xLong1 = 0
          xChar1 = Left(xChar1, xLong1 - 1)
          EndIf
        MainForm_LoadTimers(MainHWnd, xChar1, #False)
      Case " "
        MainForm_LoadTimers(MainHWnd, AppBase_GetByExt("cpt"), #False)
      EndSelect
    EndIf
  
  
  
;...      ShowInfo
  
  xPStateIconStartup = #False
  DoAnimateReadDir(0)
  
  MainForm_UpdateMainIcon()
  MainForm_LockMe(#False)
 
  If ctSSLayer_CanUseItem($20) And xCmdSaveSet And Not RestoreRegOnlyNow
    If Not LCase(ctSSLayer_GetInfoString(4)) = xNoVerWarnDLL
      ShowInitInfo()
      EndIf
    EndIf
 
;  On Error GoTo 0
  
  AutoSwitchIRadioCheck(#True)
  EndProcedure

Procedure Main()
  CompilerIf #HowToDeferWindowPos = 1
    Set TrDeferWindowPos_Coll = New Collection
    CompilerEndIf
  ;Load OLEHelperForm
  DoThemeUpdates()
  MainForm_StartPlayer()
  If MainHWnd = 0
    ;If *ptrTemp = 0
      ;ApplicationClose
      ;EndIf
    Else
    MessageHandler()
    EndIf
  EndProcedure

Procedure SetAutoDirVar(NewIndex.i)
  If Not xDirListModeSet = NewIndex
    xDirListModeSet = NewIndex
    RadioApiMenu(424, 427, 424 + xDirListModeSet)
    EndIf
  
  If NewIndex = 3
    If xDirListEffDirs > #xDirListEffMax2
      NewIndex = 2
CompilerIf #AutoDirPosOnTop
      ElseIf xDirListEffDirs > xDirListEffMax1
      NewIndex = 1
CompilerEndIf
      Else
      NewIndex = 0
      EndIf
    Else
    NewIndex = NewIndex
    EndIf
  If Not xDirListModeCur = NewIndex
    xDirListModeCur = NewIndex
    MainForm_ToggleDirList(#True, #False)
    EndIf
  EndProcedure

Procedure ReCreateIRFont()
  Define.i xLong1
  Define.i xLong2
  Define.LOGFONT xType1
  Define.TEXTMETRIC xType2
  Define.POINT xType3

  xIRBarHeight = 34
  SystemParametersInfo_(#SPI_GETICONTITLELOGFONT, SizeOf(LOGFONT), @xType1, 0)

  ;xIRBarHeight = 3 + 32 * DPIScaleY

  If DPIScaleY > 1
    xType1\lfHeight = Int((21 * DPIScaleY) / xGlobalDialogUnits)
    If xType1\lfQuality < 2
      xType1\lfQuality = 2
      EndIf
    Else
    xType1\lfHeight = Int(21 / xGlobalDialogUnits)
    EndIf
  hFontShIRIsVerticalBitmapFont = #False
  If xTitlesPos = 1 Or xTitlesPos = 2
    xType1\lfEscapement = 900
    xType1\lfOrientation = 900
    ;xType1.lfOutPrecision = 7
    xLong1 = CreateFontIndirect_(@xType1)
    If Not xLong1 = 0
      If Not SelectObject_(xSharedDC, xLong1) = 0
        GetTextExtentPoint32_(xSharedDC, #DefTxt, #LenDefTxt, @xType3)
        xIRBarHeight = xType3\y + 4
        If GetTextMetrics_(xSharedDC, xType2)
          SelectObject_(xSharedDC, hFontGFix)
          If (xType2\tmPitchAndFamily & $6) = 0
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("Bitmap font; Cannot be used vertically")
            CompilerEndIf
            hFontShIRIsVerticalBitmapFont = #True
            EndIf
          Else
          SelectObject_(xSharedDC, hFontGFix)
          EndIf
        EndIf
      EndIf
    Else
    xLong1 = CreateFontIndirect_(@xType1)
    If Not xLong1 = 0
      If Not SelectObject_(xSharedDC, xLong1) = 0
        GetTextExtentPoint32_(xSharedDC, #DefTxt, #LenDefTxt, xType3)
        xIRBarHeight = xType3\y + 4
        SelectObject_(xSharedDC, hFontGFix)
        EndIf
      EndIf
    EndIf
   If xIRBarHeight < 34
     xIRBarHeight = 34
     EndIf
  If Not hFontShIR = 0
    DeleteObject_(hFontShIR)
    EndIf
  hFontShIR = xLong1
  EndProcedure

Procedure ShowIR_Do(Passive.i)
  Define.i xLong1
  
  If xStaticIconsHWnd(#xStaticIcons_ShowIR)
    If ShowIRWin
      If Not Passive
        ShowIRTicks = GetTickTimeMS()
        EndIf
      xLong1 = GetDC_(xStaticIconsHWnd(#xStaticIcons_ShowIR))
      If Not xLong1 = 0
        SendMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $14, xLong1, 0)
        SendMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $F, xLong1, 0)
        ReleaseDC_(xStaticIconsHWnd(#xStaticIcons_ShowIR), xLong1)
        EndIf
      ElseIf Not Passive
      ProcClassWnd(1, $113, 0, 0)  ; WM_Timer
      
      ShowIRTicks = GetTickTimeMS()
      ShowWindow_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $4)
      SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_ShowIR), -1, 0, 0, 0, 0, $213)
      SetTimer_(xStaticIconsHWnd(#xStaticIcons_ShowIR), 3, 150, @ProcClassWnd())
      ShowIRWin = #True
      EndIf
    EndIf
  EndProcedure

Procedure ForceIRPosUpdate()
  ProcClassWnd(1, $113, 0, 0)
  ShowIR_Do(#True)      ;#False
  EndProcedure

Procedure UpdateSearchVals(FullApply.i)
  Define.i xLong1
  Define.i xLong2
  ShowWindow_(Interface_Control(#Interface_Control_Search_Play), 0)
  If xSearchAutoPlay
    xLong1 = 1
    EndIf
  SetWindowLong_(Interface_Control(#Interface_Control_Search_Play), -16, (GetWindowLong_(Interface_Control(#Interface_Control_Search_Play), -16) & $FFFFFFFE) | xLong1)
  ShowWindow_(Interface_Control(#Interface_Control_Search_Play), 1)

  ShowWindow_(Interface_Control(#Interface_Control_Search_Select), 0)
  xLong1 = 1 - xLong1
  SetWindowLong_(Interface_Control(#Interface_Control_Search_Select), -16, (GetWindowLong_(Interface_Control(#Interface_Control_Search_Select), -16) & $FFFFFFFE) | xLong1)
  ShowWindow_(Interface_Control(#Interface_Control_Search_Select), 1)
  
  
  If FullApply
    xLong1 = 1 - xLong1
    SendMessage_(Interface_Control(#Interface_Control_Search_Check1), $F1, xLong1, 0)
    If xSearchAutoClose
      xLong1 = 1
      Else
      xLong1 = 0
      EndIf
    SendMessage_(Interface_Control(#Interface_Control_Search_Check2), $F1, xLong1, 0)
    SearchForm_CheckBoxTxtChange()
    EndIf
  EndProcedure

Procedure SpektrumToggleEvent()
  If Not (PlayerIsLocked Or xAutoDoing)  ; Or vKioskMode)
    If xShowSpectrum
      xShowSpectrum = #False
      MainForm_DesireSpectrumState(#False, #True)
      Else
      xShowSpectrum = #True
      MainForm_DesireSpectrumState(#True, #True)
      EndIf
    If LEDMode = 0
      If xShowSpectrum
        ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Spectrum), 5)
        Else
        ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Spectrum), 0)
        EndIf
      EndIf
    CheckApiMenu(302, xShowSpectrum)
    SetPanelSize()
    EndIf
  EndProcedure

Procedure MainForm_ReGetWidth()
  Define.i xLong1
  Define.i xDC1
  Define.i xDC2
  Define.i xDCD
  Define.i xDCB
  Define.i xFntD
  Define.i xFntB
  Define.i xFntS
  
  xDC1 = CreateCompatibleDC_(0)
  If xDC1 = 0
    xDCD = xSharedDC
    xDCB = xSharedDC
    Else
    xDCD = xDC1
    xFntD = SelectObject_(xDC1, hFontPLLg)
    xDC2 = CreateCompatibleDC_(0)
    If xDC2 = 0
      xDCB = xDC1
      Else
      xDCB = xDC2
      xFntB = SelectObject_(xDC2, hFontPLLgB)
      EndIf
    EndIf
  
  xFntS = SelectObject_(xSharedDC, hFontPLSm)
  
  If ShowFullPath
    For xLong1 = 0 To PLCount - 1
      CompilerIf #BoldDirs = 98
        If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
          PLI(xLong1)\pxWidthLg = GetTextOutWidth(xDCB, PLI(xLong1)\Caption)
          PLI(xLong1)\pxWidthSm = GetTextOutWidth(xSharedDC, PLI(xLong1)\Filename)
          Else
          PLI(xLong1)\pxWidthLg = GetTextOutWidth(xDCD, PLI(xLong1)\Caption)
          EndIf
        CompilerElse
        If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
          PLIPxLg(xLong1) = GetTextOutWidth(xDCB, PLICap(xLong1))
          PLIPxSm(xLong1) = GetTextOutWidth(xSharedDC, PLIFile(xLong1))
          Else
          PLIPxLg(xLong1) = GetTextOutWidth(xDCD, PLICap(xLong1))
          EndIf
        CompilerEndIf
      Next
    Else
    For xLong1 = 0 To PLCount - 1
      CompilerIf #BoldDirs = 98
        If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
          PLI(xLong1)\pxWidthLg = GetTextOutWidth(xDCB, PLI(xLong1)\Caption)
          PLI(xLong1)\pxWidthSm = GetTextOutWidth(xSharedDC, PLI(xLong1)\Caption) + (PLI(xLong1)\DirDepthFlags & #PLI_Depth) * 20
          Else
          PLI(xLong1)\pxWidthLg = GetTextOutWidth(xDCD, PLI(xLong1)\Caption)
          EndIf
        CompilerElse
        If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
          PLIPxLg(xLong1) = GetTextOutWidth(xDCB, PLICap(xLong1))
          PLIPxSm(xLong1) = GetTextOutWidth(xSharedDC, PLICap(xLong1)) + (PLIDF(xLong1) & #PLI_Depth) * 20
          Else
          PLIPxLg(xLong1) = GetTextOutWidth(xDCD, PLICap(xLong1))
          EndIf
        CompilerEndIf
      Next
    EndIf
  
  SelectObject_(xSharedDC, xFntS)
  If Not xDC1 = 0
    SelectObject_(xDC1, xFntD)
    DeleteDC_(xDC1)
    If Not xDC2 = 0
      SelectObject_(xDC2, xFntB)
      DeleteDC_(xDC2)
      EndIf
    EndIf
  EndProcedure

Procedure SearchForm_UpdateFont(HWndFont.i, UpdateFlag.i)
  Define.i xLong1

  For xLong1 = 0 To #Interface_Control_Search_LastFontApply
    SendMessage_(Interface_Control(xLong1), $30, HWndFont, UpdateFlag)
    Next
  ;$D3
  ;If Not Interface_Control(#Interface_Control_Search_Txt) = 0
  ;  SendMessage_(Interface_Control(#Interface_Control_Search_Txt), $D3, 3, $20002 + ScrollComboWidth * $10000)
  ;  endif
  ;SendMessage_(HWndButton(#Interface_Control_Search_Results), $30, HWndFont, 0)
  EndProcedure

Procedure SetAccel(Index.i, ResID.i)
  Define.s xChar1
  
  xChar1 = ReplaceString(LoadResString(ResID), "&&", "")
  ResID = FindString(xChar1, "&")
  If ResID = Len(xChar1)
    ResID = 0
    ElseIf Not ResID = 0
    ResID = Asc(UCase(Mid(xChar1, ResID + 1, 1)))
    EndIf
  Interface_Control_Accel(Index) = ResID
  EndProcedure

Procedure.i MainForm_TrySearchNow()
  Define.i xResult
  Define.i xLong1
  Define.i xLong2

  If Not (PlayerIsLocked Or xAutoDoing Or xSearchCount = 0 Or xSearchCount = #xSearchCountOver Or CPListMustDo)
    If Not SendMessage_(Interface_Control(#Interface_Control_Search_Results), $190, 0, 0) = 0
      xLong2 = -1
      SendMessage_(xListHWnd(2), #LB_SETSEL, 0, -1)
      For xLong1 = 0 To xSearchCount - 1
        If SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETSEL, xLong1, 0) > 0
          SendMessage_(xListHWnd(2), #LB_SETSEL, 1, xSearch(xLong1))
;          debug "Select:", xLong1, xSearch(xLong1)
          If xLong2 = -1
            xLong2 = xLong1
            EndIf
          EndIf
        Next
;      Exit Function
      xLong1 = SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETCARETINDEX, 0, 0)
      If xLong2 = -1
        xLong2 = xLong1
        EndIf
      If xLong1 = -1
        If Not xLong2 = -1
          SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xSearch(xLong2), 1)
          MainForm_CheckDir(#False)
          EndIf
        Else
        If SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETSEL, xLong1, 0) > 0
          SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xSearch(xLong1), 1)
          ElseIf Not xLong2 = -1
          SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xSearch(xLong2), 1)
          SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xSearch(xLong1), 0)
          EndIf
        MainForm_CheckDir(#False)
        EndIf
      xResult = #True
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.i MainForm_TrySearchNowEx()
  Define.i xResult
  Define.i xLong1

  If Not (PlayerIsLocked Or xAutoDoing Or xSearchCount = 0 Or xSearchCount = #xSearchCountOver Or CPListMustDo)
    If SendMessage_(Interface_Control(#Interface_Control_Search_Results), $190, 0, 0) = 1
      xLong1 = SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETCARETINDEX, 0, 0)
      If Not xLong1 = -1
        If SendMessage_(Interface_Control(#Interface_Control_Search_Results), #LB_GETSEL, xLong1, 0) > 0
          xMarkSong(xSearch(xLong1), #False, #False)
          xResult = #True
          EndIf
        EndIf
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure SearchForm_TrySCommand(hWnd.i, wParam.i)
  Define.s xChar1
  
  If IsWindowEnabled_(hWnd)
    Select hWnd
      Case Interface_Control(#Interface_Control_Search_Play)
        If MainForm_TrySearchNowEx()
          If xSearchAutoClose
            ToggleInterface(#Interface_Mode_None)
            EndIf
          ;If hwnd = Interface_Control(#Interface_Control_Search_play)
            MainForm_PlayListDoubleClickEvent()
          ;  endif
          EndIf
      Case Interface_Control(#Interface_Control_Search_Select)
        If MainForm_TrySearchNow()
          If xSearchAutoClose
            ToggleInterface(#Interface_Mode_None)
            EndIf
          EndIf
      Case Interface_Control(#Interface_Control_Search_Check1)
        If SendMessage_(hWnd, $F0, 0, 0)
          xSearchAutoPlay = #True
          Else
          xSearchAutoPlay = #False
          EndIf
        UpdateSearchVals(#False)
      Case Interface_Control(#Interface_Control_Search_Check2)
        If SendMessage_(hWnd, $F0, 0, 0)
          xSearchAutoClose = #True
          Else
          xSearchAutoClose = #False
          EndIf
      Case Interface_Control(#Interface_Control_Search_Return)
        ToggleInterface(#Interface_Mode_None)
        ;SearchForm_TrySCommand = #True
      Case Interface_Control(#Interface_Control_Search_Txt)
        If (wParam & $FFFF0000) = $3000000
          xChar1 = GetWindowText(hWnd)
          If Not CPListText = xChar1
            CPListText = xChar1
            InitCPList()
            EndIf
          EndIf
      EndSelect
    EndIf
  EndProcedure

Procedure SearchForm_TryAccel(wParam.i)
  Define.i xLong1
  
  ;If wParam = 40 Or wParam = 38
  If wParam = 93
    If MainForm_TrySearchNow()
      MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(8), Interface_Control(#Interface_Control_Search_Results)))
      EndIf
    Else
    For xLong1 = 0 To #Interface_Control_Search_LastAccel
      If Interface_Control_Accel(xLong1) = wParam
        SetFocus_(Interface_Control(#Interface_Control_Search_Txt))
        If Not xLong1 = #Interface_Control_Search_Txt
          CheckboxAccelerate(Interface_Control(xLong1))
          SearchForm_TrySCommand(Interface_Control(xLong1), 0)
          EndIf
        Break
        EndIf
      Next
    EndIf
  EndProcedure

Procedure.i SearchForm_ButtonProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Define.i xLong1
  
  If Message = $100
    If wParam = 9
      LoadResEx_Window_ManualTab(MainHWnd, hWnd)
      ProcedureReturn 0
      ElseIf wParam = 27
      ToggleInterface(#Interface_Mode_None)
      ProcedureReturn 0
      EndIf
    ElseIf Message = $105 ;And (lParam & $40000000) = 0
    SearchForm_TryAccel(wParam)
    EndIf
  For xLong1 = 0 To #Interface_Control_Search_LastHook
    If Interface_Control(xLong1) = hWnd
      ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
      EndIf
    Next
;lblSkipDef:
  ProcedureReturn 0
  EndProcedure

Procedure.i SearchForm_TextProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Select Message
    Case $100
      ;down
      Select wParam
        Case 9
          LoadResEx_Window_ManualTab(MainHWnd, hWnd)
          ProcedureReturn 0
        Case 27
          ToggleInterface(#Interface_Mode_None)
          ProcedureReturn 0
        ;33=pgup, 34=pgdown, 36=home, 35=end
        Case 13
          If CPListMustDo
            MainForm_TrySearch(#False)
            Else
            If xSearchAutoPlay
              hWnd = #Interface_Control_Search_Play
              Else
              hWnd = #Interface_Control_Search_Select
              EndIf
            SearchForm_TrySCommand(Interface_Control(hWnd), 0)
            EndIf
          ProcedureReturn 0
        Case 33, 34, 38, 40 ;33=pgup
          If Not (xSearchCount = 0 Or xSearchCount = #xSearchCountOver Or CPListMustDo)
            SendMessage_(Interface_Control(#Interface_Control_Search_Results), $100, wParam, lParam)
            EndIf
          ProcedureReturn 0
;        Case 93
;          ;SearchForm_TextProc = 1
;          exit function
        EndSelect
;    Case $102
;      ;press
;      Select wParam
;        Case 9, 13 ;, 93
;          ;SearchForm_TextProc = 1
;          ;exit function
;        EndSelect
    Case $101
      ;up
      Select wParam
        Case 9, 13
          ProcedureReturn 0
        EndSelect
    Case $105
      SearchForm_TryAccel(wParam)
    EndSelect
  ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure.i FloodSelected(FilesOnly.i)
  Define.i xResult
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.s xChar1
  ;define.s xChar2
  Define.s xChar4
  
  Select SendMessage_(xListHWnd(2), $190, 0, 0)
    Case 0
    Case 1
      xResult = SendMessage_(xListHWnd(2), $19D, 0, 0)  ;anchor not caret
      If xResult < 0
        xResult = 0
        Else
        CompilerIf #BoldDirs = 98
          xChar1 = PLI(xResult)\Filename
          CompilerElse
          xChar1 = PLIFile(xResult)
          CompilerEndIf
        If Mid(xChar1, 2, 1) = ":" Or Left(xChar1, 2) = "\\"
          sCharA1(0) = xChar1
          xResult = 1
          Else
          xResult = 0
          EndIf
        EndIf
    Default
      If FilesOnly
        For xLong1 = 0 To PLCount - 1
          If SendMessage_(xListHWnd(2), #LB_GETSEL, xLong1, 0)
CompilerIf #BoldDirs = 98
            If ((PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = 0 And (Mid(PLI(xLong1)\Filename, 2, 1) = ":") Or Left(PLI(xLong1)\Filename, 2) = "\\")
CompilerElse
            If ((PLIDF(xLong1) & #PLI_IsDir) = 0 And (Mid(PLIFile(xLong1), 2, 1) = ":") Or Left(PLIFile(xLong1), 2) = "\\")
CompilerEndIf
              ;xChar1 = Mid(PLItem(xLong1), 3)
              ;xLong2 = FloodSelected * 2
              ;sCharA1(xLong2 + 1) = xChar1
CompilerIf #BoldDirs = 98
              sCharA1(xResult) = PLI(xLong1)\Filename
CompilerElse
              sCharA1(xResult) = PLIFile(xLong1)
CompilerEndIf
              xResult = xResult + 1
              EndIf
            EndIf
          Next
        Else
        For xLong1 = 0 To PLCount - 1
          If SendMessage_(xListHWnd(2), #LB_GETSEL, xLong1, 0)
            CompilerIf #BoldDirs = 98
              xChar1 = PLI(xLong1)\Filename
              xLong2 = (PLI(xLong1)\DirDepthFlags & #PLI_IsDir)
              CompilerElse
              xChar1 = PLIFile(xLong1)
              xLong2 = (PLIDF(xLong1) & #PLI_IsDir)
              CompilerEndIf
            ;xChar2 = UCase(xChar1)
            If Mid(xChar1, 2, 1) = ":" Or Left(xChar1, 2) = "\\"
              ; isasong or isadirectory
              xLong3 = InstrRevChar(xChar1, 92) ; "\"
              If xLong3 = 0
                xChar4 = ""
                Else
                xChar4 = Left(xChar1, xLong3 - 1)
                EndIf
              xLong3 = InstrRevChar(xChar1, 92) ; "\"
              If xLong3 = 0
                xChar1 = ""
                Else
                xChar4 = xChar1 + "\"
                If xLong2
                  xLong3 = Len(xChar4)
                  For xLong2 = xResult - 1 To 0 Step -1
                    ;xLong4 = xLong2 * 2
                    If sCharA1(xLong2) = xChar1 Or Left(sCharA1(xLong2), xLong3) = xChar4 Or sCharA1(xLong2) + "\" = Left(xChar4, Len(sCharA1(xLong2)) + 1)
                      If sCharA1(xLong2) = xChar1 Or sCharA1(xLong2) + "\" = Left(xChar4, Len(sCharA1(xLong2)) + 1)
                        xChar1 = ""
                        Break
                        Else
                        For xLong4 = xLong2 To xResult - 2
                          sCharA1(xLong4) = sCharA1(xLong4 + 1)
                          Next
                        xResult = xResult - 1
                        EndIf
                      EndIf
                    Next
                  Else
                  For xLong2 = 0 To xResult - 1
                    If sCharA1(xLong2) = xChar1 Or sCharA1(xLong2) + "\" = Left(xChar4, Len(sCharA1(xLong2)) + 1)
                      xChar1 = ""
                      Break
                      EndIf
                    Next
                  EndIf
                EndIf
              If Not xChar1 = ""
                sCharA1(xResult) = xChar1
                xResult = xResult + 1
                EndIf
              EndIf
            EndIf
          Next
        EndIf
    EndSelect
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_OLEStartDrag()
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  Define.s xChar2
  Define hBuff
  CompilerIf #DragExtText
    Define.i xOLEShowDragShift
    Define.i xOLEShowDragAlt

    Structure DragDataFormat
      Format.l    ; The OS specific ID for the format to drag (see below for more information)
      *Buffer      ; The memory buffer containing the data in this format
      Size.l      ; The size of the data in the buffer
      EndStructure
  
    Dim DF.DragDataFormat(0)

    If ((GetAsyncKeyState_($10) & #AsyncKeyPressedMask) And LEDMode = 0)
      xOLEShowDragShift = #True
      EndIf
    If ((GetAsyncKeyState_($12) & #AsyncKeyPressedMask) And LEDMode = 0)
      xOLEShowDragAlt = #True
      EndIf
    CompilerEndIf
  

  
  If DragOut And Not (PlayerIsLocked Or xAutoDoing)
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Preparing OLE Dragging")
      CompilerEndIf
;Debug "DF: Can"
;xOLEShowDragShift = 0
    
    If (GetAsyncKeyState_($11) & #AsyncKeyPressedMask) And Not LEDMode
      xLong1 = #True
      EndIf
    xLong2 = FloodSelected(xLong1)
    If xLong2
      hBuff = BinaryBuffer_Create()
      If hBuff
        SetAutoDoing(#True)
        If Not vKioskMode
          ;RevokeDragDrop(MainHWnd)
          DragAcceptFiles_(MainHWnd, #False)
          EndIf
        xLong2 - 1
CompilerIf #DragExtText
        If xOLEShowDragShift
Debug "DF: Shift0"
          xChar2 = #CRLF$
          If xOLEShowDragAlt
Debug "DF: Shift1"
            CompilerIf #PB_Compiler_Unicode
              BinaryBuffer_WriteMemEx(hBuff, @sCharA1(0), Len(sCharA1(0)) << 1)
              CompilerElse
              BinaryBuffer_WriteMemEx(hBuff, @sCharA1(0), Len(sCharA1(0)))
              CompilerEndIf
            For xLong1 = 1 To xLong2
              CompilerIf #PB_Compiler_Unicode
                BinaryBuffer_WriteMemEx(hBuff, @xChar2, 4)
                BinaryBuffer_WriteMemEx(hBuff, @sCharA1(xLong1), Len(sCharA1(xLong1)) << 1)
                CompilerElse
                BinaryBuffer_WriteMemEx(hBuff, @xChar2, 2)
                BinaryBuffer_WriteMemEx(hBuff, @sCharA1(xLong1), Len(sCharA1(xLong1)))
                CompilerEndIf
              Next
            Else
Debug "DF: Shift2"
            xChar1 = SimpleFile(sCharA1(0))
            CompilerIf #PB_Compiler_Unicode
              BinaryBuffer_WriteMemEx(hBuff, @xChar1, Len(xChar1) << 1)
              CompilerElse
              BinaryBuffer_WriteMemEx(hBuff, @xChar1, Len(xChar1))
              CompilerEndIf
            For xLong1 = 1 To xLong2
              xChar1 = #CRLF$ + SimpleFile(sCharA1(xLong1))
              CompilerIf #PB_Compiler_Unicode
                BinaryBuffer_WriteMemEx(hBuff, @xChar1, Len(xChar1) << 1)
                CompilerElse
                BinaryBuffer_WriteMemEx(hBuff, @xChar1, Len(xChar1))
                CompilerEndIf
              Next
            EndIf
Debug "DF: Shift3"
          xLong1 = 0
          CompilerIf #PB_Compiler_Unicode
            BinaryBuffer_WriteMemEx(hBuff, @xLong1, 2)
            CompilerElse
            BinaryBuffer_WriteMemEx(hBuff, @xLong1, 1)
            CompilerEndIf
Debug "DF: Shift4"
          DF(0)\Size = BinaryBuffer_GetMemSize(hBuff)
          If DF(0)\Size
            DF(0)\Buffer = BinaryBuffer_GetMemPtr(hBuff)
            If DF(0)\Buffer
              CompilerIf #PB_Compiler_Unicode
                DF(0)\Format = 13
                CompilerElse
                DF(0)\Format = 0
                CompilerEndIf
              DragOSFormats(DF(), 1, #PB_Drag_Copy)
              EndIf
            EndIf
          Else
CompilerEndIf
          xChar2 = #LF$
          CompilerIf #PB_Compiler_Unicode
            BinaryBuffer_WriteMemEx(hBuff, @sCharA1(0), Len(sCharA1(0)) << 1)
            CompilerElse
            BinaryBuffer_WriteMemEx(hBuff, @sCharA1(0), Len(sCharA1(0)))
            CompilerEndIf
          For xLong1 = 1 To xLong2
            CompilerIf #PB_Compiler_Unicode
              BinaryBuffer_WriteMemEx(hBuff, @xChar2, 2)
              BinaryBuffer_WriteMemEx(hBuff, @sCharA1(xLong1), Len(sCharA1(xLong1)) << 1)
              CompilerElse
              BinaryBuffer_WriteMemEx(hBuff, @xChar2, 1)
              BinaryBuffer_WriteMemEx(hBuff, @sCharA1(xLong1), Len(sCharA1(xLong1)))
              CompilerEndIf
            Next
          xLong1 = BinaryBuffer_GetMemPtr(hBuff)
          xLong2 = BinaryBuffer_GetMemSize(hBuff)
          If xLong1 And xLong2
            CompilerIf #PB_Compiler_Unicode
              DragFiles(PeekS(xLong1, xLong2 >> 1))
              CompilerElse
              DragFiles(xChar1)
              CompilerEndIf
            EndIf
CompilerIf #DragExtText
          EndIf
CompilerEndIf
        BinaryBuffer_Discard(hBuff)
        ;xOLEisDragging(#True)
        SetAutoDoing(#False)
        ;RegisterDragDrop(MainHWnd, ObjPtr(DragClass))
        If Not vKioskMode
          DragAcceptFiles_(MainHWnd, #True)
          EndIf
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure.i SearchForm_ResultListProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Define.i xResult
  Define.i xLong1
  
  Select Message
    Case $200 ;move
      If SearchFormDraggingIs And Not (lParam = SearchFormDraggingLParam)
        If MainForm_TrySearchNow()
          ;DoDragFiles()
          MainForm_OleStartDrag()
          ;Load OLEHelperForm
          ;OLEHelperForm.OLEDrag
          ;Unload OLEHelperForm
          ;App.TaskVisible = #False
          EndIf
        EndIf
      SearchFormDraggingIs = #False
    Case $201, $204 ;down
      If DragOut
        If DragDetectWinLikeSL(lParam)
          SearchFormDraggingIs = #True
          SearchFormDraggingWParam = wParam
          SearchFormDraggingLParam = lParam
          SearchFormDraggingWMsgPlus = Message
          ProcedureReturn 0;xResult
          EndIf
        EndIf
    Case $202, $205 ;up
      If SearchFormDraggingIs
        HookedWindowProc(hWnd, SearchFormDraggingWMsgPlus, SearchFormDraggingWParam, SearchFormDraggingLParam)
        SearchFormDraggingIs = #False
        EndIf
      If Message = $205
        xResult = HookedWindowProc(hWnd, Message, wParam, lParam)
        If Not (PlayerIsLocked Or xAutoDoing Or xSearchCount = 0 Or xSearchCount = #xSearchCountOver Or CPListMustDo)
          xLong1 = TrackListBox(xStaticIconsHWnd(#xStaticIcons_ShowIR), Interface_Control(#Interface_Control_Search_Results), SignedHigherWord(lParam), #False, 0, 1)  ;#True
          If Not xLong1 = -1
            If MainForm_TrySearchNow()
              MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(8), 0))
              EndIf
            EndIf
          EndIf
        ProcedureReturn xResult
        EndIf
    Case $100
      xResult = HookedWindowProc(hWnd, Message, wParam, lParam)
      Select wParam
        Case 9
          LoadResEx_Window_ManualTab(MainHWnd, hWnd)
        Case 13
          If xSearchAutoPlay
            hWnd = #Interface_Control_Search_Play
            Else
            hWnd = #Interface_Control_Search_Select
            EndIf
          SearchForm_TrySCommand(Interface_Control(hWnd), 0)
        Case 27
          ToggleInterface(#Interface_Mode_None)
        Case 93 ;menukey
          If Not (PlayerIsLocked Or xAutoDoing Or xSearchCount = 0 Or xSearchCount = #xSearchCountOver Or CPListMustDo)
            If MainForm_TrySearchNow()
              MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(8), Interface_Control(#Interface_Control_Search_Results)))
              EndIf
            EndIf
        EndSelect
      ProcedureReturn xResult
    Case $105
;debug "F5"
      ;If (lParam & $40000000) = 0
        SearchForm_TryAccel(wParam)
      ;  endif
    Case $203 ; WM_LBUTTONDBLCLK
      xResult = HookedWindowProc(hWnd, Message, wParam, lParam)
      If xSearchAutoPlay
        hWnd = #Interface_Control_Search_Play
        Else
        hWnd = #Interface_Control_Search_Select
        EndIf
      SearchForm_TrySCommand(Interface_Control(hWnd), 0)
      ProcedureReturn xResult
CompilerIf #ListFocusedLists
    Case 7
      xCurFocusHWnd = hWnd
    Case 8
      xCurFocusHWnd = wParam
CompilerEndIf
    EndSelect
    ;default
  ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure SearchForm_Interface()
  Define.i xLong1

  SearchFormDraggingIs = #False
  
  Interface_Icon = LoadResEx_Image_MultiOS(#PLIconSearch_ResID, 1, 32)
  If Not Interface_Icon = 0
    Interface_Control(#Interface_Control_Search_Image) = CreateWindowExOC(0, #W_STATIC, "", $56000003, 0, 4, 32, 32, MainHWnd, 0, 0)
    If Interface_Control(#Interface_Control_Search_Image) = 0
      DestroyIcon_(Interface_Icon)
      Interface_Icon = 0
      Else
      SendMessage_(Interface_Control(#Interface_Control_Search_Image), $170, Interface_Icon, 0)
      EndIf
    EndIf
  
  Interface_Control(#Interface_Control_Search_CapLabel) = CreateWindowExOC(0, #W_STATIC, LoadResString(2300), $56000000, 4, 3, 417, 17, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Search_Txt) = CreateWindowExOC($200, #W_EDIT, "", $56010090, 6, 17, 400, 14, MainHWnd, 0, 0)
  SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Anim), 0, 0, 0, 0, 0, $213)

  Interface_Control(#Interface_Control_Search_Results) = CreateWindowExOC($200, #W_LISTBOX, "", $56300918, 0, 48, 425, 160, MainHWnd, 0, 0)

  Interface_Control(#Interface_Control_Search_Check1) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2301), $56010003, 8, 232, 121, 17, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Search_Check2) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2302), $56010003, 8, 232, 121, 17, MainHWnd, 0, 0)
  If xSearchAutoPlay
    xLong1 = 1
    EndIf
  Interface_Control(#Interface_Control_Search_Play) = CreateWindowExOC(0, #W_BUTTON, "", $56010000 | xLong1, 8, 208, 129, 25, MainHWnd, 0, 0)
  xLong1 = 1 - xLong1
  Interface_Control(#Interface_Control_Search_Select) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2304), $56010000 | xLong1, 8, 208, 129, 25, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Search_Return) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2305), $56010000, 8, 208, 129, 25, MainHWnd, 0, 0)
  
  SetAccel(#Interface_Control_Search_Txt, 2300)
  For xLong1 = 0 To #Interface_Control_Search_Return
    If Not xLong1 = #Interface_Control_Search_Play
      SetAccel(xLong1, 2301 + xLong1)
      EndIf
    HookWindow(Interface_Control(xLong1), @SearchForm_ButtonProc())
    Next
  
  SearchForm_UpdateFont(hFontGFix, 1)
  SendMessage_(Interface_Control(#Interface_Control_Search_Results), $30, hFontPLLgB, 0)

  HookWindow(Interface_Control(#Interface_Control_Search_Txt), @SearchForm_TextProc())
  HookWindow(Interface_Control(#Interface_Control_Search_Results), @SearchForm_ResultListProc())

  SearchForm_CheckBoxTxtChange()
  UpdateSearchVals(#True)
  
  ;eButton(3).Enabled = Not (xSearchOldQueriesCount = 0)
  If Len(CPListText) = 0
    MainForm_TrySearch(#False)
    Else
    SendMessage_(Interface_Control(#Interface_Control_Search_Txt), $C, 0, @CPListText)
    SendMessage_(Interface_Control(#Interface_Control_Search_Txt), $B1, 0, -1)
    CPListMustDo = #False
    InitCPList()
    EndIf
  
  SendMessage_(Interface_Control(#Interface_Control_Search_Results), $1A0, 0, PLODHeight)
  If Not Interface_Control(#Interface_Control_Search_Txt) = 0
    SetFocus_(Interface_Control(#Interface_Control_Search_Txt))
    EndIf
  EndProcedure

CompilerIf #PresetBinded
  Procedure MainForm_LoadSettings(Filename.s)
    Define.s xChar1
    Define.s xChar2
    Define.i xLong1
    Define.i xLong2
    Define.i xBool3
    Define.i xHasPrioValue
    Define.i xHasTray
    Define.i xHasTagFont
    Define.i xHasSpec
    Define.i xHasFullPath
    Define.i xHasTrayMini
    Define.i xHasFullTitle
    Define.i xHasKeys
    Define.i xBoolIRFont
    Define.i hFile
    
    hFile = TxtFileReader_FromFile(Filename)
    If Not hFile = 0
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Loading & performing preset (" + Filename + ")")
        CompilerEndIf
      If GlobalKeys
        MainForm_SetGlobalKeys(#False)
        EndIf
      
      While TxtFileReader_NextLine(hFile)
        xChar1 = TxtFileReader_GetLineString(hFile)
        xLong2 = FindString(xChar1 + "=", "=")
        xChar2 = Mid(xChar1, xLong2 + 1)
        xLong1 = Val(xChar2)
        If xLong1 > 0
          xBool3 = #True
          Else
          xBool3 = #False
          EndIf
        If UCase(Left(xChar1, 3)) = "KEY"
          ApplySpecKeyByStrAndMaybeReset(UCase(Mid(xChar1, 4)), UCase(xChar2))
          xHasKeys = #True
          Else
          Select UCase(Left(xChar1, xLong2 - 1))
            Case "ALLOWFILEDELETING"
              If Not xSecureMode
                If (xLong1 = 1)
                  xDelMode = #True
                  Else
                  xDelMode = #False
                  EndIf
                MainForm_EnableApiMenu(133, xDelMode)
                MainForm_EnableApiMenu(230, xDelMode)
                EndIf
            Case "AUTOPLAY"
              xAutoPlayback = xBool3
            Case "AUTOSWITCHIRADIOVIEW"
              xAutoSwitchIRadioOEPl = xBool3
            Case "BLOCKIDEWHILELOADING"
              xClassicBlockingOnLoad = xBool3
            Case "CHECKACCURATESTREAMS"
              CheckAccurate = xBool3
            Case "CHECKSONGSONPLAYLISTLOAD"
              RemoveMissingOnPLLoad = xBool3
            Case "CROSSFADETIME"
              xLong1 = xLong1 - #xFadeConsts1
              If xLong1 < 0
                xCrossFadeTimeM = 0
                ElseIf xLong1 > #xFadeConstsX
                xCrossFadeTimeM = #xFadeConstsX
                Else
                xCrossFadeTimeM = xLong1
                EndIf
            Case "DIRECTORYLISTALIGNMENT"
              If xLong1 < 4 And Not xLong1 < 0
                SetAutoDirVar(xLong1)
                EndIf
            Case "DIRECTORYLISTTOPHEIGHT"
              If xLong1 > 0 And Not xLong1 > #xDirListMaxTH
                If Not xLong1 = xDirListTopHeight
                  xDirListTopHeight = xLong1
                  MainForm_ResizePlayer(#False)
                  EndIf
                EndIf
            Case "DIRECTORYLISTLEFTWIDTH"
              If Not (xLong1 < #xDirListMinLW Or xLong1 > #xDirListMaxLW)
                If Not xLong1 = xDirListLeftWidth
                  xDirListLeftWidth = xLong1
                  MainForm_ResizePlayer(#False)
                  EndIf
                EndIf
            Case "DISABLEWINDOWSSOUNDS"
              If xLong1 < 3 And Not xLong1 < 0
                SoundSchemePointerMode = xLong1
                MainForm_ApplyProcessMode()
                EndIf
            Case "ELAPSEDTIME"
              xShowElapsed = xBool3
            Case "ENDSONGMODE"
              If xLong1 < 4 And Not xLong1 < 0
                xProcessMode = xLong1
                MainForm_ApplyProcessMode()
                EndIf
            Case "ENDSTREAMS"
              GetValidSkipper(#ctSSLayer_MusicTypeStream, xLong1)
            Case "ENDTRACKERS"
              GetValidSkipper(#ctSSLayer_MusicTypeTracker, xLong1)
            Case "ENDCDAUDIO"
              GetValidSkipper(#ctSSLayer_MusicTypeCDAudio, xLong1)
            Case "FADING"
              xGenFading = xBool3
              ;mOMenu(0).Checked = xGenFading
              CheckApiMenu(301, xGenFading)
            CompilerIf #UseFileLogging
              Case "CDDA", "CDDAJITTERCORRECTION", "OUTPUTDEVICE", "FAILSAVE", "NOVERWARN", "PLAYERWINDOWSTATE", "PLAYERWINDOWPOS"
                MainForm_ctConsoleA_AddLog("Tag not supported in presets (tag ignored): " + Left(xChar1, xLong2 - 1))
              CompilerEndIf
            Case "FOLLOWSONG"
              xFollowCurSong = xBool3
              CheckApiMenu(310, xFollowCurSong)
            Case "GETFILEFORMAT", "GETMP3FORMAT"
              If MP3GetFormat XOr xBool3
                MP3GetFormat = xBool3
                SetFormatToolTip(LoadResString(1900), "")
                MP3GetFormatChanged(#True)
                MainForm_ReadLate("", #False)
                EndIf
            Case "GETFILEINFOS"
              If MP3GetID3Tag XOr xBool3
                MP3GetID3Tag = xBool3
                ;If MP3GetID3Tag
                  ;ReadLate ""
                  ;EndIf
                If MP3GetID3Tag
                  MainForm_ReadLate("", #False)
                  ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Tags), 5)
                  Else
                  ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Tags), 0)
                  EndIf
                EndIf
              CheckApiMenu(303, MP3GetID3Tag)
            Case "GLOBALPLAYKEYS"
              GlobalKeys = xBool3
            Case "IGNOREUNDERSCORED"
              IgnoreUnderscored = xBool3
            Case "INTROMODE"
              If xLong1 < 0
                IntroModeActive = #False
                xLong1 = -xLong1
                Else
                IntroModeActive = #True
                EndIf
              If xLong1 < #IntroMdSkipperMinVal
                IntroModeTime = #IntroMdSkipperMinVal
                ElseIf xLong1 > #IntroMdSkipperMaxVal
                IntroModeTime = #IntroMdSkipperMaxVal
                Else
                IntroModeTime = xLong1
                EndIf
            Case "PLAYLISTDOUBLECLICK"
              If xLong1 < 3 And Not xLong1 < 0
                PlDClickAction = xLong1
                If InterfaceMode = #Interface_Mode_Search
                  SearchForm_CheckBoxTxtChange()
                  EndIf
                EndIf
            Case "PLAYLISTUPDATEINTERVAL"
              If xLong1 < 3 And Not xLong1 < 0
                LockWinUpd = xLong1
                EndIf
            Case "PRIORITY"
              If xLong1 < -2
                xHasPrioValue = 8 ; 10 + -2
                ElseIf xLong1 > 3
                xHasPrioValue = 13 ; 10 + 3
                Else
                xHasPrioValue = xLong1 + 10
                EndIf
            Case "RADIOAUTOCLOSE"
              xRadioAutoClose = xBool3
            Case "RANDOMSEEK"
              RandomPosOnTrackerSkipper = xBool3
            Case "REGISTERFOLDERS"
                For xLong2 = 0 To 3
                  If xLong1 & 1
                    RegFolderMode(xLong2) = #True
                    Else
                    RegFolderMode(0) = #False
                    EndIf
                  xLong1 >> 1
                  Next
            Case "REMOVEMISSINGSONGS"
              xRemoveMissingSongs = xBool3
              CheckApiMenu(320, xRemoveMissingSongs)
            Case "REMOVEPLAYEDSONGS"
              xRemovePlayedSongs = xBool3
              CheckApiMenu(322, xRemovePlayedSongs)
            Case "REMOVESKIPPEDSONGS"
              xRemoveSkippedSongs = xBool3
              CheckApiMenu(321, xRemoveSkippedSongs)
            Case "REPEATMODE"
              If xLong1 < 3 And Not xLong1 < 0
                xRep = xLong1
                ;ApplyRepMode
                EndIf
            Case "SEARCHAUTOCLOSE"
              xSearchAutoClose = xBool3
            Case "SEARCHAUTOPLAY"
              xSearchAutoPlay = xBool3
            Case "SHOWFULLPATH"
              xHasFullPath = xBool3
            Case "SHOWFULLTITLE"
              xHasFullTitle = xBool3
            Case "SORTING"
              xSorting = xBool3
            Case "SPECTRUM"
              If xLong1 & 1
                xHasSpec = #True
                Else
                xHasSpec = #False
                EndIf
              If xLong1 & 2
                xDeluxeSpectrum = #True
                Else
                xDeluxeSpectrum = #False
                EndIf
  ;          Case "TAGSFONT"
  ;            xHasTagFont = GrabPLFont(1, xChar2)
            Case "TITLESPOSITION"
              If Not (xLong1 < 0 Or xLong1 > 15)
                xBoolIRFont = xLong1
                EndIf
            Case "TITLESWHENMINIMIZED"
              If Not (xLong1 < 0 Or xLong1 > 2)
                xTitlesWhenMinimized = xLong1
                EndIf
            Case "TRACKERPANSEPERATION"
              If xLong1 < 0
                xModPanning = 0
                ElseIf xLong1 > 100
                xModPanning = 100
                Else
                xModPanning = xLong1
                EndIf
              UpdatePanning(xModPanning)
            Case "TRAYICON"
              If Not xTrayIconVisible = xBool3
                xHasTray = xBool3
                EndIf
            Case "TRAYLEFTCLICK"
              If xLong1 < 7 And Not xLong1 < 0
                xTrayIconLeft = xLong1
                EndIf
            Case "TRAYMINIMIZE", "MINIMIZETOTRAY"
              If Not (xBool3 = xTrayIconEnabled Or xShellMode)
                xHasTrayMini = xBool3
                EndIf
            Case "TRAYRIGHTCLICK"
              If xLong1 < 3 And Not xLong1 < 0
                xTrayIconRight = xLong1
                EndIf
            Case "USEDFILETYPES"
              xUsedTypes = xChar2
            Case "USEPLAYLISTSETTINGS"
              UsePLSettings = xBool3
            Case "VOLUME"
              If xLong1 > 255
                xSetVolume = 255
                ElseIf xLong1 < 0
                xSetVolume = 0
                Else
                xSetVolume = xLong1
                EndIf
              DoVolume(xSetVolume, #True)
            CompilerIf #UseFileLogging
              Default
                MainForm_ctConsoleA_AddLog("Unknown tag: ;" + Left(xChar1, xLong2 - 1) + "; (tag ignored)")
              CompilerEndIf
            EndSelect
          EndIf
        Wend
      TxtFileReader_Close(hFile)
      If GlobalKeys
        MainForm_SetGlobalKeys(#False)
        EndIf
CompilerIf #UseFileLogging
      Else
      MainForm_ctConsoleA_AddLog("Error loading configuration / preset (" + Filename + ")")
CompilerEndIf
      EndIf
    
    If xHasKeys
      MainForm_UpdateMenus()
      EndIf
    
    UpdateFolderReg(#True)
    MainForm_ApplyRepMode()

    If Not xTitlesPos = xBoolIRFont
      xTitlesPos = xBoolIRFont
      ReCreateIRFont()
      ForceIRPosUpdate()
      EndIf

    
    If InterfaceMode = #Interface_Mode_Search
      UpdateSearchVals(#True)
      ElseIf InterfaceMode = #Interface_Mode_Radio
      RadioForm_UpdateRadioVals()
      EndIf
    If (xHasTray XOr xTrayIconVisible) Or (xHasTrayMini XOr xTrayIconEnabled)
      MainForm_ShowTray(#False)
      EndIf
    If xHasSpec XOr xShowSpectrum
      If xShowSpectrum
        If LEDMode = 0
          SpektrumToggleEvent()
          EndIf
        Else
        If ctSSLayer_CanUseItem(4) And FindString(CommandX, "/NOSPECTRUM") = 0
          SpektrumToggleEvent()
          EndIf
        EndIf
      EndIf
    
    SetPanelSize()
    If ShowFullPath XOr xHasFullPath
      ShowFullPath = xHasFullPath
      MainForm_ReGetWidth()
      MainForm_xBuildDirs()
      EndIf
    
    If ShowFullTitle XOr xHasFullTitle
      ShowFullTitle = xHasFullTitle
      If ShowIRWin
        ShowIR_Do(#True)
        EndIf
      NeedIRPathElipse = ""
      EndIf
    
    If Not (xHasPrioValue = 0 Or xHasPrioValue = PlayerPriority + 10)
      UpdatePriority(xHasPrioValue - 10)
      EndIf
    
    CheckFileTypes()
    EndProcedure
  
  Procedure.i SavePreset(Filename.s)
    Define.i xResult
    Define.i hFile
    Define.i xLong1

    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Saving preset")
      CompilerEndIf

    hFile = TxtFileWriter_CreateFile(Filename)
    If Not hFile = 0
      TxtFileWriter_WriteLine(hFile, "AllowFileDeleting=" + BoolChar1(xDelMode))
      TxtFileWriter_WriteLine(hFile, "AutoPlay=" + BoolChar1(xAutoPlayback))
      TxtFileWriter_WriteLine(hFile, "AutoSwitchIRadioView=" + BoolChar1(xAutoSwitchIRadioOEPl))
      TxtFileWriter_WriteLine(hFile, "BlockIDEWhileLoading=" + BoolChar1(xClassicBlockingOnLoad))
      TxtFileWriter_WriteLine(hFile, "CheckAccurateStreams=" + BoolChar1(CheckAccurate))
      TxtFileWriter_WriteLine(hFile, "CheckSongsOnPlaylistLoad=" + BoolChar1(RemoveMissingOnPLLoad))
      TxtFileWriter_WriteLine(hFile, "CrossfadeTime=" + Str(xCrossFadeTimeM + #xFadeConsts1))
      TxtFileWriter_WriteLine(hFile, "DirectoryListLeftWidth=" + Str(xDirListLeftWidth))
      TxtFileWriter_WriteLine(hFile, "DirectoryListAlignment=" + Str(xDirListModeSet))
      TxtFileWriter_WriteLine(hFile, "DirectoryListTopHeight=" + Str(xDirListTopHeight))
      TxtFileWriter_WriteLine(hFile, "DisableWindowsSounds=" + Str(SoundSchemePointerMode))
      TxtFileWriter_WriteLine(hFile, "ElapsedTime=" + BoolChar1(xShowElapsed))
      TxtFileWriter_WriteLine(hFile, "EndSongMode=" + Str(xProcessMode))
      TxtFileWriter_WriteLine(hFile, "EndStreams=" + StrS(xTrackerSkipper(#ctSSLayer_MusicTypeStream)))
      TxtFileWriter_WriteLine(hFile, "EndTrackers=" + StrS(xTrackerSkipper(#ctSSLayer_MusicTypeTracker)))
      TxtFileWriter_WriteLine(hFile, "EndCDAudio=" + StrS(xTrackerSkipper(#ctSSLayer_MusicTypeCDAudio)))
      TxtFileWriter_WriteLine(hFile, "Fading=" + BoolChar1(xGenFading))
      TxtFileWriter_WriteLine(hFile, "FollowSong=" + BoolChar1(xFollowCurSong))
      TxtFileWriter_WriteLine(hFile, "GetFileInfos=" + BoolChar1(MP3GetID3Tag))
      TxtFileWriter_WriteLine(hFile, "GetFileFormat=" + BoolChar1(MP3GetFormat))
      TxtFileWriter_WriteLine(hFile, "GlobalPlayKeys=" + BoolChar1(GlobalKeys))
      TxtFileWriter_WriteLine(hFile, "IgnoreUnderscored=" + BoolChar1(IgnoreUnderscored))
      If IntroModeActive
        TxtFileWriter_WriteLine(hFile, "IntroMode=" + Str(IntroModeTime))
        Else
        TxtFileWriter_WriteLine(hFile, "IntroMode=" + StrS(-IntroModeTime))
        EndIf
      WriteKeyboardSetup(hFile)
      TxtFileWriter_WriteLine(hFile, "PlaylistDoubleClick=" + Str(PlDClickAction))
      TxtFileWriter_WriteLine(hFile, "PlaylistUpdateInterval=" + Str(LockWinUpd))
      TxtFileWriter_WriteLine(hFile, "Priority=" + StrS(PlayerPriority))
      TxtFileWriter_WriteLine(hFile, "RadioAutoClose=" + BoolChar1(xRadioAutoClose))
      TxtFileWriter_WriteLine(hFile, "RandomSeek=" + BoolChar1(RandomPosOnTrackerSkipper))
      TxtFileWriter_WriteLine(hFile, "RemoveMissingSongs=" + BoolChar1(xRemoveMissingSongs))
      TxtFileWriter_WriteLine(hFile, "RemovePlayedSongs=" + BoolChar1(xRemovePlayedSongs))
      TxtFileWriter_WriteLine(hFile, "RemoveSkippedSongs=" + BoolChar1(xRemoveSkippedSongs))
      TxtFileWriter_WriteLine(hFile, "RepeatMode=" + Str(xRep))
      TxtFileWriter_WriteLine(hFile, "SearchAutoClose=" + BoolChar1(xSearchAutoClose))
      TxtFileWriter_WriteLine(hFile, "SearchAutoPlay=" + BoolChar1(xSearchAutoPlay))
      TxtFileWriter_WriteLine(hFile, "ShowFullPath=" + BoolChar1(ShowFullPath))
      TxtFileWriter_WriteLine(hFile, "ShowFullTitle=" + BoolChar1(ShowFullTitle))
      TxtFileWriter_WriteLine(hFile, "Sorting=" + BoolChar1(xSorting))
      xLong1 = 0
      If xShowSpectrum
        xLong1 = 1
        EndIf
      If xDeluxeSpectrum
        xLong1 | 2
        EndIf
      TxtFileWriter_WriteLine(hFile, "Spectrum=" + Str(xLong1))
      xLong1 = 0
      If RegFolderMode(0)
        xLong1 | 1
        EndIf
      If RegFolderMode(1)
        xLong1 | 2
        EndIf
      If RegFolderMode(2)
        xLong1 | 4
        EndIf
      If RegFolderMode(3)
        xLong1 | 8
        EndIf
      TxtFileWriter_WriteLine(hFile, "RegisterFolders=" + Str(xLong1))
      TxtFileWriter_WriteLine(hFile, "TitlesPosition=" + Str(xTitlesPos))
      TxtFileWriter_WriteLine(hFile, "TitlesWhenMinimized=" + Str(xTitlesWhenMinimized))
      TxtFileWriter_WriteLine(hFile, "TrackerPanSeperation=" + Str(xModPanning))
      TxtFileWriter_WriteLine(hFile, "TrayIcon=" + BoolChar1(xTrayIconVisible))
      TxtFileWriter_WriteLine(hFile, "TrayLeftClick=" + Str(xTrayIconLeft))
      TxtFileWriter_WriteLine(hFile, "TrayMinimize=" + BoolChar1(xTrayIconEnabled))
      TxtFileWriter_WriteLine(hFile, "TrayRightClick=" + Str(xTrayIconRight))
      TxtFileWriter_WriteLine(hFile, "UsedFileTypes=" + PrettyFileTypes())
      TxtFileWriter_WriteLine(hFile, "UsePlaylistSettings=" + BoolChar1(UsePLSettings))
      TxtFileWriter_WriteLine(hFile, "Volume=" + Str(xSetVolume))
      xResult = #True
      TxtFileWriter_Close(hFile)
CompilerIf #UseFileLogging
      Else
      MainForm_ctConsoleA_AddLog("Error saving preset")
CompilerEndIf
      EndIf
    ProcedureReturn xResult
  EndProcedure
  CompilerEndIf

Procedure MainForm_DelayedDragDrop()
  Define.i hBuff
  Define.s xChar1
  Define.i xLong1
  Define.i DropCount
  Define.i FileCount
  Define.i DirsCount
  Define.i Shift
  Define.i xSuccess
  Define.i OldPLCount
  
  
  If OLEDropMemory
    hBuff = OLEDropMemory
    OLEDropMemory = 0
    If Not (xAutoDoing Or PlayerIsLocked)
      SetAutoDoing(#True)
      BinaryBuffer_ReadMemEx(hBuff, @DropCount, 4)
;Debug "Read " + Str(DropCount)

      BinaryBuffer_ReadMemEx(hBuff, @Shift, 4)
      SetAutoDoing(#True)
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Analyzing OLE Drag Drop")
        CompilerEndIf
      xChar1 = BinaryBuffer_ReadStringLP(hBuff)
      If DropCount = 1
        Select AllowedItem(xChar1, #True)
          Case 253
            MainForm_LoadSettings(xChar1)
            SetAutoDoing(#False)
            xSuccess = #True
          Case 254
            MainForm_LoadTimers(MainHWnd, xChar1, #False)
            SetAutoDoing(#False)
            xSuccess = #True
          Case 255
            If PLCount Or xAutoDirCount Or xRadioCount
              If Not LCase(AppBase_GetByExt(#DefaultPLExtension)) = LCase(xChar1)
                PLWriter_Save(AppBase_GetByExt(#DefaultPLExtension), #False)
                EndIf
              EndIf
            xAutoDoing = #False
            LoadPList(xChar1, #False, #False) ;, #False)
            CheckReplay()
            xSuccess = #True
          EndSelect
        EndIf
      If PLCount < PLCountMaxX And Not xSuccess
        xPStateIconRefreshing = #True
        MainForm_UpdateMainIcon()
        If (Shift & 6)
          Shift = GetAPIPopupMenu(MainHWnd, xMenu(1), 0)
          If Shift = 0
            xPStateIconRefreshing = #False
            MainForm_UpdateMainIcon()
            SetAutoDoing(#False)
            xSuccess = #True
            EndIf
          Else
          Shift = 1901
          EndIf
        EndIf
      If Not xSuccess
        OldPLCount = PLCount
        DropCount - 1
        Dim xCharA1.s(DropCount)
        BinaryBuffer_SetReadOffset(hBuff, 8)
        For xLong1 = 0 To DropCount
          xChar1 = BinaryBuffer_ReadStringLP(hBuff)
          Select AllowedItem(xChar1, #True)
            Case 0
              If Len(xChar1) = 3 And Mid(xChar1, 2) = ":\"
                xChar1 = Left(xChar1, 2)
                EndIf
              xCharA1(DirsCount) = xChar1
              DirsCount + 1
            Case 1
              If FileCount < sCharA1Max
                sCharA1(FileCount) = xChar1
                FileCount + 1
                EndIf
            EndSelect
          Next
        If FileCount
          InitResearchClear()
          GenCalaymStructure(#True, FileCount, xSorting)
          ElseIf DirsCount
          InitResearchClear()
          EndIf
        If DirsCount And PLCount < PLCountMaxX
          MainForm_LockMe(#True)
          AbortReading = #False
          ReadDirInit()
          For xLong1 = 0 To DirsCount - 1
            ReadDirectory(xCharA1(xLong1), 0, #True, 0, Int((#xDefBWDifL * xLong1) / DirsCount), Int(#xDefBWDifL / DirsCount))
            If AbortReading
              Break
              EndIf
            If PLCount = PLCountMax
              Break
              EndIf
            Next
          ReadDirDone()
          MainForm_LockMe(#False)
          EndIf
        If OldPLCount = PLCount - 1
          xPStateIconRefreshing = #False
          MainForm_UpdateMainIcon()
          SetAutoDoing(#False)
          Else
          RealPLAdd(OldPLCount)
          xPStateIconRefreshing = #False
          MainForm_UpdateMainIcon()
          SetAutoDoing(#False)
          If FileCount Or DirsCount
            InitResearch(#False)
            EndIf
          CheckReplay()
        
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("Postprocessing OLE Drag Drop")
            CompilerEndIf
        
          If Not (Shift = 0 Or Shift = 1900)
            Shift = Shift - 1900
            Repeat
              If OldPLCount = PLCount
                Break
                EndIf
              CompilerIf #BoldDirs = 98
                If (PLI(OldPLCount)\DirDepthFlags & #PLI_IsDir) = 0
                  Break
                  EndIf
                CompilerElse
                If (PLIDF(OldPLCount) & #PLI_IsDir) = 0
                  Break
                  EndIf
                CompilerEndIf
              OldPLCount = OldPLCount + 1
              ForEver
            xMarkSong(OldPLCount, #False, #False)
            If Shift = 2
              MainForm_LockMe(#True)
              MainForm_xEndSong(#True, xPStateIconPaused, #False, #False)
              MainForm_LockMe(#False)
              PLCurItem = OldPLCount
              MainForm_xPlayClick(#False)
              ElseIf Shift = 3 Or Shift = 4
              PLNext = OldPLCount
              CompilerIf #BoldDirs = 98
                PlNextSong = PLI(OldPLCount)\Filename
                PlNextSongCap = PLI(OldPLCount)\Caption
                CompilerElse
                PlNextSong = PLIFile(OldPLCount)
                PlNextSongCap = PLICap(OldPLCount)
                CompilerEndIf
              SetNextSong(#True)
              If Shift = 3
                MainForm_CheckAfter(#True, #False, #True, #False) ;to prevent waitforendsong when xfading
                EndIf
              EndIf
            EndIf
          EndIf
        EndIf
      EndIf
    BinaryBuffer_Discard(hBuff)
    EndIf
  EndProcedure

Procedure MenuEventCDDrive(CDDriveLetters.s, ReAdd.i, RemoveNonRF.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xCaret
  Define.i xCaretOld
  
  If Not (ReAdd And (xAutoDoing Or PlayerIsLocked))
    MainForm_LockMe(#True)
    SetAutoDoing(#True)
    xPStateIconRefreshing = #True
    MainForm_UpdateMainIcon()
    DoEvents()
    If LockWinUpd
      LockWindowUpdate_(xListHWnd(2))
      EndIf
    xCaret = SendMessage_(xListHWnd(2), #LB_GETCARETINDEX, 0, 0)
    xCaretOld = xCaret
    InitResearchClear()

    While Not xLong1 = PLCount
CompilerIf #BoldDirs = 98
      If (PLI(xLong1)\DirDepthFlags & #PLI_Depth) = 0
        If Len(PLI(xLong1)\Filename) = 2 Or Not ReAdd
          If RemoveNonRF Or (PLI(xLong1)\DirDepthFlags & #PLI_IsAuto) = #PLI_IsAuto
            If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir And Mid(PLI(xLong1)\Filename, 2, 1) = ":" And FindString(CDDriveLetters, UCase(Left(PLI(xLong1)\Filename, 1))) ; Mid(PLItem(xLong1), 3) = CDDriveLetters
CompilerElse
      If (PLIDF(xLong1) & #PLI_Depth) = 0
        If Len(PLIFile(xLong1)) = 2 Or Not ReAdd
          If RemoveNonRF Or (PLIDF(xLong1) & #PLI_IsAuto) = #PLI_IsAuto
            If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir And Mid(PLIFile(xLong1), 2, 1) And FindString(CDDriveLetters, UCase(Left(PLIFile(xLong1), 1))) ; Mid(PLItem(xLong1), 3) = CDDriveLetters
CompilerEndIf
              Repeat
                ;RemoveListItemMS
                RemoveFromSearch(xLong2)
                ;PLRemoveShifted1 = xLong2
                ;PLRemoveShifted2 = xLong1
                SendMessage_(xListHWnd(2), #LB_DELETESTRING, xLong2, 0)
                If xCaret >= xLong2
                  xCaret = xCaret - 1
                  EndIf
                xLong1 = xLong1 + 1
                If xLong1 & $7f = 0
                  If LockWinUpd = 0
                    DoEventsEx_SleepPeriodical()
                    ElseIf LockWinUpd = 1
                    DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
                    EndIf
                  EndIf
                If Not (PLCurItem = 0 Or PLCurItem < xLong1)
                  PLCurItem = PLCurItem - 1
                  EndIf
                If PLNext = xLong1 And Not PlNextSong = ""
                  SetNextSong(#False)
                  EndIf
CompilerIf #BoldDirs = 98
                Until (xLong1 = PLCount Or (PLI(xLong1)\DirDepthFlags & #PLI_Depth) = 0)
              Else
              Goto KeepOldInfo
              EndIf
            Else
            Goto KeepOldInfo
            EndIf
CompilerElse
                Until (xLong1 = PLCount Or (PLIDF(xLong1) & #PLI_Depth) = 0)
              Else
              Goto KeepOldInfo
              EndIf
            Else
            Goto KeepOldInfo
            EndIf
CompilerEndIf
          ;PLRemoveShifted1 = $7FFFFFFF
          Else
          Goto KeepOldInfo
          EndIf
        Else
KeepOldInfo:
        If PLCurItem = xLong1
          PLCurItem = xLong2
          EndIf
        If PLNext = xLong1 And Not PlNextSong = ""
          PLNext = xLong2
          EndIf
          CompilerIf #BoldDirs = 98
          CopyStructureEx(PLI(xLong1), PLI(xLong2), tPlaylistItem)
          SendMessage_(xListHWnd(2), $19A, xLong2, xLong2)
          CompilerElse
          PLIFile(xLong2) = PLIFile(xLong1)
          PLICap(xLong2) = PLICap(xLong1)
          PLIDF(xLong2) = PLIDF(xLong1)
          PLIPxLg(xLong2) = PLIPxLg(xLong1)
          PLIPxSm(xLong2) = PLIPxSm(xLong1)
          SendMessage_(xListHWnd(2), $19A, xLong2, xLong2)
          CompilerEndIf
        xLong2 = xLong2 + 1
        xLong1 = xLong1 + 1
        EndIf
      Wend
    
    If Not (PLCount = 0 Or xCaret = xCaretOld)
      If xCaret > PLCount - 1
        xCaret = PLCount - 1
        EndIf
      If xCaret < 0
        xCaret = 0
        EndIf
      SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xCaret, 0)
      MainForm_CheckDir(#False)
      EndIf
    
    If LockWinUpd
      LockWindowUpdate_(0)
      EndIf
    PLCount = xLong2
      
    AbortReading = #False
    If ReAdd ;And Not PLCount < PLCountMaxX
      ;InitResearchClear()
      ReadDirInit()
      For xLong1 = 1 To Len(CDDriveLetters)
        If PLCount < PLCountMaxX
          ReadDirectory(Mid(CDDriveLetters, xLong1, 1) + ":", 0, #True, 0, Int((#xDefBWDifL * (xLong1 - 1)) / Len(CDDriveLetters)), Int(#xDefBWDifL / Len(CDDriveLetters)))
          Else
          Break
          EndIf
        Next
      ReadDirDone()
      MainForm_LockMe(#False)
      ;xPStateIconRefreshing = #False
      RealPLAdd(xLong2)
      xPStateIconRefreshing = #False
      SetAutoDoing(#False)
      MainForm_UpdateMainIcon()
      InitResearch(#False)
      CheckReplay()
      Else
      xPStateIconRefreshing = #False
      InitResearch(#False)
      MainForm_xBuildDirs()
      EndIf
    EndIf
  EndProcedure

Procedure ChangeVolumeMenu(Index.i)
  Define.i xLong1
  
  If Not PlayerIsLocked
    Select Index
      Case 0 ;VolUp
        xLong1 = xSetVolume + 10
      Case 1 ;VolDown
        xLong1 = xSetVolume - 10
      Case 3 To 13
        xLong1 = Int((Index - 3) * 25.5)
      EndSelect
  
    If xLong1 > 255
      xLong1 = 255
      ElseIf xLong1 < 0
      xLong1 = 0
      EndIf
    DoVolume(xLong1, #True)
    EndIf
  EndProcedure

Procedure.s GetPLTypes(ForSaving.i)
  Define.s xChar1
  If ForSaving
    CompilerIf #PB_Compiler_Unicode
      xChar1 = ReplaceString(ReplaceString(LoadResString(1230), "$X", "m3u8"), "$O", LoadResString(1241)) + #FileFilterVBNullChar + "*.m3u8" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(LoadResString(1231), "$X", "m3u"), "$O", LoadResString(1240)) + #FileFilterVBNullChar + "*.m3u" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(LoadResString(1231), "$X", "pls"), "$O", LoadResString(1240)) + #FileFilterVBNullChar + "*.pls" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(LoadResString(1231), "$X", "xspf"), "$O", LoadResString(1241)) + #FileFilterVBNullChar + "*.xspf" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(ReplaceString(LoadResString(1234), "$X", "aimppl"), "$P", "AIMP3"), "$O", LoadResString(1242)) + #FileFilterVBNullChar + "*.aimppl" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(ReplaceString(LoadResString(1234), "$X", "plc"), "$P", "AIMP2"), "$O", LoadResString(1242)) + #FileFilterVBNullChar + "*.plc" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(ReplaceString(LoadResString(1234), "$X", "aap"), "$P", "Apollo"), "$O", LoadResString(1240)) + #FileFilterVBNullChar + "*.aap" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(ReplaceString(LoadResString(1234), "$X", "wpl"), "$P", "Windows Media Player"), "$O", LoadResString(1240)) + #FileFilterVBNullChar + "*.wpl"
      CompilerElse
      xChar1 = ReplaceString(ReplaceString(LoadResString(1230), "$X", "m3u"), "$O", LoadResString(1240)) + #FileFilterVBNullChar + "*.m3u" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(LoadResString(1232), "$X", "m3u8"), "$O", LoadResString(1241)) + #FileFilterVBNullChar + "*.m3u8" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(LoadResString(1231), "$X", "pls"), "$O", LoadResString(1240)) + #FileFilterVBNullChar + "*.pls" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(LoadResString(1232), "$X", "xspf"), "$O", LoadResString(1241)) + #FileFilterVBNullChar + "*.xspf" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(ReplaceString(LoadResString(1235), "$X", "aimppl"), "$P", "AIMP3"), "$O", LoadResString(1242)) + #FileFilterVBNullChar + "*.aimppl" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(ReplaceString(LoadResString(1235), "$X", "plc"), "$P", "AIMP2"), "$O", LoadResString(1242)) + #FileFilterVBNullChar + "*.plc" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(ReplaceString(LoadResString(1234), "$X", "aap"), "$P", "Apollo"), "$O", LoadResString(1240)) + #FileFilterVBNullChar + "*.aap" + #FileFilterVBNullChar
      xChar1 + ReplaceString(ReplaceString(ReplaceString(LoadResString(1235), "$X", "wpl"), "$P", "Windows Media Player"), "$O", LoadResString(1241)) + #FileFilterVBNullChar + "*.wpl"
      CompilerEndIf
    Else
    CompilerIf #PB_Compiler_Unicode
      xChar1 = ReplaceString(LoadResString(1225), "$X", "*.m3u; *.m3u8 *.pls; *.xspf; *.aap; *.wpl") + #FileFilterVBNullChar + "*.m3u;*.m3u8;*.pls;*.xspf;*.aimppl;*.plc;*.aap;*.wpl"
      CompilerElse
      xChar1 = ReplaceString(LoadResString(1225), "$X", "*.m3u; *.pls; *.aap") + #FileFilterVBNullChar + "*.m3u;*.pls;*.aap;"
      CompilerEndIf
    EndIf
  ProcedureReturn xChar1
  EndProcedure

Procedure MenuEventFile_AddFileDialog()
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.s xChar1
  Define.s xChar2

  If PLCount < PLCountMaxX And Not (xAutoDoing Or PlayerIsLocked)
    If xUsedTypesResort
      xUsedTypes = MainForm_ResortTypes(xUsedTypes)
      EndIf
    DialogTimer(#True)
    xChar1 = OpenFileRequester(LoadResString(1200), xLastDirectory, GetUsedFileFilters(), 0, #PB_Requester_MultiSelection)
    DialogTimer(#False)
    If Len(xChar1) And PLCount < PLCountMaxX And Not (xAutoDoing Or PlayerIsLocked)
      CompilerIf #BoldDirs = 98
        PLI(PLCount)\Filename = GetPathPart(xChar1)
        PLI(PLCount)\Caption = PLI(PLCount)\Filename
        PLI(PLCount)\DirDepthFlags = #PLI_IsDir
        CompilerElse
        PLIFile(PLCount) = GetPathPart(xChar1)
        PLICap(PLCount) = PLIFile(PLCount)
        PLIDF(PLCount) = #PLI_IsDir
        CompilerEndIf
      PLCount = PLCount + 1
      xLong2 = 0
      xChar2 = GetPathPart(xChar1) + "\"
      While Len(xChar1)
        If AllowedItemSongFast(xChar1, #True)
          sCharA1(xLong2) = GetFilePart(xChar1)
          xLong2 = xLong2 + 1
          If xLong2 = sCharA1Max Or PLCount + xLong2 = PLCountMax
            Break
            EndIf
          EndIf
        xChar1 = NextSelectedFileName()
        Wend
      If xLong2 = 0
        PLCount = PLCount - 1
        Else
        xLong3 = PLCount - 1
        InitResearchClear()
        If xSorting
          SortArray(sCharA1(), #PB_Sort_Ascending | #PB_Sort_NoCase, 0, xLong2 - 1)
          EndIf
        For xLong1 = 0 To xLong2 - 1
          CompilerIf #BoldDirs = 98
            PLI(PLCount)\Filename = xChar2 + sCharA1(xLong1)
            PLI(PLCount)\Caption = sCharA1(xLong1)
            PLI(PLCount)\DirDepthFlags = 1
            CompilerElse
            PLIFile(PLCount) = xChar2 + sCharA1(xLong1)
            PLICap(PLCount) = sCharA1(xLong1)
            PLIDF(PLCount) = 1
            CompilerEndIf
          PLCount = PLCount + 1
          Next
        ;If Not xLong3 = PLCount
          RealPLAdd(xLong3)
        ;  EndIf
        InitResearch(#False)
        xMarkSong(xLong3, #False, #False)
        CheckReplay()
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure.s CalaymLoadSingleFile(Filter.s, Caption.s, InitDir.s, hWnd.i, SetDialogTimer.i)
  If SetDialogTimer
    DialogTimer(#True)
    EndIf
  If Not Right(InitDir, 1) = "\"
    If IsDirExists(InitDir)
      InitDir + "\"
      EndIf
    EndIf
  Caption = OpenFileRequester(Caption, InitDir, Filter, 0)
  If SetDialogTimer
    DialogTimer(#False)
    EndIf
  ProcedureReturn Caption
  EndProcedure

Procedure.s CalaymSaveSingleFile(Filter.s, Caption.s, InitDirFile.s, hWnd.i, SetDialogTimer.i)
  Define.GetSaveFilename_CustomParams xType1

  xType1\ErrExistsTitle = LoadResString(1270)
  xType1\ErrExistsText = LoadResString(1271)
  xType1\ErrROTitle = LoadResString(1272)
  xType1\ErrROText = LoadResString(1273)
  If SetDialogTimer
    DialogTimer(#True)
    EndIf
;  If Not Right(InitDir, 1) = "\"
;    If IsDirExists(InitDir)
;      InitDir + "\"
;      EndIf
;    EndIf

  Caption = GetSaveFileName(MainHwnd, Caption, InitDirFile, Filter, @xType1)
;  Caption = SaveFileRequester(Caption, InitDir, Filter, 0)
  If SetDialogTimer
    DialogTimer(#False)
    EndIf
  ProcedureReturn Caption
  EndProcedure

Procedure MenuEventFile(Index.i)
  Define.i xLong1
  ;Define.i xLong2
  ;Define.i xLong3
  Define.s xChar1
  ;Define.s xChar2
  ;Define.s xChar3

  If Not (PlayerIsLocked Or xAutoDoing)
    Select Index
      Case 0 ;addfiles
        MenuEventFile_AddFileDialog()

      Case 1 ;adddir
        If PLCount < PLCountMaxX And Not (xAutoDoing Or PlayerIsLocked)
          DialogTimer(#True)
          xChar1 = PathRequester(LoadResString(1210), xLastDir)
          If Right(xChar1, 1) = "\"
            xChar1 = Left(xChar1, Len(xChar1) - 1)
            EndIf
          DialogTimer(#False)
          If Len(xChar1) And PLCount < PLCountMaxX And Not (xAutoDoing Or PlayerIsLocked)
            SetAutoDoing(#True)
            AddFDirNowSub(xChar1)
            SetAutoDoing(#False)
            CheckReplay()
            EndIf
          EndIf
      Case 6 ;new
        PLCount = 0
        xRadioCount = 0
        RadioForm_PrePreset()
        PLCurItem = 0
        ClearOverload()
        If Not PlNextSong = ""
          SetNextSong(#False)
          EndIf
        ClearPLEx()
        xAutoDirCount = 0
        MainForm_xBuildDirs()
        MainForm_EnableApiMenu(411, #False)
        MainForm_EnableApiMenu(412, #False)
        MainForm_EnableApiMenu(413, #False)
        MainForm_EnableApiMenu(414, #False)
        xCurPlistFilename = AppBase_GetByExt(#DefaultPLExtension)
        xRadioCount = 0
        RadioForm_PrePreset()
        CheckShowWizard()
      Case 2, 7 ;addpl / load
        If (PLCount < PLCountMaxX Or Index = 7) And Not xAutoDoing
          xChar1 = CalaymLoadSingleFile(GetPLTypes(#False), LoadResString(1220), m3uList, MainHWnd, #True)
          If Not xChar1 = ""
            m3uList = SimpleDir(xChar1)
            If AllowedItem(xChar1, #True) = 255
              If Not ((PLCount = 0 And xAutoDirCount = 0 And xRadioCount = 0) Or (Not Index = 2) Or LCase(xChar1) = LCase(AppBase_GetByExt(#DefaultPLExtension)) Or LCase(xChar1) = LCase(xCurPlistFilename))
                PLWriter_Save(AppBase_GetByExt(#DefaultPLExtension), #False)
                EndIf
              If Not PlNextSong = ""
                SetNextSong(#False)
                EndIf
              If Index = 2
                LoadPList(xChar1, #True, #False)   ;, #False)
                Else
                PLCount = 0
                xRadioCount = 0
                RadioForm_PrePreset()
                LoadPList(xChar1, #False, #False)   ;, #False)
                EndIf
              EndIf
            EndIf
          EndIf
      Case 8 ;load default pl
        LoadPList(AppBase_GetByExt(#DefaultPLExtension), #False, #False)
      Case 9 ;reload
        ;If AutoRefreshVisible
        ;  SetWindowPos_(frmAutoRefresh.hwnd, 0, 0, 0, 0, 0, $3)
        ;  Else
          If Not PlNextSong = ""
            SetNextSong(#False)
            EndIf
          PLCount = 0
          xRadioCount = 0
          RadioForm_PrePreset()
          ;xPStateIconRefreshing = #True
          ;ShowIcon 0
          ;DoEvents()
;Stop
          LoadPList(xCurPlistFilename, #False, #False)  ;, #False)
          ;xPStateIconRefreshing = #False
          ;ShowIcon 0
        ;  endif
      Case 10 ;save
        If Not xNoSaveListMenu = 2
          If xCurPlistFilenameSuggestNew
            Goto AskNewFilename
            EndIf
          If Not PLWriter_Save(xCurPlistFilename, #False)
            Goto AskNewFilename
            EndIf
          EndIf
      Case 11 ;save as
        If Not xNoSaveListMenu = 2
AskNewFilename:
          If xCurPlistFilenameSuggestNew Or LCase(xCurPlistFilename) = LCase(AppBase_GetByExt(#DefaultPLExtension))
            xChar1 = m3uList
            Else
            xChar1 = xCurPlistFilename
            EndIf
;debug xChar1
          xChar1 = CalaymSaveSingleFile(GetPLTypes(#True), LoadResString(1221), xChar1, MainHWnd, #True)
;Debug "SavePL1:" + xChar1
          If Not xChar1 = ""
            m3uList = SimpleDir(xChar1)
            xLong1 = AllowedItem(xChar1, #False)
;Debug "SavePL1:" + Str(xLong1)
            If xLong1 = 255 Or xLong1 = -1
;Debug "EnterSave"
              If PLWriter_Save(xChar1, #True)
                ;xLong1 = InstrRevChar(xChar1, 92) ;"\"
                ;xChar2 = Left(xChar1, xLong1)
                EndIf
              EndIf
            EndIf
          EndIf
      Case 13 ;clear playlist
        ;If Not xAutoDoing
          InitResearchClear()
          If Not PlNextSong = ""
            SetNextSong(#False)
            EndIf
          PLCurItem = 0
          PLCount = 0
          ClearOverload()
          ClearPLEx()
          InitResearch(#False)
      EndSelect
    EndIf
  EndProcedure

CompilerIf #PresetBinded
  Procedure MenuEventPlaylistLoader(Index.i)
    Define.s xChar1
    
    If Not (PlayerIsLocked Or xAutoDoing)
      If Index = 0
        ;save
        xChar1 = CalaymSaveSingleFile(LoadResString(1655) + #FileFilterVBNullChar + "*.cps", LoadResString(1651), PresetFile, MainHWnd, #True)
        If Not xChar1 = ""
          If SavePreset(xChar1)
            PresetFile = SimpleDir(xChar1)
            EndIf
          EndIf
        Else
        ;load; =2
        xChar1 = CalaymLoadSingleFile(LoadResString(1655) + #FileFilterVBNullChar + "*.cps" + #FileFilterVBNullChar + LoadResString(1656) + #FileFilterVBNullChar + "*.ini", LoadResString(1650), PresetFile, MainHWnd, #True)
        If Not Len(xChar1) = 0
          PresetFile = SimpleDir(xChar1)
          If AllowedItem(xChar1, #True) = 253
            MainForm_LoadSettings(xChar1)
            EndIf
          EndIf
        EndIf
      EndIf
    EndProcedure
  CompilerEndIf

Procedure.i GetTrackNumber(Filename.s)
  Define.i xResult
  Define.i xLong1
  Define.i xLong2
  
  xLong1 = Len(Filename) - 4
  While xLong2 < xLong1
    xLong2 = xLong2 + 1
    If Not FindString("0123456789", Mid(Filename, xLong2, 1)) = 0
      Filename = Mid(Filename, xLong2)
      xLong1 = xLong1 - xLong2 + 2
      xLong2 = 1
      While xLong2 < xLong1
        xLong2 = xLong2 + 1
        If FindString("0123456789", Mid(Filename, xLong2, 1)) = 0
          Break
          EndIf
        Wend
      If Not xLong2 = 1
        xResult = Val(Left(Filename, xLong2 - 1))
        EndIf
      EndIf
    Wend
    
  ;xChar1 = Mid(xChar1, 9)
  ;xChar1 = Left(xChar1, FindString(xChar1 & ".", ".") - 1)
  ;;If Val(xChar2) > 0
  ProcedureReturn xResult
  EndProcedure

Procedure EndSongEx()
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  setting as next song")
    CompilerEndIf
  
  PLNext = PLCurItem
  CompilerIf #BoldDirs = 98
    PlNextSong = PLI(PLCurItem)\Filename
    PlNextSongCap = PLI(PLCurItem)\Caption
    CompilerElse
    PlNextSong = PLIFile(PLCurItem)
    PlNextSongCap = PLICap(PLCurItem)
    CompilerEndIf
  SetNextSong(#True)
  SilentPlNext = #True
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  done")
    CompilerEndIf
  EndProcedure

Procedure.i TrackerIsLooping()
  Define.i xResult
  If xXFadeCurMusic = #ctSSLayer_MusicTypeTracker And (ctSSLayer_CanUseItem(6) & 4) = 0
    xResult = ctSSLayer_MusicHasFinished(SongPointer(OldSongID))
    ElseIf xXFadeCurMusic = #ctSSLayer_MusicTypeTracker
    xResult = ctSSLayer_MusicHasFinished(SongPointer(OldSongID))
    EndIf
  CompilerIf #UseFileLogging
    If xResult
      xResult = 1
      EndIf
    MainForm_ctConsoleA_AddLog("  TrackerIsLooping=" + Str(xResult))
    CompilerEndIf
  If xResult
    xResult = #True
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure xPlayItem_HideAnimAndExit()
  xLoadingStream = 0
  ;UpdateAnimIcon
  MainForm_UpdateMainIcon()
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xPlayItemC(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
    CompilerEndIf
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  xPlayItem finished")
    CompilerEndIf
  EndProcedure

Procedure.i GetTimeFmtMax()
  Define.i xResult
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  Define.s xChar2
  
  If PLCurSongLength > 0 Or ctSSLayer_CanUseItem(6) = $2
    If CurMusic = #ctSSLayer_MusicTypeTracker And ctSSLayer_CanUseItem(6) < 2
      xChar1 = StringFromCharCode(Int(Log10(PLCurSongLength)) + 1, 42) + "/" + StrU(PLCurSongLength) ;"*"
      Else
      If PLCurSongLength < 600000
        xChar1 = "*:**"
        ElseIf PLCurSongLength < 3600000
        xChar1 = "**:**"
        Else
        xChar1 = StringFromCharCode(Int(Log10(Int(PLCurSongLength / 3600000)) + 1), 42) + ":**:**" ; "*"
        EndIf
      EndIf
    ElseIf CurMusic = #ctSSLayer_MusicTypeTracker And ctSSLayer_CanUseItem(6) < 2
    If PLCurSongLength > 0
      xChar1 = StringFromCharCode(Int(Log10(PLCurSongLength)) + 1, 63) + "/" + StrU(PLCurSongLength) ;"?"
      Else
      xChar1 = "??/??"
      EndIf
    Else ;somethingtimebased
      If PLCurSongLength < 600000 Or (CurMusic = #ctSSLayer_MusicTypeTracker And (ctSSLayer_CanUseItem(6) & 4) = 0)
        xChar1 = "?:??"
        ElseIf PLCurSongLength < 3600000
        xChar1 = "??:??"
        Else
        xChar1 = StringFromCharCode(Int(Log10(Int(PLCurSongLength / 3600000))) + 1, 63) + "??:??" ;"?"
        EndIf
    EndIf
  
  xChar1 = " " + xChar1 + " " ; -  "
  
  SelectObject_(xSharedDC, hFontGFix)
  For xLong1 = 48 To 57 ;0 To 9
    xChar2 = ReplaceString(xChar1, "*", Chr(xLong1))
    xLong2 = GetTextOutWidth(xSharedDC, xChar2)
    If xLong2 > xResult
      xResult = xLong2
      EndIf
    Next
  ProcedureReturn xResult
  EndProcedure

Procedure.i GetTimeFmtMaxPerc()
  Define.i xResult
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  
  ;SelectObject_(xSharedDC, hFontPLSm) done by our only caller
  xChar1 = " 100% " ; -  "
  xResult = GetTextOutWidth(xSharedDC, xChar1)
  For xLong1 = 49 To 57 ; 1 To 9
    xChar1 = " " + Chr(xLong1) + Chr(xLong1) + " "
    xLong2 = GetTextOutWidth(xSharedDC, xChar1)
    If xLong2 > xResult
      xResult = xLong2
      EndIf
    Next
  ;ePic_Paint 3
  ProcedureReturn xResult
  EndProcedure

CompilerIf #LoudestSongMethode
Procedure xAddLastDir()
CompilerElse
Procedure xAddLastDir(canShowIR.i)
CompilerEndIf
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  
  CompilerIf #LoudestSongMethode
    CompilerElse
    If canShowIR
      ShowIR
      EndIf
    CompilerEndIf

  If Not xLastPathCount = 0
CompilerIf #BoldDirs = 98
    If UCase(xLastPath(xLastPathCount - 1)) = UCase(PLI(PLCurItem)\Filename)
CompilerElse
    If UCase(xLastPath(xLastPathCount - 1)) = UCase(PLIFile(PLCurItem))
CompilerEndIf
      ProcedureReturn
      EndIf
    EndIf
  CompilerIf #BoldDirs = 98
    xChar1 = PLI(PLCurItem)\Caption
  CompilerElse
    xChar1 = PLICap(PLCurItem)
    CompilerEndIf
  
  SelectObject_(xSharedDC, hFontGFix)
  xLong2 = GetTextOutWidth(xSharedDC, xChar1)
  
  If xLastPathCount = #xLastPathMax
    xLastPathCurMaxWidth = 0
;    xLong2 = xLastPathLen(0)
    For xLong1 = 0 To #xLastPathMax - 2
      xLastPath(xLong1) = xLastPath(xLong1 + 1)
      xLastPathCap(xLong1) = xLastPathCap(xLong1 + 1)
      xLastPathTime(xLong1) = xLastPathTime(xLong1 + 1)
      xLastPathLen(xLong1) = xLastPathLen(xLong1 + 1)
      SendMessage_(xListHWnd(1), $19A, xLong1 + 1, xLong1)
      If xLastPathLen(xLong1) > xLastPathCurMaxWidth
        xLastPathCurMaxWidth = xLastPathLen(xLong1)
        EndIf
      Next
    SendMessage_(xListHWnd(1), #LB_DELETESTRING, 0, 0)
    xLastPathCount = #xLastPathMaxX
    EndIf
  
  CompilerIf #BoldDirs = 98
    xLastPath(xLastPathCount) = PLI(PLCurItem)\Filename
    xLastPathCap(xLastPathCount) = PLI(PLCurItem)\Caption
    CompilerElse
    xLastPath(xLastPathCount) = PLIFile(PLCurItem)
    xLastPathCap(xLastPathCount) = PLICap(PLCurItem)
    CompilerEndIf
  xLastPathTime(xLastPathCount) = SPTimeShort()
  xLastPathLen(xLastPathCount) = xLong2
  If xLong2 > xLastPathCurMaxWidth
    xLastPathCurMaxWidth = xLong2
    EndIf
  SendMessage_(xListHWnd(1), #LB_ADDSTRING, 0, xLastPathCount)

  SendMessage_(xListHWnd(1), $194, (32 + xLastPathTimeSpace + xLastPathCurMaxWidth), 0)
  xLastPathCount = xLastPathCount + 1
  
  If SendMessage_(xListHWnd(1), #LB_GETCURSEL, 0, 0) = (xLastPathCount - 2) ;Or xLastPathCount = 1
    SendMessage_(xListHWnd(1), #LB_SETCURSEL, xLastPathCount - 1, 0)
    EndIf
CompilerIf #LoudestSongMethode
  EndProcedure
CompilerElse
  EndProcedure
CompilerEndIf

Procedure CheckThisSong(FileID.i)  ;(FileID.i) ; Always PLCurItem
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.s xChar1
  ;define.s xChar2
  ;Dim xBool1 As Boolean
  ;Dim FileID.i
  
  ;FileID = PLCurItem

  CompilerIf #BoldDirs = 98
    xChar1 = PLI(FileID)\Filename
    CompilerElse
    xChar1 = PLIFile(FileID)
    CompilerEndIf
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Checking file: " + xChar1)
    CompilerEndIf
  
  If Not IsFileExists(xChar1)
CompilerIf #BoldDirs = 98
    If (PLI(FileID)\DirDepthFlags & #PLI_IsAuto) = #PLI_IsAuto
CompilerElse
    If (PLIDF(FileID) & #PLI_IsAuto) = #PLI_IsAuto
CompilerEndIf
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  not found. is autorefresh")
        CompilerEndIf
      xPStateIconRefreshing = #True
      MainForm_UpdateMainIcon()
      MainForm_xAutoRefreshNow(#False, #True, #False, #False, #True)
      MainForm_LockMe(#True)
      If PLCount = 0 And CurMusic = #ctSSLayer_MusicTypeNone
        xPStateIconPlaying = #False
        EndIf
      xPStateIconRefreshing = #False
      MainForm_UpdateMainIcon()
      Else
      If xRemoveMissingSongs
        If Not xAutoDoing
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("  not found. removing")
            CompilerEndIf
          xLong4 = FileID
          CompilerIf #BoldDirs = 98
            xLong1 = (PLI(FileID)\DirDepthFlags & #PLI_Depth) - 1
            CompilerElse
            xLong1 = (PLIDF(FileID) & #PLI_Depth)
            CompilerEndIf
          xLong2 = FileID
;DoEventsEx_Sleep 5000
          Repeat
            xLong2 = xLong2 - 1
;            Exit Do
CompilerIf #BoldDirs = 98
            If (PLI(xLong2)\DirDepthFlags & #PLI_Depth) = xLong1
CompilerElse
            If (PLIDF(xLong2) & #PLI_Depth) = xLong1
CompilerEndIf
              CompilerIf #BoldDirs = 98
                xLong3 = GetFileAttributes(PLI(xLong2)\Filename)
                CompilerElse
                xLong3 = GetFileAttributes(PLIFile(xLong2))
                CompilerEndIf
              
              If xLong1 = 0
                CompilerIf #UseFileLogging
                  MainForm_ctConsoleA_AddLog("ExtRemoving 0")
                  CompilerEndIf
                If xLong3 = -1 Or (xLong3 & 16) = 0
                  xLong4 = xLong2
                  EndIf
                Break
                Else
                If xLong3 = -1 Or (xLong3 & 16) = 0
                  CompilerIf #UseFileLogging
                    MainForm_ctConsoleA_AddLog("ExtRemoving -")
                    CompilerEndIf
                  xLong1 = xLong1 - 1
                  xLong4 = xLong2
                  Else
                  CompilerIf #UseFileLogging
                    MainForm_ctConsoleA_AddLog("ExtRemoving \")
                    CompilerEndIf
                  xLong1 = xLong1 + 1
                  Break
                  EndIf
                EndIf
              EndIf
            ForEver
          If xLong4 = FileID
            xLong3 = 1
            Else
            xLong3 = PLCount - 1
            For xLong2 = FileID + 1 To PLCount - 2
CompilerIf #BoldDirs = 98
              If (PLI(xLong2)\DirDepthFlags & #PLI_Depth) <= xLong1
CompilerElse
              If (PLIDF(xLong2) & #PLI_Depth) <= xLong1
CompilerEndIf
                xLong3 = xLong2 - 1
                Break
                EndIf
              Next
;debug "RemoveThis!", xLong4, xLong3
            xLong3 = xLong3 - xLong4 + 1
            EndIf
          
;debug "RemoveThis!", xLong4, xLong3
          
          If xLong3 = 1
            RemoveFromSearch(xLong4)
            Else
            InitResearchClear()
            EndIf
          For xLong1 = xLong4 To PLCount - xLong3 - 1
            CompilerIf #BoldDirs = 98
              CopyStructureEx(PLI(xLong1 + xLong3), PLI(xLong1), tPlaylistItem)
              SendMessage_(xListHWnd(2), $19A, xLong1 + xLong3, xLong1)
              CompilerElse
              PLIFile(xLong1) = PLIFile(xLong1 + xLong3)
              PLICap(xLong1) = PLICap(xLong1 + xLong3)
              PLIDF(xLong1) = PLIDF(xLong1 + xLong3)
              PLIPxLg(xLong1) = PLIPxLg(xLong1 + xLong3)
              PLIPxSm(xLong1) = PLIPxSm(xLong1 + xLong3)
              SendMessage_(xListHWnd(2), $19A, xLong1 + xLong3, xLong1)
              CompilerEndIf
            Next
          For xLong1 = xLong4 + xLong3 - 1 To xLong4 Step -1
            RemoveListItemMS(xListHWnd(2), xLong1)
            Next
          PLCount = PLCount - xLong3
          ;FileID = FileID - xlong3
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("BeforeCheckThisSong: " + Str(SendMessage_(xListHWnd(2), #LB_GETCOUNT, 0, 0)) + "?=" + Str(PLCount))
            CompilerEndIf
          If Not PLCurItem = 0
            If PLCurItem >= xLong4 + xLong3
              PLCurItem = PLCurItem - xLong3
              ElseIf PLCurItem >= xLong4
              PLCurItem = xLong4 - 1
              EndIf
;            Stop
            If PLCurItem < 0
              PLCurItem = 0
              EndIf
            EndIf
          If Not PlNextSong = ""
            If PLNext >= xLong4 + xLong3
              PLNext = PLNext - xLong3
              ElseIf PLNext >= xLong4
              SetNextSong(#False)
              EndIf
            If PLNext < 0
              PLNext = 0
              EndIf
            EndIf
DoneLargeRemoving:
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("BeforeCheckEmptyNodes: " + Str(SendMessage_(xListHWnd(2), #LB_GETCOUNT, 0, 0)) + "?=" + Str(PLCount))
            CompilerEndIf
          If xLong3 = 1
            CheckEmptyNodes(#False, xLong4) ; -1
            Else
            CheckEmptyNodes(#False, -1)
            InitResearch(#False)
            EndIf
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("AfterCheckEmptyNodes: " + Str(SendMessage_(xListHWnd(2), #LB_GETCOUNT, 0, 0)) + "?=" + Str(PLCount))
            CompilerEndIf
;If PLCount < 3
  ;Stop
  ;EndIf
          ;1.00 beta 52 (endinging with crossfade will not stop properly if playlist gets empty)
          ;from:
          ;If PLCount = 0
          ;to:
          If PLCount = 0 And CurMusic = #ctSSLayer_MusicTypeNone
            xPStateIconPlaying = #False
            MainForm_UpdateMainIcon()
            EndIf
          CompilerIf #UseFileLogging
            Else
            MainForm_ctConsoleA_AddLog("  not found. cannot remove currently")
            CompilerEndIf
          EndIf
        CompilerIf #UseFileLogging
          Else
          MainForm_ctConsoleA_AddLog("  not found.")
          CompilerEndIf
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure.i xPlayItem(CanFade.i, PlaySilent.i, DoCrossFade.i, NoSFXWait.i, ResumePaused.i, ManualURL.s)
  Define.i xResult
  Define.i xBool1
  Define.i xLong1
  Define.i xLong2
  Define.i PreJump
  Static xLastOpenedLogged.s
  Define.i xGotoBoolURLHack
  Define.i TempMusic
  Define.i xCrossFadeTimeMN
  Define.i xCrossFadeTimeMT
  Define.i xCrossFadeTimeEN
  Define.i xBool2
  Define.s xChar1

  CompilerIf #UseFileLogging
    If Not PlayerIsLocked
      MessageBox_(MainHWnd, @"Error 200510-2", @"please report me", #MB_ICONEXCLAMATION)
      ;Me.Visible = #False
      ;DoEvents()
      ProcedureReturn 0
      EndIf
    CompilerEndIf
  
  If Not xGenFading
    CanFade = #False
    EndIf
  If ctSSLayer_MaxIDs = 2
    CanFade = #False
    EndIf
  ;If ctSSLayer_MaxIDs < 5
  ;  DoCrossFade = #False
  ;  EndIf
  
  If Len(ManualURL)
    xGotoBoolURLHack = #True
    ElseIf PLCount = 0
    xResult = #True
    If Not CurMusic = #ctSSLayer_MusicTypeNone
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("!Stopped2")
        CompilerEndIf
      If CanFade And Not xPStateIconPaused
        MainForm_xEndSong(#True, #False, #False, #False)
        Else
        MainForm_xEndSong(#False, #False, #False, #False)
        EndIf
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("xPlayItem1(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
        CompilerEndIf
      xPStateIconPlaying = #False
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("xPlayItem2(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
        CompilerEndIf
;      CurMusic = #ctSSLayer_MusicTypeNone
      MainForm_UpdateMainIcon()
      If Not PlNextSong = ""
        SetNextSong(#False)
        EndIf
      EndIf
CompilerIf #BoldDirs = 98
    ElseIf (PLI(PLCurItem)\DirDepthFlags & #PLI_IsDir) = 0
CompilerElse
    ElseIf (PLIDF(PLCurItem) & #PLI_IsDir) = 0
CompilerEndIf
    xGotoBoolURLHack = #True
    EndIf
  
  If xGotoBoolURLHack
    CompilerIf #PlayLoosingLog
      MainForm_ctConsoleA_AddLog("xPlayItem3(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
      CompilerEndIf
    If CurMusic = #ctSSLayer_MusicTypeNone
      CanFade = #False
      DoCrossFade = #False
      ElseIf Not (DoCrossFade And xPStateIconPlaying)
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("!Stopped3")
        CompilerEndIf
      MainForm_xEndSong(CanFade, xPStateIconPaused, #False, #False)
      EndIf
    OldSongID = CurrentSongID
    xXFadeCurMusic = CurMusic
    xXFadeOldTime = PLCurSongLength
    DoEvents()
    
    CompilerIf #PlayLoosingLog
      MainForm_ctConsoleA_AddLog("xPlayItem4(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
      CompilerEndIf
    If xPStateIconPlaying
      CompilerIf #UseFileLogging
        If Len(ManualURL) = 0
          CompilerIf #BoldDirs = 98
            MainForm_ctConsoleA_AddLog("Playitem: " + PLI(PLCurItem)\Filename)
            CompilerElse
            MainForm_ctConsoleA_AddLog("Playitem: " + PLIFile(PLCurItem))
            CompilerEndIf
          Else
          MainForm_ctConsoleA_AddLog("PlayStream: " + RealURL(ManualURL))
          EndIf
        CompilerEndIf
      
      xSongWillBeMidi = 0
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("xPlayItem5(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
        CompilerEndIf
      
      If Len(ManualURL) = 0
        CompilerIf #BoldDirs = 98
          xChar1 = GetExtensionPart(PLI(PLCurItem)\Filename)
          CompilerElse
          xChar1 = GetExtensionPart(PLIFile(PLCurItem))
          CompilerEndIf
        If xChar1 = "cda"
          TempMusic = #ctSSLayer_MusicTypeCDAudio
          xSongWillBeMidi = 2
          ElseIf FindString(xSupportedFilesS, #UsedTypesVBNullChar + xChar1 + #UsedTypesVBNullChar) = 0
          If FindString(xSupportedFilesM, #UsedTypesVBNullChar + xChar1 + #UsedTypesVBNullChar) And ctSSLayer_CanUseItem($9) = 0
            xSongWillBeMidi = 1
            EndIf
          TempMusic = #ctSSLayer_MusicTypeTracker
          Else
          TempMusic = #ctSSLayer_MusicTypeStream
          EndIf
        If TempMusic = #ctSSLayer_MusicTypeCDAudio
;          xChar1 = GetTrackNumber(Mid(PLItem(PLCurItem), 3))
;          If Val(xChar1) = 0
CompilerIf #BoldDirs = 98
          If GetTrackNumber(PLI(PLCurItem)\Filename) = 0
CompilerElse
          If GetTrackNumber(PLIFile(PLCurItem)) = 0
CompilerEndIf
            CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  invalid cd track id")
              CompilerEndIf
            ProcedureReturn 0
            EndIf
          ;xChar1 = Mid(PLItem(PLCurItem), 3, 1) + xChar1
          ;Else
          ;xChar1 = Mid(PLItem(PLCurItem), 3)
          EndIf
        Else
        TempMusic = #ctSSLayer_MusicTypeStream
        ;xChar1 = ManualURL
        xSongWillBeMidi = 3
        EndIf


      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("xPlayItem6(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
        CompilerEndIf
      
      If xSongWillBeMidi = xSongIsMidi And DoCrossFade And xSongWillBeMidi
        If NoSFXWait
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("!Stopped1")
            CompilerEndIf
          MainForm_xEndSong(CanFade, xPStateIconPaused, #True, #False)
          DoCrossFade = #False
          Else
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("  cannot crossfade from CD audio to CD audio, playing after current song")
            CompilerEndIf
          EndSongEx()
          ProcedureReturn #True
          EndIf
        EndIf
      
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  loading & initializing...")
        CompilerEndIf
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("xPlayItem7(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
        CompilerEndIf







      If Len(ManualURL) = 0
        xLoadingStream = 1
        Else
        xLoadingStream = 2
        xLoadURL = ManualURL
        EndIf
      MainForm_UpdateMainIcon()
      If xClassicBlockingOnLoad
        DoEvents()
        EndIf
      ;UpdateAnimIcon






      Tear_WaitFor(xSongWillBeMidi)
;      debug "DoneWaiting"
      xLong2 = GetTickTimeMS()
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  load1")
        CompilerEndIf
            
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("xPlayItem8(xPStateIconPlaying=" + Str(xPStateIconPlaying) + ", CurMusic=" + Str(CurMusic) + ")")
        CompilerEndIf
      ;debug NewSongID
      If Not xClassicBlockingOnLoad
        xLong1 = 2
        EndIf
      If Len(ManualURL) = 0
        ;xLoadingStream = 1
        ;MainForm_UpdateMainIcon()
        ;;UpdateAnimIcon
        If CheckAccurate
          xLong1 | 1
          EndIf
        CompilerIf #BoldDirs = 98
          SongPointer(NewSongID) = ctSSLayer_LoadSong(TempMusic, @PLI(PLCurItem)\Filename, xLong1)
          CompilerElse
          SongPointer(NewSongID) = ctSSLayer_LoadSong(TempMusic, @PLIFile(PLCurItem), xLong1)
          CompilerEndIf
        Else
        ;xLoadingStream = 2
        ;;xLoadURL = ManualURL
        ;;UpdateAnimIcon
        ;MainForm_UpdateMainIcon()
        xChar1 = RealURL(ManualURL)
        SongPointer(NewSongID) = ctSSLayer_LoadSong(#ctSSLayer_MusicTypeInetStream, @xChar1, xLong1)
        EndIf
CompilerIf #UseFileLogging
  MainForm_ctConsoleA_AddLog("  load2")
  CompilerEndIf
      TearDown_Relocate(xLong2)
;      debug "DoneLoading"
      If SongPointer(NewSongID)
        Select ctSSLayer_LoadSongFinished(SongPointer(NewSongID))
          Case -1
            CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  blockstate: error")
              CompilerEndIf
            ctSSLayer_LoadSongAbort(SongPointer(NewSongID))
            SongPointer(NewSongID) = 0
          Case 0
            CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  blockstate: waiting...")
              CompilerEndIf
            xLong1 = GetTickTimeMS()
CompilerIf #BlockTimeOutHandle
            xLong2 = GetTickTimeMS()
CompilerEndIf
            Repeat
              DoEventsEx_Sleep(25)
              If IsTickTimeElapsedMS(xLong1, #DoEventsEx_SleepPeriodical_Interval)
                DoAnimateReadDir(1)
                xLong1 = GetTickTimeMS()
                Select ctSSLayer_LoadSongFinished(SongPointer(NewSongID))
                  Case -1
                    CompilerIf #UseFileLogging
                      MainForm_ctConsoleA_AddLog("  blockstate: posterror")
                      CompilerEndIf
CompilerIf #BlockTimeOutHandle
PostBlockTimeOut:
CompilerEndIf
                    ctSSLayer_LoadSongAbort(SongPointer(NewSongID))
                    SongPointer(NewSongID) = 0
                    Break
                  Case 1
                    
                    
                    CompilerIf #UseFileLogging
                      MainForm_ctConsoleA_AddLog("  blockstate: success / nonblocked")
                      CompilerEndIf
                    Break
                  EndSelect
                EndIf
CompilerIf #BlockTimeOutHandle
              If IsTickTimeElapsedMS(xLong1, 30000)
                MainForm_ctConsoleA_AddLog("  blockstate: timeout")
                Goto PostBlockTimeOut
                EndIf
CompilerEndIf
              ForEver
CompilerIf #UseFileLogging
          Case 1
            MainForm_ctConsoleA_AddLog("  blockstate: success / nonblocked")
CompilerEndIf
          EndSelect
        EndIf
      ;xLoadingStream = 0
      ;UpdateAnimIcon
      ;MainForm_UpdateMainIcon()
      If Not SongPointer(NewSongID) = 0
CompilerIf #UseFileLogging
  MainForm_ctConsoleA_AddLog("  load3")
  CompilerEndIf
        
        xLong1 = ctSSLayer_SongLength(SongPointer(NewSongID))
CompilerIf #UseFileLogging
  MainForm_ctConsoleA_AddLog("  load4")
  CompilerEndIf
        If TempMusic = #ctSSLayer_MusicTypeTracker And (ctSSLayer_CanUseItem(6) & 4) = 0
          For xCrossFadeTimeMN = xCrossFadeTimeM To 1 Step -1
            If xLong1 > CrossFadeMinPatterns(xCrossFadeTimeMN)
              Break
              EndIf
            Next
CompilerIf #UseFileLogging
  MainForm_ctConsoleA_AddLog("  load4a")
  CompilerEndIf
          If (xLong1 < CrossFadeNewMinMinPatterns(xCrossFadeTimeMN) Or (xLong1 < CrossFadeMinPatterns(xCrossFadeTimeMN) And Not NoSFXWait))
            xBool1 = #True
            Else
            xBool1 = #False
            EndIf
          If DoCrossFade
            xLong2 = xXFadeOldTime - ctSSLayer_GetPosition(SongPointer(OldSongID))
CompilerIf #UseFileLogging
  MainForm_ctConsoleA_AddLog("  load4b")
  CompilerEndIf
            For xCrossFadeTimeEN = xCrossFadeTimeMN To 1 Step -1
              If xLong2 > CrossFadeMinRemainPatterns(xCrossFadeTimeEN)
                Break
                EndIf
              Next
            If (xLong2 < CrossFadeMinRemainPatterns(xCrossFadeTimeEN))
              xBool2 = #True
              Else
              xBool2 = #False
              EndIf
            EndIf
          Else
          For xCrossFadeTimeMN = xCrossFadeTimeM To 1 Step -1
            If xLong1 > CrossFadeMinTime(xCrossFadeTimeMN)
              Break
              EndIf
            Next
CompilerIf #UseFileLogging
  MainForm_ctConsoleA_AddLog("  load4c")
  CompilerEndIf
          If (xLong1 < CrossFadeNewMinMinTime(xCrossFadeTimeMN) Or (xLong1 < CrossFadeMinTime(xCrossFadeTimeMN) And Not NoSFXWait))
            xBool1 = #True
            Else
            xBool1 = #False
            EndIf
          If DoCrossFade
            If (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
              xLong2 = 360000
              ;debug "OldURLHack2"
              Else
              xLong2 = xXFadeOldTime - ctSSLayer_GetPosition(SongPointer(OldSongID))
              EndIf
CompilerIf #UseFileLogging
  MainForm_ctConsoleA_AddLog("  load4d")
  CompilerEndIf
            For xCrossFadeTimeEN = xCrossFadeTimeMN To 1 Step -1
              If xLong2 > CrossFadeMinRemainTime(xCrossFadeTimeEN)
                Break
                EndIf
              Next
            If (xLong2 < CrossFadeMinRemainTime(xCrossFadeTimeEN))
              xBool2 = #True
              Else
              xBool2 = #False
              EndIf
            EndIf
          EndIf
        If DoCrossFade
          xBool2 = TrackerIsLooping()
          If xCrossFadeTimeMN > xCrossFadeTimeMC
            If xCrossFadeTimeEN > xCrossFadeTimeMC
              xCrossFadeTimeMT = xCrossFadeTimeMC
              Else
              xCrossFadeTimeMT = xCrossFadeTimeEN
              EndIf
            ElseIf xCrossFadeTimeEN > xCrossFadeTimeMN
            xCrossFadeTimeMT = xCrossFadeTimeMN
            Else
            xCrossFadeTimeMT = xCrossFadeTimeEN
            EndIf
          If xBool1 Or xBool2
            If NoSFXWait Or xBool2 Or TrackerLoop
              CompilerIf #UseFileLogging
                MainForm_ctConsoleA_AddLog("!Stopped4")
                CompilerEndIf
              MainForm_xEndSong(CanFade, xPStateIconPaused, #False, #False)
              DoCrossFade = #False
              Else
              CompilerIf #UseFileLogging
                MainForm_ctConsoleA_AddLog("  new song too short to crossfade, playing after current song")
                CompilerEndIf
              ctSSLayer_LoadSongAbort(SongPointer(NewSongID))
              EndSongEx()
              xPlayItem_HideAnimAndExit()
              ProcedureReturn #True
              ;Exit Function
              EndIf
            ElseIf Not (NoSFXWait Or xCrossFadeTimeMC = xCrossFadeTimeMT)
            CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  check new timings!")
              MainForm_ctConsoleA_AddLog("  Old  xFadeTime: " + Str(xCrossFadeTimeMC + 2))
              MainForm_ctConsoleA_AddLog("  New  xFadeTime: " + Str(xCrossFadeTimeMN + 2))
              MainForm_ctConsoleA_AddLog("  Fade left time: " + Str(xCrossFadeTimeEN + 2))
              MainForm_ctConsoleA_AddLog("  Used xFadeTime: " + Str(xCrossFadeTimeMT + 2))
              CompilerEndIf
            If CurMusic = #ctSSLayer_MusicTypeTracker And (ctSSLayer_CanUseItem(6) & 4) = 0
              If (xLong2 > CrossFadeMaxPattern(xCrossFadeTimeMT))
                xBool1 = #True
                Else
                xBool1 = #False
                EndIf
              ElseIf Not CurMusic = #ctSSLayer_MusicTypeTracker Or (ctSSLayer_CanUseItem(6) & $1) = $1
              If (xLong2 > CrossFadeMaxPattern(xCrossFadeTimeMT))
                xBool1 = #True
                Else
                xBool1 = #False
                EndIf
              CompilerIf #UseFileLogging
                MainForm_ctConsoleA_AddLog("LengthCur:              " + Str(PLCurSongLength))
                MainForm_ctConsoleA_AddLog("LengthLeftCur:          " + Str(PLCurSongLength - ctSSLayer_GetPosition(SongPointer(CurrentSongID))))
                MainForm_ctConsoleA_AddLog("CrossFadeMinPos:        " + Str(CrossFadeMinPos(xCrossFadeTimeMT)))
                MainForm_ctConsoleA_AddLog("CrossFadeMaxPos:        " + Str(CrossFadeMaxPos(xCrossFadeTimeMT)))
                MainForm_ctConsoleA_AddLog("CrossFadeMinRemainTime: " + Str(CrossFadeMinRemainTime(xCrossFadeTimeMT)))
                MainForm_ctConsoleA_AddLog("Result:                 " + Str(xBool1))
                CompilerEndIf
              EndIf
            If xBool1
              CompilerIf #UseFileLogging
                MainForm_ctConsoleA_AddLog("  new timings!")
                CompilerEndIf
              xCrossFadeTimeMC = xCrossFadeTimeMN
              ctSSLayer_LoadSongAbort(SongPointer(NewSongID))
              ;xSongIsMidi = xSongWasMidi
              EndSongEx()
              SilentPlNext = #False
              xPlayItem_HideAnimAndExit()
              ProcedureReturn #True
              EndIf
            
            ;DoCrossFade = #False
            ;If Not PlaySilent
            ;  xLong1 = xSetVolume
            ;  EndIf
            EndIf
          EndIf

        
        CompilerIf #BoldDirs = 98
          If Not UCase(PLI(PLCurItem)\Filename) = xLastOpenedLogged
            MainForm_ctConsoleA_AddSong(PLI(PLCurItem)\Filename)
            xLastOpenedLogged = UCase(PLI(PLCurItem)\Filename)
            EndIf
          CompilerElse
          If Not UCase(PLIFile(PLCurItem)) = xLastOpenedLogged
            MainForm_ctConsoleA_AddSong(PLIFile(PLCurItem))
            xLastOpenedLogged = UCase(PLIFile(PLCurItem))
            EndIf
          CompilerEndIf
        
        ;ctSSLayer_MoveSongID(#False)
        ;CurrentSongID = NewSongID
        ;NewSongID = Tear_Create()
        If Len(ManualURL) = 0
          PLCurSongLength = xLong1 ; ctSSLayer_SongLength(currentsongid)
          Else
          PLCurSongLength = 100
          EndIf
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  starting playback...")
          CompilerEndIf
        
        
        
        ;prejump = 0
        If Len(ManualURL) = 0 And RandomPosOnTrackerSkipper And (xTrackerSkipper(TempMusic) > 0 Or (IntroModeActive And xRep))
          If Not TempMusic = #ctSSLayer_MusicTypeTracker Or (ctSSLayer_CanUseItem(6) & 4) = 4
            CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  Randomizer:        ")
              MainForm_ctConsoleA_AddLog("    Size:            " + Str(PLCurSongLength))
              MainForm_ctConsoleA_AddLog("    Required (CS 0): " + Str(CrossFadeMinTime(0)))
              If IntroModeActive And xRep
                MainForm_ctConsoleA_AddLog("    IntroTime:       " + Str(IntroModeTime * 1000))
                Else
                MainForm_ctConsoleA_AddLog("    TrackerSkipper:  " + Str(xTrackerSkipper(TempMusic) * 60000))
                EndIf
              CompilerEndIf
            If IntroModeActive And xRep
              xLong1 = PLCurSongLength - (#CrossFadeWaitSeek + IntroModeTime * 1000)
              Else
              xLong1 = PLCurSongLength - (#CrossFadeWaitSeek + xTrackerSkipper(TempMusic) * 60000)
              EndIf
            If xLong1 > CrossFadeMinTime(xCrossFadeTimeM)
              CompilerIf #UseFileLogging
                MainForm_ctConsoleA_AddLog("    ok - still crossfade range")
                MainForm_ctConsoleA_AddLog("    MaxPos           " + Str(CrossFadeMaxPos(xCrossFadeTimeM)))
                MainForm_ctConsoleA_AddLog("    MinPos           " + Str(CrossFadeMinPos(xCrossFadeTimeM)))
                CompilerEndIf
              
              xLong1 = xLong1 - CrossFadeMinPos(xCrossFadeTimeM)
              ;PreJump = CLng((Rnd * 0.92 + 0.03) * xLong1)
              PreJump = URndDnP(xLong1 * 0.92) + 0.03 * xLong1
              CompilerIf #UseFileLogging
                
                MainForm_ctConsoleA_AddLog("    CanSeekBetween   " + Str(xLong1))
                MainForm_ctConsoleA_AddLog("    DefMin=0+ Delay  " + Str(#CrossFadeWaitSeek))
                MainForm_ctConsoleA_AddLog("    DefMax]]+ Delay  " + Str(#CrossFadeWaitSeek + xLong1))
                If IntroModeActive And xRep
                  MainForm_ctConsoleA_AddLog("      When timeout   " + Str(#CrossFadeWaitSeek + xLong1 + IntroModeTime * 1000))
                  Else
                  MainForm_ctConsoleA_AddLog("      When timeout   " + Str(#CrossFadeWaitSeek + xLong1 + xTrackerSkipper(TempMusic) * 60000))
                  EndIf
                MainForm_ctConsoleA_AddLog("      MustNotExeed:  " + Str(PLCurSongLength - CrossFadeMinPos(xCrossFadeTimeM)))
                MainForm_ctConsoleA_AddLog("    Is: -----------> " + Str(PreJump) + " /")
                MainForm_ctConsoleA_AddLog("                     " + Str(xLong1) + " - " + Str(PLCurSongLength))
                CompilerEndIf
              EndIf
            EndIf
          EndIf
        
        ;NewSongID = Tear_Create()
        If xRep = 0
          xLong1 = #True
          Else
          xLong1 = #False
          EndIf
        If PlaySilent Or DoCrossFade
          ;ctSSLayer_LoadSongPlay(NewSongID, 0, (xRep = 0), xModPanning, #False)

          ctSSLayer_LoadSongPlay(SongPointer(NewSongID), 0, xLong1, xModPanning, ResumePaused)
          Tear_Volume(NewSongID) = 0
          Else
          If ResumePaused Or PreJump = 0
            ctSSLayer_LoadSongPlay(SongPointer(NewSongID), xSetVolume, xLong1, xModPanning, ResumePaused)
            Else
            ctSSLayer_LoadSongPlay(SongPointer(NewSongID), 0, xLong1, xModPanning, #False)
            ; only time based!
            ctSSLayer_SeekSong(SongPointer(NewSongID), #CrossFadeWaitSeek + PreJump)
            Tear_Volume(NewSongID) = 0
            Tear_StartDropping(NewSongID, xSongWillBeMidi, 12, 0, #SimpleFadingTotalTime, 1)
            EndIf
          Tear_Volume(NewSongID) = 1
          EndIf
;Stop
        CurrentSongID = NewSongID
        CurMusic = TempMusic
        ClearOldSongInfo()
        If TempMusic = #ctSSLayer_MusicTypeCDAudio
          Tear_IsINet(CurrentSongID) = #False
          CompilerIf #BoldDirs = 98
            PLCurSongDisplay = PLI(PLCurItem)\Caption
            CompilerElse
            PLCurSongDisplay = PLICap(PLCurItem)
            CompilerEndIf
          ElseIf Len(ManualURL) = 0
          Tear_IsINet(CurrentSongID) = #False
          CompilerIf #BoldDirs = 98
            PLCurSongDisplay = PLI(PLCurItem)\Caption
            CompilerElse
            PLCurSongDisplay = PLICap(PLCurItem)
            CompilerEndIf
          Else
          Tear_IsINet(CurrentSongID) = #True
          SenderURL = Mid(ManualURL, FindString(ManualURL + #CR$, #CR$) + 1)
          PLCurSongDisplay = RealURL(SenderURL)
          If Len(PLCurSongDisplay) = 0
            PLCurSongDisplay = RealURL(ManualURL) ;PLCurSongDisplay
            SenderURL = ""
            Else
            SenderURL = Mid(SenderURL, FindString(SenderURL + #CR$, #CR$) + 1)
            SenderURL = RealURL(SenderURL)
            EndIf
          EndIf
        PLCurSongPos = 0
        If Len(ManualURL) = 0
          PLCurSongDisplaySpace = GetTimeFmtMax()
          CompilerIf #BoldDirs = 98
            PLCurSong = PLI(PLCurItem)\Filename
            CompilerElse
            PLCurSong = PLIFile(PLCurItem)
            CompilerEndIf
          Tear_Filename(CurrentSongID) = PLCurSong
          Else
          PLCurSongDisplaySpace = PLCurSongDisplaySpacePerc
          PLCurFullURL = ManualURL
          If (Not Len(PLCurFullURL) = 0)
            xLong1 = #True
            Else
            xLong1 = #False
            EndIf
          MainForm_EnableApiMenu(407, xLong1)
          If Not UrlsAllowed
            xLong1 = #False
            EndIf
          MainForm_EnableApiMenu(408, xLong1)
          Tear_Filename(CurrentSongID) = PLCurFullURL
          EndIf
        Tear_Caption(CurrentSongID) = PLCurSongDisplay
        
        If MP3GetID3Tag Or MP3GetFormat
          MainForm_ReadLate(PLCurSong, #False)
          EndIf
        If xSongWillBeMidi = 3
          xLong1 = #True
          Else
          xLong1 = #False
          EndIf
        GetTimeFmt(xLong1)

        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("AddLastDir")
          CompilerEndIf

        ResetPatternLog()
        If Len(ManualURL) = 0
          CompilerIf #LoudestSongMethode
            xAddLastDir()
            CompilerElse
            If ResumePaused
              xLong1 = #False
              Else
              xLong1 = #True
              EndIf
            xAddLastDir(xLong1) ;#True
            CompilerEndIf
          If xFollowCurSong And PLCurItem < PLCount And PlCount And Not PLCurItem < 0
            If SendMessage_(xListHWnd(2), $190, 0, 0) < 2
              GetListIndexMS(xListHWnd(2), @xLong1)
              If Not PLCurItem = xLong1
                xMarkSong(PLCurItem, #False, #False)
                xFollowCurSongLast = GetTickTimeMS()
                If DoCrossFade
                  xFollowCurSongLastDiff = #CrossFadeWaitSeek + CrossFadeTimeSingle(xCrossFadeTimeMT) + CrossFadeTimeDelay(xCrossFadeTimeMT)
                  Else
                  xFollowCurSongLastDiff = #xFollowCurSongLastDiffDef
                  EndIf
                EndIf
              EndIf
            EndIf
          EndIf
        If DoCrossFade
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("  initializing crossfade tear")
            CompilerEndIf
          If Not TempMusic = #ctSSLayer_MusicTypeTracker Or (ctSSLayer_CanUseItem(6) & 4) = 4
            xLong1 = #CrossFadeWaitSeek + PreJump
            Else
            xLong1 = #CrossFadeWaitSkipPattern
            EndIf
          If Tear_StepT(OldSongID) = 0
            Tear_Volume(OldSongID) = 1
            EndIf
          ;debug "X: ", CrossFadeTimeSingle(xCrossFadeTimeMT), xCrossFadeTimeMT
          If Not Len(ManualURL) = 0
            Goto NoURLSeek
            EndIf
          If ctSSLayer_SeekSong(SongPointer(CurrentSongID), xLong1)
NoURLSeek:
            ;MainForm_ctConsoleA_AddLog("  crossfade tear 1")
            Tear_StartDropping(CurrentSongID, xSongWillBeMidi, 10, 0, CrossFadeTimeSingle(xCrossFadeTimeMT), 1)
            ;MainForm_ctConsoleA_AddLog("  crossfade tear 2")
            Tear_StartDropping(OldSongID, xSongIsMidi, 11, CrossFadeTimeDelay(xCrossFadeTimeMT), CrossFadeTimeSingle(xCrossFadeTimeMT), 0)
            Else
            ;MainForm_ctConsoleA_AddLog("  crossfade tear 1b")
            Tear_StartDropping(CurrentSongID, xSongWillBeMidi, 10, 0, #CrossFadeWaitTime + CrossFadeTimeSingle(xCrossFadeTimeMT), 1)
            ;MainForm_ctConsoleA_AddLog("  crossfade tear 2b")
            Tear_StartDropping(OldSongID, xSongIsMidi, 11, #CrossFadeWaitTime + CrossFadeTimeDelay(xCrossFadeTimeMT), CrossFadeTimeSingle(xCrossFadeTimeMT), 0)
            EndIf
          ;Else
          
          EndIf
        ;MainForm_ctConsoleA_AddLog("  crossfade tear 3")
        xSongIsMidi = xSongWillBeMidi
;        CheckIsRadio
        NewSongID = Tear_Create()
        PLCurSongPos = 0
        PLCurSongLastPos = -1
        xCrossFadeTimeMC = xCrossFadeTimeMN
        
        xResult = #True
        ;MainForm_ctConsoleA_AddLog("  crossfade tear 4")
        MainForm_UpdateMainIcon()
        ;MainForm_ctConsoleA_AddLog("  crossfade tear 5")
        xEndSongTimerEventTime = GetTickTimeMS()
        LastPosTime = xEndSongTimerEventTime
        If NoSFXWait
          ForceLoudestTear = CurrentSongID
          If Not ResumePaused
            ShowIRI()
            EndIf
          Else
          ForceLoudestTear = -1
          EndIf
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  playItem finished")
          CompilerEndIf
        Else
;        If Not xBool1
CompilerIf #PlayLoosingLog
  MainForm_ctConsoleA_AddLog("xPlayItemA(xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
  CompilerEndIf
        CompilerIf #UseFileLogging
          If Len(ManualURL) = 0
            CompilerIf #BoldDirs = 98
              MainForm_ctConsoleA_AddLog("  loading failed (" + PLI(PLCurItem)\Filename + ")")
              CompilerElse
              MainForm_ctConsoleA_AddLog("  loading failed (" + PLIFile(PLCurItem) + ")")
              CompilerEndIf
            Else
            MainForm_ctConsoleA_AddLog("  loading failed (" + RealURL(ManualURL) + ")")
            EndIf
          CompilerEndIf
;          endif
CompilerIf #PlayLoosingLog
  MainForm_ctConsoleA_AddLog("xPlayItemB(xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
  CompilerEndIf
        If Len(ManualURL) = 0
          CheckThisSong(PLCurItem)
          EndIf
        EndIf
      xPlayItem_HideAnimAndExit()
      ProcedureReturn xResult
      Else
      CompilerIf #UseFileLogging
        CompilerIf #BoldDirs = 98
          MainForm_ctConsoleA_AddLog("Current song: " + PLI(PLCurItem)\Filename)
          CompilerElse
          MainForm_ctConsoleA_AddLog("Current song: " + PLIFile(PLCurItem))
          CompilerEndIf
        CompilerEndIf
      xResult = #True
      If xFollowCurSong And PLCurItem < PLCount And PLCount And Not PLCurItem < 0
        If SendMessage_(xListHWnd(2), $190, 0, 0) < 2
          xMarkSong(PLCurItem, #False, #False)
          EndIf
        EndIf
      EndIf
    EndIf
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xPlayItemC(xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
    CompilerEndIf
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  xPlayItem finished")
    CompilerEndIf
  ProcedureReturn xResult
  EndProcedure

Procedure ProcessTimer(TimerEvSetts.s)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.s xChar2
  
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("ShouldDoTimer: " + TimerEvSetts)
    CompilerEndIf
  xLong1 = FindString(TimerEvSetts, "=")
  TimerEvSetts = TimerEvSetts + #TimerSepp
  
  Repeat
    xLong2 = FindString(TimerEvSetts, #TimerSepp, xLong1 + 1)
    If xLong2 = 0
      Break
      EndIf
    xChar2 = Mid(TimerEvSetts, xLong1 + 1, xLong2 - xLong1 - 1)
    xLong3 = FindString(xChar2, ",")
    If xLong3 = 0
      If ProcessTimerEvent(Val(xChar2), "")
        Break ;, TimerIndex) Exit Do
        EndIf
      Else
      ProcessTimerEvent(Val(Left(xChar2, xLong3 - 1)), Trim(Mid(xChar2, xLong3 + 1))) ;, TimerIndex)
      EndIf
    xLong1 = xLong2
    ForEver
  EndProcedure

Procedure xTimerRemove(Index.i)
  For Index = Index To xTimerEvCount - 1
    xTimerEvTime(Index) = xTimerEvTime(Index + 1)
    xTimerEv(Index) = xTimerEv(Index + 1)
    Next
  xTimerEvCount = xTimerEvCount - 1
  EndProcedure

Procedure.i StartWeb(xURL.s, NoAutoResume.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xResult
  Define.i xBool1
  Define.i xBool2
  Define.i xBool3
  Define.s xChar1
  
  If CanIRadio
    If Not (PlayerIsLocked Or xAutoDoing)
      MainForm_LockMe(#True)
      If xPStateIconPlaying
        xBool1 = xPStateIconPaused
        If xGenFading And CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3
          xBool2 = #True
          EndIf
        xPStateIconPaused = #False
        If (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
          xBool3 = #True
          EndIf
        If xProcessMode = 1
          xResult = #True
          Else
          xResult = #False
          EndIf
        xResult = xPlayItem(xGenFading, xBool2, xResult, #True, #False, xURL)
;debug StartWeb, CurMusic, xPStateIconPlaying
        If NoAutoResume And (CurMusic = #ctSSLayer_MusicTypeNone Or Not xResult)
          If CurMusic = #ctSSLayer_MusicTypeNone
            Goto FailPlay
            Else
            xPStateIconPlaying = #True
            xPStateIconPaused = xBool1
            MainForm_UpdateMainIcon()
            Goto CannotRunIt
            EndIf
          EndIf
        If Not xPStateIconPlaying Or CurMusic = #ctSSLayer_MusicTypeNone
          If xBool3 And Not xBool1
            If xProcessMode = 1
              xLong1 = #True
              Else
              xLong1 = #False
              EndIf
            If xPlayItem(xGenFading, xBool2, xLong1, #True, #False, PLCurFullURL)
              If Not CurMusic = #ctSSLayer_MusicTypeNone
                Goto FadeIn
                EndIf
              EndIf
            EndIf
          xPStateIconPlaying = #False
          MainForm_UpdateMainIcon()
          If Not xBool1
            MainForm_LockMe(#False)
            MainForm_xPlayClick(#True)
            EndIf
          Else
FadeIn:
          MainForm_UpdateMainIcon()
          If (xBool2 And Tear_StepT(CurrentSongID) = 0)
            Tear_StartDropping(CurrentSongID, xSongIsMidi, 0, 0, #SimpleFadingTotalTime, 1)
            MainForm_UpdateMainIcon()
            EndIf
          EndIf
        Else
        If Not NoAutoResume
          xReAutoPlay = #True
          EndIf
;MainForm_UpdateMainIcon()
        xChar1 = Mid(xURL, FindString(xURL + #CR$, #CR$) + 1)
        PLCurSongDisplay = RealURL(xChar1)
        If Len(PLCurSongDisplay) = 0
          PLCurSongDisplay = RealURL(xURL)
          If Len(PLCurSongDisplay) = 0
            Goto CannotRunIt
            EndIf
          EndIf
        xPStateIconPlaying = #True
        MainForm_UpdateMainIcon()
        If xPlayItem(#True, #False, #True, #True, #False, xURL)
          If CurMusic = #ctSSLayer_MusicTypeNone
            xPStateIconPlaying = #False
            MainForm_UpdateMainIcon()
            If NoAutoResume
              Goto FailPlay
              EndIf
            Else
            If CurMusic = #ctSSLayer_MusicTypeNone
              xResult = #False
              Else
              xResult = #True
              EndIf
            EndIf
          Else
FailPlay:
          xPStateIconPlaying = #False
          xPStateIconPaused = #False
          MainForm_UpdateMainIcon()
          EndIf
        EndIf
      MainForm_EraseBackground(xStaticIconsHWnd(#xStaticIcons_CurSongPos))
      xEndSongTimerEventTime = GetTickTimeMS()
CannotRunIt:
      MainForm_LockMe(#False)
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure CheckAutoDirs()
  Define.i xLong1
  Define.i xBool1

  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Checking " + Str(xAutoDirHWndCount) + " autorefresh monitor items")
    CompilerEndIf

  For xLong1 = 0 To xAutoDirHWndCount - 1
    If Not xAutoDirHWnd(xLong1) = 0
      If WaitForSingleObject_(xAutoDirHWnd(xLong1), 0) = 0
        FindNextChangeNotification_(xAutoDirHWnd(xLong1))
        xBool1 = #True
        EndIf
      EndIf
    Next
  
  If xBool1
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("  done, changed")
      CompilerEndIf
    MainForm_xAutoRefreshNow(#False, #True, #False, #False, #True)
    CompilerIf #UseFileLogging
    Else
      MainForm_ctConsoleA_AddLog("  done, unchanged")
      CompilerEndIf
    EndIf
  ;ReAutoPlayDR = #False
  ;If Not xAutoDoing Or ForceNow
  ;  LockMe #True
  EndProcedure

Procedure MainForm_eTimerTime()
  ;Define.s xChar1
  Define.i xLong1
  Define.i xLong2
  Define.i xBool1
  ;Dim xBool2 As Boolean
  
    ;On Error Goto 0
  
  
  
    If ShowIRWin
      If IsTickTimeElapsedMS(ShowIRTicks, #ShowIRTicksFull)
        MainForm_HideIRWin()
        EndIf
      EndIf
  
  If CPListMustDo
    If IsTickTimeElapsedMS(CPListTime, #CPListDelay) And Not (PlayerIsLocked Or xAutoDoing)
      MainForm_TrySearch(#False)
      EndIf
    EndIf
  
  If Not xFindNtfy = 0
    If WaitForSingleObject_(xFindNtfy, 0) = 0
      MainForm_XMenuRefresherFileDir() ;(#False)
      FindNextChangeNotification_(xFindNtfy)
      EndIf
    EndIf
  
  If xTimerIsEnabled And xTimerEvCount And Not (xTimerEditing Or PlayerIsLocked Or xAutoDoing)
    GrabError()
    If GetLocalTimeHMS_HS() = xTimerEvTime(0) And Not LastDoneTimer = xTimerEvTime(0) + 1
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Timer event... (timer: " + Str(GetLocalTimeHMS_HS()) + ", xTimerEv(0): " + Str(xTimerEvTime(0)) + ", LastTimer: " + Str(LastDoneTimer - 1) + ")")
        CompilerEndIf
      
      TimerListForm_xLocked = #True
      If InterfaceMode = #Interface_Mode_Timer
        TimerListForm_ApplyLockState()
        EndIf
      
      ProcessTimer(xTimerEv(0))
      
      If xTimerEvIR = 0
        xTimerRemove(0)
        xTimerEvIR = -1
        EndIf
      LastDoneTimer = xTimerEvTime(0) + 1
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Timer event... (Lasttimer changed: " + Str(LastDoneTimer - 1))
        CompilerEndIf
      
      If InterfaceMode = #Interface_Mode_Timer
        TimerListForm_ListUpdate()
        ;frmTimer.mM.Enabled = #True
        ;frmTimer.mF.Enabled = #True
        Else
        MainForm_SetTimerImage()
        EndIf
      TimerListForm_xLocked = #False
      If InterfaceMode = #Interface_Mode_Timer
        TimerListForm_ApplyLockState()
        ;timerlistform_cleanbuttons
        EndIf
      Else
      If IsTickTimeElapsedMS(xTimerTimeTimerTime, 40000)
        GrabError()
        If Not LastDoneTimer = GetLocalTimeHMS_HS() + 1
          LastDoneTimer = GetLocalTimeHMS_HS() + 1
          If InterfaceMode = #Interface_Mode_Timer
            TimerListForm_ListUpdate()
            Else
            ResortTimers()
            EndIf
          Else
          MainForm_SetTimerImage()
          EndIf
        EndIf
      EndIf
    EndIf
  
  CompilerIf #TrayIconViaTimerCheck
    If xTrayIconIndicator Or xTrayIconVisible
      If IsTickTimeElapsedMS(xTrayIconCrashUpdateTimer, #xTrayIconCrashUpdateTimerDelay)
        CompilerIf #UseFileLogging And #DetailLog
          MainForm_ctConsoleA_AddLog("Refreshing systray icon (Explorer may have reloaded)")
          CompilerEndIf
        CompilerIf #TrayIconViaTimerCheck = 2
          Shell_NotifyIcon(1, @SysTrayIcon)
          CompilerElse
          Shell_NotifyIcon(2, @SysTrayIcon)
          Shell_NotifyIcon(0, @SysTrayIcon)
          CompilerEndIf
        xTrayIconCrashUpdateTimer = GetTickTimeMS()
        EndIf
      EndIf
    CompilerEndIf
  
  If xTimerIsEnabled And xPStateIconPlaying And PLCount And xRep And xEndSongTimerEventTime > -1 And (IntroModeActive Or xTrackerSkipper(CurMusic) > 0) And Not ((CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3) Or PlayerIsLocked Or xAutoDoing Or xPStateIconPaused Or CurMusic = #ctSSLayer_MusicTypeNone)
    If IntroModeActive
      If IsTickTimeElapsedMS(xEndSongTimerEventTime, IntroModeTime * 1000)
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("Timer event: Ending song (IntroMode)")
          CompilerEndIf
        xEndSongTimerEventTime = -1
        MainForm_CheckAfter(#True, #False, #True, #False) ; #False , #True
        Goto FinishMark
        EndIf
      EndIf
      ;Else
    If xTrackerSkipper(CurMusic) > 0
      If IsTickTimeElapsedMS(xEndSongTimerEventTime, xTrackerSkipper(CurMusic) * 60000)
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("Timer event: Ending song (End song after ... mins)")
          CompilerEndIf
        xEndSongTimerEventTime = -1
        MainForm_CheckAfter(#True, #False, #False, #True)
        Goto FinishMark
        EndIf
      EndIf
    EndIf
  
  
  
  
  If Not (xAutoDoing Or PlayerIsLocked)
    If NotOutOfSession()
      If OutOfSessionLeft
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("ReEntering session")
          CompilerEndIf
        OutOfSessionLeft = #False
        If xPStateIconPlaying And xPStateIconPaused And OutOfSessionHasPaused
          OutOfSessionHasPaused = #False
          MainForm_xPauseClick()
          EndIf
        OutOfSessionHasPaused = #False
        EndIf
      ElseIf OutOfSessionPause And Not OutOfSessionLeft
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Leaving session")
        CompilerEndIf
      OutOfSessionLeft = #True
      If xPStateIconPlaying And Not xPStateIconPaused
        OutOfSessionHasPaused = #True
        MainForm_xPauseClick()
        Else
        OutOfSessionHasPaused = #False
        EndIf
      EndIf
    
    If xAutoPlayback And xReAutoPlay And Not (xPStateIconPaused Or OutOfSessionHasPaused)
      If xPStateIconPlaying
        xAutoPlaybackLastRetryTime = GetTickTimeMS()
        ElseIf IsTickTimeElapsedMS(xAutoPlaybackLastRetryTime, 60000)
        CompilerIf #UseFileLogging
          If ReAutoPlayDR
            MainForm_ctConsoleA_AddLog("Timer event: Attempting automatic playback (Delayed autorefresh)")
            Else
            MainForm_ctConsoleA_AddLog("Timer event: Attempting automatic playback")
            EndIf
          CompilerEndIf
        If PLCount = 0
          If xAutoDirCount = 0
            xAutoPlaybackLastRetryTime = GetTickTimeMS()
            ReAutoPlayDR = #False
            Goto FinishMark
            Else
            MainForm_xAutoRefreshNow(#False, #True, #False, #False, #False)
            ReAutoPlayDR = #False
            ProcedureReturn 0
            EndIf
          Else
          MainForm_IconsMouseUp(1)
          xAutoPlaybackLastRetryTime = GetTickTimeMS()
          ReAutoPlayDR = #False
          Goto FinishMark
          EndIf
        EndIf
      EndIf
    EndIf
  
  If ReAutoPlayDR And Not (xAutoDoing Or PlayerIsLocked)
    If IsTickTimeElapsedMS(ReAutoPlayDRTime, 60000)
      MainForm_xAutoRefreshNow(#False, #False, #False, #False, #False)
      CheckReplay()
      EndIf
    EndIf
  
  If Not CurMusic = #ctSSLayer_MusicTypeNone
    If (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
      PLCurSongPos = ctSSLayer_GetPosition(SongPointer(CurrentSongID))
  ;    Stop
      If PLCurSongPos > 0 Or xPStateIconPaused
        LastPosTime = GetTickTimeMS()
        ;updatebitrate xLong1
        MainForm_ReadLate("", #True)
        ElseIf IsTickTimeElapsedMS(LastPosTime, #LastPosSkipTimeNetStream)
        If Not StartWeb(PLCurFullURL, #False)
          MainForm_CheckAfter(#False, #False, #False, #False)
          Goto FinishMark
          ;Else
          ;PLCurSongPos = 0
          EndIf
        EndIf
      ;debug "NS: ", xLong1, xLong2
      If PLCurSongPos < 0
        PLCurSongPos = 0
        EndIf
      GetTimeFmt(#True)
      Else
      If xTimerIsEnabled And Not (PlayerIsLocked Or xAutoDoing Or xPStateIconPaused)
        xBool1 = #True
        Else
        xBool1 = #False
        EndIf
      PLCurSongPos = ctSSLayer_GetPosition(SongPointer(CurrentSongID))
      GetTimeFmt(#False)
      If CurMusic = #ctSSLayer_MusicTypeTracker
        If ctSSLayer_MusicHasFinished(SongPointer(CurrentSongID)) And xBool1
          MainForm_CheckAfter(#False, #False, #False, #False)
          Goto FinishMark
          ElseIf (ctSSLayer_CanUseItem(6) & $1) = $1
          If (ctSSLayer_CanUseItem(6) & $4) = $4
            xLong1 = ctSSLayer_MusicGetPattern(SongPointer(CurrentSongID))
            Else
            If xBool1 And xProcessMode = 1 And PLCount And PLCurSongLength > CrossFadeMinPatterns(xCrossFadeTimeMC) And PLCurSongLength - PLCurSongPos <= CrossFadeMinPattern(xCrossFadeTimeMC) And PLCurSongLength - PLCurSongPos >= CrossFadeMaxPattern(xCrossFadeTimeMC) And Not (SilentPlNext Or (xRep = 0 And xSongIsMidi))
              MainForm_CheckAfter(#True, #False, #False, #False)
              Goto FinishMark
              Else
              xLong1 = PLCurSongPos
              ;xLong2 = PLCurSongLength
              EndIf
            EndIf
          
          If Not xLong1 = xModCurPattern
            ;xChar1 = Chr(xLong1)
            xModCurPattern = xLong1
            
            If QuerySetPattern(xLong1)
              TrackerLoop = #True
              If xProcessMode = 1 And xBool1 And xRep And (xAutoDirCount Or PLCount)
                CompilerIf #UseFileLogging
                  ;MainForm_ctConsoleA_AddLog("Tracker looping event, skipping song (bufferlength: " + CStr(Len(xChar1)))
                  CompilerEndIf
                MainForm_CheckAfter(#True, #False, #False, #False)
                Goto FinishMark
                EndIf
              EndIf
            EndIf
  
          If (ctSSLayer_CanUseItem(6) & $D) = $9
            ;pseudorealtimecheck for xfade!
            xLong2 = ctSSLayer_MusicTime(SongPointer(CurrentSongID))
            xLong1 = xLong1 * xLong2
            xLong2 = ctSSLayer_MusicGetPatterns(SongPointer(CurrentSongID)) * xLong2
            If xBool1 And xProcessMode = 1 And xLong2 > CrossFadeMinTime(xCrossFadeTimeMC) And xLong2 - xLong1 <= CrossFadeMinPos(xCrossFadeTimeMC) And xLong2 - xLong1 > CrossFadeMaxPos(xCrossFadeTimeMC) And PLCount And Not (SilentPlNext Or (xRep = 0 And xSongIsMidi))
              MainForm_CheckAfter(#True, #False, #False, #False)
              Goto FinishMark
              EndIf
            EndIf
          EndIf
        EndIf
        
        ; nontracker or tracker with realtimes
      If Not CurMusic = #ctSSLayer_MusicTypeTracker Or (ctSSLayer_CanUseItem(6) & 4) = 4
        If xBool1
          If PLCurSongPos = PLCurSongLength
            MainForm_CheckAfter(#False, #False, #False, #False)
            Goto FinishMark
            ElseIf PLCurSongPos = PLCurSongLastPos
            If IsTickTimeElapsedMS(LastPosTime, #LastPosSkipTime)
              MainForm_CheckAfter(#False, #False, #False, #False)
              Goto FinishMark
              EndIf
            EndIf
          EndIf
        
        PLCurSongLastPos = PLCurSongPos
        LastPosTime = GetTickTimeMS()
        If xBool1 And xProcessMode = 1 And PLCurSongLength > CrossFadeMinTime(xCrossFadeTimeMC) And PLCurSongLength - PLCurSongPos <= CrossFadeMinPos(xCrossFadeTimeMC) And PLCurSongLength - PLCurSongPos > CrossFadeMaxPos(xCrossFadeTimeMC) And PLCount And Not (SilentPlNext Or (xRep = 0 And xSongIsMidi))
          MainForm_CheckAfter(#True, #False, #False, #False)
          EndIf
        EndIf
    ;    endif
      EndIf
    EndIf
    
  FinishMark:
  If xAutoRefreshTimer(1) > 0
    If IsTickTimeElapsedMS(xAutoRefreshTimerEventTime(1), xAutoRefreshTimer(1) * 60000)
      CheckAutoDirs()
      xAutoRefreshTimerEventTime(1) = GetTickTimeMS()
      EndIf
    EndIf
  If xAutoRefreshTimer(0) > 0
    If IsTickTimeElapsedMS(xAutoRefreshTimerEventTime(0), xAutoRefreshTimer(0) * 60000)
      MainForm_xAutoRefreshNow(#False, #False, #False, #False, #False)
      EndIf
    EndIf
  ;DoEvents()
  EndProcedure

Procedure.i xFindNextItem(xStep.i, DontPlay.i, CanFade.i, FindPLOnly.i, DoCrossFade.i)
  Define.i xResult
  Define.i xLong1
  Define.i xLong2
  Define.i xBool1
  ;compilerif #TryPreventReInit
    ;Dim xBool1 As Boolean
   ; compilerendif
  
  CompilerIf #TryPreventReInit
  Define.i xTPRI_Reloop.i
  
  Lb1:
    CompilerEndIf
  
  If Not PLCount = 0
    If FindPLOnly
      GetListIndexMS(xListHWnd(2), @xLong1)
      If xLong1 = -1
        xLong1 = 0
        EndIf
      EndIf
    xLastSkipDirection = xStep
  
    xLong2 = GetTickTimeMS()
    Repeat
      If xRep = 2
        xLong1 = RandomSong()
        ElseIf FindPLOnly
        xLong1 = (xLong1 + xStep + PLCount) % PLCount
        Else
        xLong1 = (PLCurItem + xStep + PLCount) % PLCount
        EndIf
      If FindPLOnly
  CompilerIf #BoldDirs = 98
        If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = 0
  CompilerElse
        If (PLIDF(xLong1) & #PLI_IsDir) = 0
  CompilerEndIf
          xResult = xLong1
          Break ;Function
          EndIf
        Else
        If xLong1 = 0 And xProcessMode = 2 And xRep = 1 And Not CanFade
          If xPStateIconPlaying
  ;        If Not DoCrossFade
            MainForm_LockMe(#True)
            MainForm_xEndSong(CanFade, xPStateIconPaused, #False, #False)
            MainForm_LockMe(#False)
  ;MainForm_ctConsoleA_AddLog("xFindNextItem (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xFindNextItem1")
    CompilerEndIf
            xPStateIconPlaying = #False
            MainForm_UpdateMainIcon()
            EndIf
          If Not PlNextSong = ""
            SetNextSong(#False)
            EndIf
          Break ;Function
          Else
          PLCurItem = xLong1
          EndIf
        
  CompilerIf #BoldDirs = 98
        If (PLI(PLCurItem)\DirDepthFlags & #PLI_IsDir) = 0
  CompilerElse
        If (PLIDF(PLCurItem) & #PLI_IsDir) = 0
  CompilerEndIf
          If Not DontPlay
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xFindNextItemA (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
    CompilerEndIf
              If xPlayItem(CanFade, #False, DoCrossFade, CanFade, #False, "")
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xFindNextItemB (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
    CompilerEndIf
              ;;;;;; userdoes is same as canfade
              ;;;;;; (actually, it canfage is (userdoes and forcefadeout), but if forcefadeout,
              ;;;;;; docrossfade is now #False to prevent crossfade
              ;;;;;; sending canfade (userdoes) as NoSFXWait to prevent waiting for old song on crossfade
              Break
              EndIf
            Else
            If xFollowCurSong And PLCount And PLCurItem < PLCount And SendMessage_(xListHWnd(2), $190, 0, 0) < 2 And Not (PLCurItem < 0)
              xMarkSong(PLCurItem, #False, #False)
              xFollowCurSongLast = GetTickTimeMS()
              xFollowCurSongLastDiff = #xFollowCurSongLastDiffDef
              EndIf
            Break
            EndIf
          EndIf
        EndIf
      CompilerIf #TryPreventReInit
        If IsTickTimeElapsedMS(xLong2, CannotPlayAbortTime) Or xBool1
          If Not (xPStateIconPlaying Or xBool1)
            If FSOUND_GetError = SndBusy
              OutputChange #False
              xBool1 = #True
              xTPRI_Reloop = #True
              Break
              EndIf
            EndIf
          EndIf
        CompilerElse
      If IsTickTimeElapsedMS(xLong2, #CannotPlayAbortTime)
          CompilerEndIf
  
        If xBool1
          If CurMusic = #ctSSLayer_MusicTypeNone
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xFindNextItem2")
    CompilerEndIf
            xPStateIconPlaying = #False
            MainForm_UpdateMainIcon()
            EndIf
          If Not PlNextSong = ""
            SetNextSong(#False)
            EndIf
          Break
          Else
          xBool1 = #True
          EndIf
        EndIf
      If PLCount = 0
        ;1.00 beta 52 (endinging with crossfade will not stop properly if playlist gets empty)
        ;from:
        ;If Not DoCrossFade
        ;to:
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xFindNextItemC (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
    CompilerEndIf
        If (CurMusic = #ctSSLayer_MusicTypeNone) And Not DoCrossFade
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xFindNextItem3")
    CompilerEndIf
          xPStateIconPlaying = #False
          MainForm_UpdateMainIcon()
          EndIf
        If Not PlNextSong = ""
          SetNextSong(#False)
          EndIf
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("xFindNextItemD (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
    CompilerEndIf
        Break ;Function
        EndIf
      ForEver

    CompilerIf #TryPreventReInit
      If xTPRI_Reloop
        xTPRI_Reloop = #False
        Goto Lb1
        EndIf
      CompilerEndIf

    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure xDeleteFileNow(DeleteCurrentSong.i)
  Define.SHFILEOPSTRUCT xType1
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  ;Dim xLong5.i
  ;Dim xLong6.i
  ;Dim xLong7.i
  ;Dim xLong8.i
  ;define.s xChar1
  Define.s xChar2
  Define.s xChar3
  Define.s xChar4
  Define.i xBool1
  Define.i xBool2
  Define.i xCaret
  Define.i xCaretOld
  Define.i hBuff

  If xDelMode And IsTickTimeElapsedMS(xFollowCurSongLast, xFollowCurSongLastDiff) And Not (PlayerIsLocked Or xAutoDoing Or xSecureMode)
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Deleting files")
      MainForm_ctConsoleA_AddLog("  Preparing to delete files")
      CompilerEndIf

    MainForm_LockMe(#True)
    xChar2 = UCase(PLCurSong)
    xChar3 = UCase(PlNextSong)
    hBuff = BinaryBuffer_Create()
    If hBuff
      If DeleteCurrentSong
        If IsFileExists(PLCurSong) And Not (AllTears_TypesCount > 2 Or PLCurSong = "" Or CurMusic = #ctSSLayer_MusicTypeNone)
          xBool1 = #True
          CompilerIf #PB_Compiler_Unicode
            BinaryBuffer_WriteMemEx(hBuff, @PLCurSong, Len(PLCurSong) << 1)
            BinaryBuffer_WriteMemEx(hBuff, @xLong1, 2)
            CompilerElse
            BinaryBuffer_WriteMemEx(hBuff, @PLCurSong, Len(PLCurSong))
            BinaryBuffer_WriteMemEx(hBuff, @xLong1, 1)
            CompilerEndIf
          sCharA1(0) = UCase(PLCurSong)
          xLong1 = 1
          If xChar2 = xChar3
            SetNextSong(#False)
            EndIf
          EndIf
        Else
        For xLong2 = 0 To PLCount - 1
  CompilerIf #BoldDirs = 98
          If (PLI(xLong2)\DirDepthFlags & #PLI_IsDir) = 0
  CompilerElse
          If (PLIDF(xLong2) & #PLI_IsDir) = 0
  CompilerEndIf
            If SendMessage_(xListHWnd(2), #LB_GETSEL, xLong2, 0)
  CompilerIf #BoldDirs = 98
              sCharA1(xLong1) = PLI(xLong2)\Filename
              If Not SendMessage_(xListHWnd(2), #LB_GETITEMDATA, xLong1, 0) = xLong1
  CompilerElse
              sCharA1(xLong1) = PLIFile(xLong2)
              If Not SendMessage_(xListHWnd(2), #LB_GETITEMDATA, xLong1, 0) = xLong1
  CompilerEndIf
                xChar2 = "Playlist is out of sync, please report this error." + #CR$ + "Deleting is aborted"
                MessageBox_(MainHWnd, @xChar2, @"Warning", #MB_ICONEXCLAMATION)
                MainForm_LockMe(#False)
                ProcedureReturn
                EndIf
              For xLong3 = 0 To xLong1 - 1
                If sCharA1(xLong3) = UCase(sCharA1(xLong1))
                  sCharA1(xLong1) = ""
                  Break
                  EndIf
                Next
              If Not sCharA1(xLong1) = ""
                xLong3 = 0
                CompilerIf #PB_Compiler_Unicode
                  BinaryBuffer_WriteMemEx(hBuff, @sCharA1(xLong1), Len(sCharA1(xLong1)) << 1)
                  BinaryBuffer_WriteMemEx(hBuff, @xLong3, 2)
                  CompilerElse
                  BinaryBuffer_WriteMemEx(hBuff, @sCharA1(xLong1), Len(sCharA1(xLong1)))
                  BinaryBuffer_WriteMemEx(hBuff, @xLong3, 1)
                  CompilerEndIf
                sCharA1(xLong1) = UCase(sCharA1(xLong1))
                If xChar2 = sCharA1(xLong1)
                  xBool1 = #True
                  EndIf
                If xChar3 = sCharA1(xLong1) And Not xChar3 = ""
                  SetNextSong(#False)
                  xChar3 = ""
                  EndIf
                xLong1 = xLong1 + 1
                EndIf
              EndIf
            EndIf
          Next
        If (CurMusic = #ctSSLayer_MusicTypeNone)
          xBool1 = #False
          EndIf
        EndIf
    
  CompilerIf #UseFileLogging
      If xLong1 = 0
        MainForm_ctConsoleA_AddLog("  no files found")
        Else
  CompilerElse
      If xLong1
  CompilerEndIf
        xPStateIconDeleting = #True
        MainForm_UpdateMainIcon()
        
        
        xForceAnimationNow = #True
        If xBool1 Or CurMusic = #ctSSLayer_MusicTypeNone ;And xPStateIconPlaying
          If xBool1
            StoreResume(#False, 500)
            EndIf
          Tear_WaitFor(-2)
          Else
          Tear_WaitFor(-3)
          EndIf
        
        xType1\wFunc = $3
        xType1\fFlags = $40 ; $C0
        

        xLong1 = 0
        CompilerIf #PB_Compiler_Unicode
          BinaryBuffer_WriteMemEx(hBuff, @xLong1, 2)
          CompilerElse
          BinaryBuffer_WriteMemEx(hBuff, @xLong1, 1)
          CompilerEndIf

        xType1\pFrom = BinaryBuffer_GetMemPtr(hBuff)
        DoEventsEx_SleepPeriodicalLW(0)
        
        
        
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  Deleting from medium")
          CompilerEndIf
  
  
        If xType1\pFrom
          SHFileOperation_(@xType1)
          EndIf
        DoEventsEx_SleepPeriodicalLW(0)
        
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  returned " + Str(xType1\fAnyOperationsAborted))
          CompilerEndIf
        
        xForceAnimationNow = #False
        
        xLong3 = xLong1 - 1
        xLong1 = 0
        For xLong2 = 0 To xLong3
          If Not IsFileExists(sCharA1(xLong2))
            sCharA1(xLong1) = sCharA1(xLong2)
            xLong1 = xLong1 + 1
            EndIf
          Next
        If Not xLong1 = 0
          xLong2 = PLCount - 1
          PLCount = 0
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("  Removing from list")
            CompilerEndIf
  
          SetAutoDoing(#True)
          
          
          xChar4 = UCase(PLCurSong)
          xCaret = SendMessage_(xListHWnd(2), #LB_GETCARETINDEX, 0, 0)
          xCaretOld = xCaret
          xLong4 = xLong2
          For xLong2 = 0 To xLong4
            CompilerIf #BoldDirs = 98
              xChar3 = UCase(PLI(xLong2)\Filename)
              CompilerElse
              xChar3 = UCase(PLIFile(xLong2))
              CompilerEndIf
            If PLCurItem = xLong2
              PLCurItem = PLCount ;: xBool2 = #True
              EndIf
            ;If UCase(PLCurSong) = xChar3
              ;xBool2 = #True
              ;EndIf
            If xChar3 = ""
              CompilerIf #BoldDirs = 98
                CopyStructureEx(PLI(xLong2), PLI(PLCount), tPlaylistItem)
                SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
                CompilerElse
                PLIFile(PLCount) = PLIFile(xLong2)
                PLICap(PLCount) = PLICap(xLong2)
                PLIDF(PLCount) = PLIDF(xLong2)
                PLIPxLg(PLCount) = PLIPxLg(xLong2)
                PLIPxSm(PLCount) = PLIPxSm(xLong2)
                SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
                CompilerEndIf
              If PLNext = xLong2
                PLNext = PLCount
                EndIf
              PLCount = PLCount + 1
              Else
              For xLong3 = 0 To xLong1 - 1
                If Len(xChar3) = Len(sCharA1(xLong3))
                  If xChar3 = sCharA1(xLong3)
                    If xChar4 = xChar3
                      xBool2 = #True
                      EndIf
                    xChar3 = ""
                    If PLNext = xLong2 And Not PlNextSong = ""
                      SetNextSong(#False)
                      EndIf
                    ;RemoveListItemMS
                    RemoveFromSearch(PLCount)
                    ;PLRemoveShifted1 = PLCount
                    ;PLRemoveShifted2 = xLong2
                    SendMessage_(xListHWnd(2), #LB_DELETESTRING, PLCount, 0) ;PLCount + 1
                    If xCaret >= PLCount
                      xCaret = xCaret - 1
                      EndIf
                    Break
                    EndIf
                  EndIf
                If xLong3 % $7f = 0
                  DoEventsEx_SleepPeriodicalLW(0)
                  EndIf
                Next
              ;PLRemoveShifted1 = $7FFFFFFF
  
              If Not xChar3 = ""
                CompilerIf #BoldDirs = 98
                  CopyStructureEx(PLI(xLong2), PLI(PLCount), tPlaylistItem)
                  SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
                  CompilerElse
                  PLIFile(PLCount) = PLIFile(xLong2)
                  PLICap(PLCount) = PLICap(xLong2)
                  PLIDF(PLCount) = PLIDF(xLong2)
                  PLIPxLg(PLCount) = PLIPxLg(xLong2)
                  PLIPxSm(PLCount) = PLIPxSm(xLong2)
                  SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
                  CompilerEndIf
                If PLNext = xLong2
                  PLNext = PLCount
                  EndIf
                PLCount = PLCount + 1
                EndIf
              EndIf
            Next
          
          If Not (PLCount = 0 Or xCaret = xCaretOld)
            If xCaret > PLCount - 1
              xCaret = PLCount - 1
              EndIf
            If xCaret < 0
              xCaret = 0
              EndIf
            SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xCaret, 0)
            EndIf
          
          CheckEmptyNodes(#False, -1)
          SetAutoDoing(#False)
          
          MainForm_xBuildDirs()
          CheckOldItems()
          EndIf
  
        xPStateIconDeleting = #False
        MainForm_UpdateMainIcon()
  
  
  
  
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  post processing")
          CompilerEndIf
        If xBool1
          If xBool2
            StoreResume(#True, 1)
            Else
            StoreResume(#True, 0)
            EndIf
          EndIf
        EndIf
      BinaryBuffer_Discard(hBuff)
      EndIf
    MainForm_LockMe(#False)
    EndIf
  EndProcedure

Procedure MainForm_xSelDirNow()
  Define.i xLong1
  Define.i xLong2

  If Not PLCount = 0
    xLong1 = SendMessage_(xListHWnd(0), #LB_GETCURSEL, 0, 0)
    If Not xLong1 = -1
      xLong2 = xDirPath(xLong1)
      If xLong1 < PLCount And PLCount > 1
        xMarkSong(PLCount - 1, #True, #True)
        xMarkSong(xLong2, #False, #True)
        MainForm_CheckDir(#False, #True)
  ;      eLabel(8)\Caption = eDropDown(0).List(xLong1)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_TearIconChance()
  CompilerIf #TrayXFadeIcon
    If Not ShowIR_IconHWnd2 = 0
      If AllTears_TypesCount > 2 And Not CurMusic = #ctSSLayer_MusicTypeNone
        ShowIR_IconHWnd = ShowIR_IconHWnd2
        Else
        ShowIR_IconHWnd = ShowIR_IconHWnd1
        EndIf
      If ShowIRWin
        ShowIR_Do(#True)
        EndIf
      EndIf
    MainForm_UpdateMainIcon()
    CompilerElse
    Stop
    UpdateAnimIcon
    CompilerEndIf
  EndProcedure

Procedure MainForm_RemoverX(PrevSkip.i)
  Define.i xLong2
  Define.i xLong3
  
  ;Do While xAutoDoing: DoEvents(): Loop
  If xAutoDoing
    MessageBox_(MainHWnd, @"Error 24.23", @"Warning", #MB_ICONEXCLAMATION)
    ProcedureReturn
    EndIf
  xLong2 = xFindSong()
  If Not xLong2 = 0
    RemoveFromSearch(xLong2)
    RemoveListItemMS(xListHWnd(2), xLong2)
    For xLong3 = xLong2 To PLCount - 2
      CompilerIf #BoldDirs = 98
        CopyStructureEx(PLI(xLong3 + 1), PLI(xLong3), tPlaylistItem)
        SendMessage_(xListHWnd(2), $19A, xLong3, xLong3)
        CompilerElse
        PLIFile(xLong3) = PLIFile(xLong3 + 1)
        PLICap(xLong3) = PLICap(xLong3 + 1)
        PLIDF(xLong3) = PLIDF(xLong3 + 1)
        PLIPxLg(xLong3) = PLIPxLg(xLong3 + 1)
        PLIPxSm(xLong3) = PLIPxSm(xLong3 + 1)
        SendMessage_(xListHWnd(2), $19A, xLong3, xLong3)
        CompilerEndIf
      Next
    PLCount = PLCount - 1
    If Not (PLCurItem = 0 Or PLCurItem < xLong2 Or PrevSkip)
      PLCurItem = PLCurItem - 1
      EndIf
    If Not PlNextSong = ""
      If PLNext > xLong2
        PLNext = PLNext - 1
        Else
        If PLNext = xLong2
          SetNextSong(#False)
          EndIf
        EndIf
      EndIf
    CheckEmptyNodes(#False, xLong2) ;- 1
    EndIf
  If PLCount = 0 And xAutoDirCount
    MainForm_xAutoRefreshNow(#False, #False, #False, #False, #False)
    EndIf
  EndProcedure

Procedure MainForm_CheckAfter(CanFade.i, NoStopSong.i, UserDoes.i, EnforceUserDoes.i)
  Define.i xLong1
  
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Postprocessing song")
    CompilerEndIf
  xTimerIsEnabled = #False
  If xRemovePlayedSongs And Not (xRep Or UserDoes Or (PLNext = PLCurItem And Len(PlNextSong)))
    MainForm_RemoverX(#False)
    EndIf
  
  If PLCount = 0 And xAutoDirCount
    MainForm_xAutoRefreshNow(#False, #False, #False, #True, #False)
    EndIf
  
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("CheckAfter (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", xCurMusic=" + CStr(CurMusic) + ")")
    CompilerEndIf
  
  If PLCount = 0
    CompilerIf #PlayLoosingLog
      MainForm_ctConsoleA_AddLog("CheckAfterX")
      CompilerEndIf
    MainForm_LockMe(#True)
    If Not CurMusic = #ctSSLayer_MusicTypeNone
      If CanFade And Not xPStateIconPaused
        MainForm_xEndSong(#True, #False, #False, #False)
        Else
        MainForm_xEndSong(#False, #False, #False, #False)
        EndIf
      EndIf
    xPStateIconPlaying = #False
    xPStateIconPaused = #False
    ;xReAutoPlay = #False
    ;ReAutoPlayDR = #False
    MainForm_UpdateMainIcon()
    MainForm_LockMe(#False)
  
    Else
    If xProcessMode = 0 And Not (xRep Or CanFade Or UserDoes Or xPStateIconPaused) And xPStateIconPlaying And PlNextSong = ""
  CompilerIf #PlayLoosingLog
    MainForm_ctConsoleA_AddLog("CheckAfter0")
    CompilerEndIf
      xLong1 = xFindSong()
      If Not xLong1 = 0
        PLCurItem = xLong1
        If CanFade
          MainForm_xPlayClick(#False)
          Else
          MainForm_xPlayClick(#True)
          EndIf
        If Not SendMessage_(xListHWnd(2), $190, 0, 0) > 1
          xMarkSong(xLong1, #False, #False)
          xFollowCurSongLast = GetTickTimeMS()
          xFollowCurSongLastDiff = #xFollowCurSongLastDiffDef
          EndIf
        xTimerIsEnabled = #True
        ProcedureReturn
        EndIf
      EndIf
    
    If EnforceUserDoes
      UserDoes = #True
      EndIf
    
    If xProcessMode = 1 And CanFade
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("CheckAfter1pre (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
        CompilerEndIf
      MainForm_PlayNext(UserDoes, 1, CanFade, #False)
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("CheckAfter1post (xPStateIconPlaying=" + CStr(xPStateIconPlaying) + ", CurMusic=" + CStr(CurMusic) + ")")
        CompilerEndIf
      ElseIf xProcessMode = 3 And Not NoStopSong
      MainForm_LockMe(#True)
      xReAutoPlay = #False
      ReAutoPlayDR = #False
      xPStateIconPlaying = #False
      MainForm_UpdateMainIcon()
      MainForm_LockMe(#False)
      MainForm_PlayNext(#False, 1, #False, #False)
      If Not CurMusic = #ctSSLayer_MusicTypeNone
        MainForm_LockMe(#True)
        MainForm_xEndSong(CanFade, xPStateIconPaused, #False, #False)
        MainForm_LockMe(#False)
        EndIf
      ElseIf xProcessMode = 2
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("CheckAfter2")
        CompilerEndIf
      MainForm_LockMe(#True)
      If Not CurMusic = #ctSSLayer_MusicTypeNone
        MainForm_xEndSong(CanFade, xPStateIconPaused, #False, #False)
        EndIf
      If Not vKioskMode
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def3, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $12000000)
        EndIf
      Tear_WaitFor(-2)
      DoEventsEx(2500)
      If Not vKioskMode
        MainForm_DrawRawBMP_CalaymStatic(#xStaticIcons_Def3, *DynButtonsResXDefBMP, DynButtonsResXDefLen, $2000000)
        EndIf
      MainForm_LockMe(#False)
      ;PlayNext UserDoes, 1, #False, #False
      MainForm_PlayNext(#False, 1, #False, #False)
      Else
      CompilerIf #PlayLoosingLog
        MainForm_ctConsoleA_AddLog("CheckAfter3")
        CompilerEndIf
      xPStateIconPaused = #False
      MainForm_UpdateMainIcon()
      MainForm_PlayNext(#False, 1, #False, CanFade)
      EndIf
    EndIf
  
  xTimerIsEnabled = #True
  EndProcedure

Procedure xTrackSeekA(xStep.i)
  Define.i xLong1

  If IsTickTimeElapsedMS(xGUIClickDelayTimer, 200) And Not (PlayerIsLocked Or CurMusic = #ctSSLayer_MusicTypeNone)
    xGUIClickDelayTimer = GetTickTimeMS()
  
    xLong1 = ctSSLayer_GetPosition(SongPointer(CurrentSongID))
    If CurMusic = #ctSSLayer_MusicTypeTracker And (ctSSLayer_CanUseItem(6) & 4) = 0
      xLong1 = xLong1 + xStep
      Else
      xLong1 = xLong1 + MulDiv_(xStep, PLCurSongLength, 16)
      EndIf
    If xLong1 > PLCurSongLength
      xLong1 = PLCurSongLength
      EndIf
    If xLong1 < 0
      xLong1 = 0
      EndIf
    If xLong1 < PLCurSongLength
      ctSSLayer_SeekSong(SongPointer(CurrentSongID), xLong1)
      If CurMusic = #ctSSLayer_MusicTypeTracker
        ;xModCurPattern = -1
        ResetPatternLog()
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure AddLastSongsToPL()
  Define.i xLong1
  Define.i xLong2
  ;define.i xLong3
  
  ;Me.Visible = #False
  ;DoEvents()
  
  SetAutoDoing(#True)
  xPStateIconRefreshing = #True
  MainForm_UpdateMainIcon()
  For xLong1 = 0 To xLastPathCount - 1
    If AllowedItem(xLastPath(xLong1), #True) = 1
      sCharA1(xLong2) = xLastPath(xLong1)
      xLong2 = xLong2 + 1
      EndIf
    Next
  If Not xLong2 = 0
    GenCalaymStructure(#False, xLong2, #False)
    SetAutoDoing(#False)
    xMarkSong(xLong2, #False, #False)
    xPStateIconRefreshing = #False
    MainForm_UpdateMainIcon()
    SetAutoDoing(#False)
    CheckReplay()
    EndIf
  EndProcedure

Procedure.i MainForm_xLastDirNow(Force.i)
  ;Define.i xResult
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  
  ;Me.Visible = #False
  ;DoEvents()
  
  If PLCount
    xLong2 = SendMessage_(xListHWnd(1), #LB_GETCURSEL, 0, 0)
    If Not xLong2 = -1
      xLong1 = xFindSong(xLastPath(xLong2))
      If xLong1 And xLong1 < PLCount And PLCount > 1
        xMarkSong(PLCount - 1, #True, #False)
        xMarkSong(xLong1, #False, #False)
        ProcedureReturn #True
        EndIf
      EndIf
    EndIf
  
  If Force And Not vKioskMode
    xChar1 = LCase(xLastPath(xLong2))
    For xLong1 = 0 To xLastPathCount - 1
      If LCase(xLastPath(xLong1)) = xChar1
        If AllowedItem(xLastPath(xLong2), #True) = 1
          AddLastSongsToPL()
          MainForm_xLastDirNow(#False)
          ProcedureReturn #True
          EndIf
        ProcedureReturn #False
        EndIf
      Next
    If AllowedItem(xLastPath(xLong2), #True) = 1
      CompilerIf #BoldDirs = 98
        PLI(PLCount)\Filename = SimpleDir(xLastPath(xLong2))
        PLI(PLCount)\Caption = PLI(PLCount)\Filename
        PLI(PLCount)\DirDepthFlags = #PLI_IsDir ;or 0
        PLCount = PLCount + 1
        PLI(PLCount)\Filename = xLastPath(xLong2)
        PLI(PLCount)\Caption = xLastPathCap(xLong2)
        PLI(PLCount)\DirDepthFlags = 1
        CompilerElse
        PLIFile(PLCount) = SimpleDir(xLastPath(xLong2))
        PLICap(PLCount) = PLIFile(PLCount)
        PLIDF(PLCount) = #PLI_IsDir ;or 0
        PLCount = PLCount + 1
        PLIFile(PLCount) = xLastPath(xLong2)
        PLICap(PLCount) = xLastPathCap(xLong2)
        PLIDF(PLCount) = 1
        CompilerEndIf
      PLCount = PLCount + 1
      RealPLAdd(PLCount - 2)
      EndIf
    EndIf
  
  ;ProcedureReturn xResult
  EndProcedure

Procedure MainForm_xLastDirNot()
  Define.i xLong1
  
  For xLong1 = 0 To xLastPathCount - 1 ;eDropDown(1).ListCount - 1
    If xLastPath(xLong1) = PLCurSong
      SendMessage_(xListHWnd(1), #LB_SETCURSEL, xLong1, 0)
      Break
      EndIf
    Next
  EndProcedure

Procedure ShowIRI()
  CompilerIf #FlatCastCF17
    xFCI.Text0 = PLCurSongDisplay
    CompilerEndIf
  
  If (xTitlesWhenMinimized = 2 Or (xTitlesWhenMinimized = 1 And (IsIconic_(MainHWnd) Or xTrayIconIndicator))) And Not (xPStateIconSndcard Or xPStateIconQuit)
    ShowIR_Do(#False)
    ElseIf ShowIRWin
    ShowIR_Do(#True)
    EndIf
  EndProcedure

Procedure DirListEvent(Index.i, ForceCont.i)
  
  If InterfaceMode = #Interface_Mode_Wizard
    ToggleInterface(#Interface_Mode_None)
    If Not ForceCont
      ProcedureReturn
      EndIf
    EndIf
  Select Index
    Case 0, 1, 2, 3 ; set combo / top / left
      SetAutoDirVar(Index)
    Case 5 ; toggle modes
      SetAutoDirVar((xDirListModeCur + 2) % 3)
    Case 8
      If xDirListModeCur = 1
        If Not xDirListTopHeight = #xDirListMinTH
          xDirListTopHeight = xDirListTopHeight - 1
          MainForm_EnableApiMenu(429, #True)
          If xDirListTopHeight = #xDirListMinTH
            MainForm_EnableApiMenu(428, #False)
            Else
            MainForm_EnableApiMenu(428, #True)
            EndIf
          MainForm_ResizePlayer(#False)
          EndIf
        ElseIf xDirListModeCur = 2
        If Not xDirListLeftWidth = #xDirListMinLW
          xDirListLeftWidth = xDirListLeftWidth - 1
          MainForm_EnableApiMenu(429, #True)
          If xDirListLeftWidth = #xDirListMinLW
            MainForm_EnableApiMenu(428, #False)
            Else
            MainForm_EnableApiMenu(428, #True)
            EndIf
          MainForm_ResizePlayer(#False)
          EndIf
        EndIf
    Case 9
      If xDirListModeCur = 1
        If Not xDirListTopHeight = #xDirListMaxTH
          xDirListTopHeight = xDirListTopHeight + 1
          If xDirListTopHeight = #xDirListMaxTH
            MainForm_EnableApiMenu(429, #False)
            Else
            MainForm_EnableApiMenu(429, #True)
            EndIf
          MainForm_EnableApiMenu(428, #True)
          MainForm_ResizePlayer(#False)
          EndIf
        ElseIf xDirListModeCur = 2
        If Not xDirListLeftWidth = #xDirListMaxLW
          xDirListLeftWidth = xDirListLeftWidth + 1
          If xDirListLeftWidth = #xDirListMaxLW
            MainForm_EnableApiMenu(429, #False)
            Else
            MainForm_EnableApiMenu(429, #True)
            EndIf
          MainForm_EnableApiMenu(428, #True)
          MainForm_ResizePlayer(#False)
          EndIf
        EndIf
    EndSelect
    ;xDirList = #True
  EndProcedure

Procedure AutoRefreshHandler(Index.i)
  Define.i xLong1

  If Not (xAutoDirCount = 0 Or PlayerIsLocked Or xAutoDoing) ;Or vKioskMode)
    SetAutoDoing(#True)
    xPStateIconRefreshing = #True
    If Index = 4 And xPStateIconPlaying
      xLong1 = xFindSong()
CompilerIf #BoldDirs = 98
      If xLong1 = 0 Or (PLI(xLong1)\DirDepthFlags & #PLI_IsAuto) = #PLI_IsAuto
CompilerElse
      If xLong1 = 0 Or (PLIDF(xLong1) & #PLI_IsAuto) = #PLI_IsAuto
CompilerEndIf
        xPStateIconPlaying = #False
        MainForm_LockMe(#True)
        MainForm_xEndSong(#True, xPStateIconPaused, #False, #False)
        MainForm_LockMe(#False)
        EndIf
      EndIf
      
    If Index = 2
      xRemoveAutoRefresh(#PLI_IsAuto, #True, #False)
      Else
      xRemoveAutoRefresh(0, #True, #False)
      EndIf
    ClearOverload()
    ClearPLEx()
    RealPLAdd(0)
    xPStateIconRefreshing = #False
    SetAutoDoing(#False)
    InitResearch(#False)
    xLong1 = xFindSong()
    If Not xLong1 = 0
      PLCurItem = xLong1
      xMarkSong(xLong1, #True, #False)
      EndIf
    If Index = 4
      ReAutoPlayDRTime = GetTickTimeMS()
      ReAutoPlayDR = #True
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_SaveTimers(xHWnd.i, Filename.s, Silent.i)
  Define.i xLong1
  Define.i xBool1
  Define.i hFile
  
  If Not xTimerEvCount = 0
    If xTimerEvCount = 1 And Not xTimerEvIR = -1
      If Silent
        ProcedureReturn
        Else
        If CalaymMessageBox(xHWnd, LoadResString(1612), LoadResString(1601), 68) = #IDYES
          xBool1 = #True
          Else ;If xTimerEvCount = 1
          ProcedureReturn
          EndIf
        EndIf
      EndIf
    If Len(Filename) = 0
      Filename = CalaymSaveSingleFile(LoadResString(1605) + #FileFilterVBNullChar + "*.cpt", LoadResString(1601), TimerDir, MainHWnd, #True)
      EndIf
    If Not Len(Filename) = 0
      TimerDir = SimpleDir(Filename)
      If Not (xTimerEvIR = -1 Or xBool1 Or Silent)
        If CalaymMessageBox(xHWnd, LoadResString(1611), LoadResString(1601), 68) = #IDYES
          xBool1 = #True
          Else
          xBool1 = #False
          EndIf
        EndIf
      hFile = TxtFileWriter_CreateFile(Filename)
      If Not hFile = 0
        TxtFileWriter_WriteLine(hFile, #xTimerIDString)
        For xLong1 = 0 To xTimerEvCount - 1
          If Not xLong1 = xTimerEvIR Or xBool1
            TxtFileWriter_WriteLine(hFile, Space(1) + Right("0" + Str(Int(xTimerEvTime(xLong1) / 60)), 2) + ":" + Right("0" + Str(xTimerEvTime(xLong1) % 60), 2) + ", " + xTimerEv(xLong1))
            EndIf
          Next
        TxtFileWriter_Close(hFile)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure TimerMenuEvent(Index.i)
  Define.s xChar1
  
  Select Index
    Case 0
      ToggleInterface(#Interface_Mode_Timer)
    Case 2
      xChar1 = CalaymLoadSingleFile(LoadResString(1605) + #FileFilterVBNullChar + "*.cpt", LoadResString(1600), TimerDir, MainHWnd, #True)
      If Not Len(xChar1) = 0
        TimerDir = SimpleDir(xChar1)
        ;LoadTimers xChar1
        MainForm_LoadTimers(MainHWnd, xChar1, #False)
        EndIf
    Case 3
      MainForm_SaveTimers(MainHWnd, "", #False)
    Case 5
      If InterfaceMode = #Interface_Mode_Timer
        TimerListForm_TrySCommandEx(MainHWnd, 3)
        Else
        
        If Not xTimerEvIR = -1
          If CalaymMessageBox(MainHWnd, LoadResString(1619), LoadResString(1618), 68) = #IDNO
            xTimerEvIR = -1
            EndIf
          EndIf
        If xTimerEvIR = -1
          xTimerEvCount = 0
          ;Erase xTimerEv
          ;Erase xTimerEvTime
          xTimerEvIR = -1
          MainForm_EnableApiMenu(443, #False)
          MainForm_EnableApiMenu(444, #False)
          Else
          xTimerEv(0) = xTimerEv(xTimerEvIR)
          xTimerEvTime(0) = xTimerEvTime(xTimerEvIR)
          xTimerEvCount = 1
          xTimerEvIR = 0
          EndIf
        MainForm_SetTimerImage()
        EndIf
    EndSelect
  EndProcedure

Procedure xRemoveItems(NoSubDirs.i)
  Define.i xLong1
  Define.i xLong2
  ;define.i xLong3
  Define.i xLong4
  Define.i xCaret
  Define.i xCaretOld

  MainForm_LockMe(#True)

  If Not (PLCount = 0 Or xAutoDoing)
    If Not SendMessage_(xListHWnd(2), $190, 0, 0) = 0
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Removing items")
        CompilerEndIf
      xLong1 = -1
      xLong4 = PLCount - 1
      PLCount = 0
      
      If LockWinUpd
        LockWindowUpdate_(xListHWnd(2))
        EndIf
      
      xCaret = SendMessage_(xListHWnd(2), #LB_GETCARETINDEX, 0, 0)
      xCaretOld = xCaret
      
      xHiddenAutoDoing = #True
      SetAutoDoing(#True)
      While xLong1 <> xLong4
        xLong1 = xLong1 + 1
        If xLong1 = PLCurItem
          PLCurItem = PLCount
          EndIf
        If SendMessage_(xListHWnd(2), #LB_GETSEL, PLCount, 0)
          ;If Left(PLItem(xLong1), 1) = Chr(1)
          If xLong1 = PLCurItem
            PLCurItem = PLCount
            EndIf
CompilerIf #BoldDirs = 98
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
          If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
            If NoSubDirs
              CompilerIf #BoldDirs = 98
                CopyStructureEx(PLI(xLong1), PLI(PLCount), tPlaylistItem)
                SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
                CompilerElse
                PLIFile(PLCount) = PLIFile(xLong1)
                PLICap(PLCount) = PLICap(xLong1)
                PLIDF(PLCount) = PLIDF(xLong1)
                PLIPxLg(PLCount) = PLIPxLg(xLong1)
                PLIPxSm(PLCount) = PLIPxSm(xLong1)
                SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
                CompilerEndIf
              ;If xLong1 = PLCurItem
                ;PLCurItem = PLCount
                ;endif
              If xLong1 = PLNext And Not PlNextSong = ""
                PLNext = xLong1
                EndIf
              PLCount = PLCount + 1
              Else
              CompilerIf #BoldDirs = 98
                xLong2 = (PLI(xLong1)\DirDepthFlags & #PLI_Depth) + 1
                CompilerElse
                xLong2 = (PLIDF(xLong1) & #PLI_Depth) + 1
                CompilerEndIf
              If xLong1 = PLNext And Not PlNextSong = ""
                PlNextSong = ""
                PlNextSongCap = ""
                EndIf
              ;RemoveListItemMS
              RemoveFromSearch(PLCount)
              ;PLRemoveShifted1 = PLCount
              ;PLRemoveShifted2 = xLong1
;debug "ShiftMode: 1"
              SendMessage_(xListHWnd(2), #LB_DELETESTRING, PLCount, 0)
              If xCaret >= PLCount
                xCaret = xCaret - 1
                EndIf
              If LockWinUpd = 0
                DoEventsEx_SleepPeriodical()
                ElseIf LockWinUpd = 1
                DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
                EndIf
              While xLong1 <> xLong4
CompilerIf #BoldDirs = 98
                If (PLI(xLong1 + 1)\DirDepthFlags & #PLI_Depth) >= xLong2
CompilerElse
                If (PLIDF(xLong1 + 1) & #PLI_Depth) >= xLong2
CompilerEndIf
                  If xLong1 = PLCurItem
                    PLCurItem = PLCount
                    EndIf
                  If xLong1 = PLNext And Not PlNextSong = ""
                    PlNextSong = ""
                    PlNextSongCap = ""
                    EndIf
                  ;RemoveListItemMS
                  RemoveFromSearch(PLCount)
;debug "ShiftMode: 2"
                  ;PLRemoveShifted1 = PLCount
                  ;PLRemoveShifted2 = xLong1
                  SendMessage_(xListHWnd(2), #LB_DELETESTRING, PLCount, 0)
                  If xCaret >= PLCount
                    xCaret = xCaret - 1
                    EndIf
                  xLong1 = xLong1 + 1
                  If xLong1 & $3f = 0
                    If LockWinUpd = 0
                      DoEventsEx_SleepPeriodical()
                      ElseIf LockWinUpd = 1
                      DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
                      EndIf
                    EndIf
                  Else
                  Break
                  EndIf
                Wend
              xLong2 = xLong2 - 2
              EndIf
            Else
            ;RemoveListItemMS
            RemoveFromSearch(PLCount)
;debug "ShiftMode: 3"
            ;PLRemoveShifted1 = PLCount
            ;PLRemoveShifted2 = xLong1
            SendMessage_(xListHWnd(2), #LB_DELETESTRING, PLCount, 0)
            If xCaret >= PLCount
              xCaret = xCaret - 1
              EndIf
            If LockWinUpd = 0
              DoEventsEx_SleepPeriodical()
              ElseIf LockWinUpd = 1
              DoEventsEx_SleepPeriodicalLW(xListHWnd(2))
              EndIf
            If xLong1 = PLNext And Not PlNextSong = ""
              PlNextSong = "": PlNextSongCap = ""
              EndIf
            EndIf
          Else
          CompilerIf #BoldDirs = 98
            CopyStructureEx(PLI(xLong1), PLI(PLCount), tPlaylistItem)
            SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
            CompilerElse
            PLIFile(PLCount) = PLIFile(xLong1)
            PLICap(PLCount) = PLICap(xLong1)
            PLIDF(PLCount) = PLIDF(xLong1)
            PLIPxLg(PLCount) = PLIPxLg(xLong1)
            PLIPxSm(PLCount) = PLIPxSm(xLong1)
            SendMessage_(xListHWnd(2), $19A, PLCount, PLCount)
            CompilerEndIf
          If xLong1 = PLNext And Not PlNextSong = ""
            PLNext = xLong1
            EndIf
          PLCount = PLCount + 1
          EndIf
        Wend
      ;PLRemoveShifted1 = $7FFFFFFF
      SetAutoDoing(#False)
      xHiddenAutoDoing = #False

      If Not (PLCount = 0 Or xCaret = xCaretOld)
        If xCaret > PLCount - 1
          xCaret = PLCount - 1
          EndIf
        If xCaret < 0
          xCaret = 0
          EndIf
        SendMessage_(xListHWnd(2), #LB_SETCARETINDEX, xCaret, 0)
        EndIf
      
      CheckEmptyNodes(#False, -1)
      CheckOldItems()
      EndIf
    EndIf
  
  MainForm_LockMe(#False)
  EndProcedure

Procedure RemoveCurrentSongFromList()
  Define.i xLong1
  
  If Not vKioskMode
    xLong1 = xFindSong()
    If Not xLong1 = 0
      xMarkSong(xLong1, #False, #False)
      xRemoveItems(#True)
      EndIf
    EndIf
  EndProcedure

Procedure OpenInExplorer(xChar1.s)
  If Not (vKioskMode Or xSecureMode)
    If Len(xChar1)
      If IsFileExists(xChar1) Or IsDirExists(xChar1)
        xChar1 = "/e,/select," + Chr(34) + xChar1 + Chr(34)
        ShellExecute_(MainHWnd, @"open", @"explorer", @xChar1, @"", 5)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure OpenInExplorerDef()
  If Not CurMusic = #ctSSLayer_MusicTypeNone
    OpenInExplorer(PLCurSong)
    EndIf
  EndProcedure

Procedure xFindNextItemExPL(xStep.i)
  Define.i xLong1
  Define.i xLong2
  
  If Not PLCount = 0
    GetListIndexMS(xListHWnd(2), @xLong1)
    If xLong1 = -1
      xLong1 = 0
      EndIf

    xLong2 = xLong1
    Repeat
      xLong1 = (xLong1 + xStep + PLCount) % PLCount
CompilerIf #BoldDirs = 98
      If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = 0 Or xLong1 = xLong2
CompilerElse
      If (PLIDF(xLong1) & #PLI_IsDir) = 0 Or xLong1 = xLong2
CompilerEndIf
        Break ;Function
        EndIf
      ForEver
    xMarkSong(xLong1, #False, #False)
    xFollowCurSongLast = GetTickTimeMS()
    xFollowCurSongLastDiff = #xFollowCurSongLastDiffDef
    EndIf
  EndProcedure

Procedure MainForm_ProcessKey(Index.i, xKioskModeParam.i = #True)
  Static xLong1.i
  
  If IsDialoging = 0 And Not (PlayerIsLocked Or xAutoDoing)
    CompilerIf #UseFileLogging And #DetailLog
      If Index < KbdCount And Not Index < 0
        MainForm_ctConsoleA_AddLog("Keyprocessing: #" & CStr(Index) & " (" & LoadResString(3700 + Index) & ")")
        Else
        MainForm_ctConsoleA_AddLog("Keyprocessing: invalid id (#" & CStr(Index) & ")")
        EndIf
      CompilerEndIf
    If Not vKioskMode
      xKioskModeParam = #False
      EndIf
    If Not xKioskModeParam
      Select Index
        Case #KbdC_FAddFileS
          If Not xSecureMode
            MenuEventFile(0)
            EndIf
        Case #KbdC_FAddDir
          ;If Not xSecureMode
            MenuEventFile(1)
           ; endif
        Case #KbdC_FAddPList
          If Not xSecureMode
            MenuEventFile(2)
            EndIf
        Case #KbdC_FNewPL
          MenuEventFile(6)
        Case #KbdC_FLoadPL
          MenuEventFile(7)
        Case #KbdC_FReloadPL
          MenuEventFile(9)
        Case #KbdC_FLoadPLDefault
          MenuEventFile(8)
        Case #KbdC_FSavePL
          If Not xNoSaveListMenu = 2
            MenuEventFile(10)
            EndIf
        Case #KbdC_FSavePLas
          If Not xSecureMode
            MenuEventFile(11)
            EndIf
        Case #KbdC_FClearPL
          MenuEventFile(13)
        Case #KbdC_CPrev, #KbdC_GPrev
          MainForm_IconsMouseUp(0)
        Case #KbdC_CPause, #KbdC_GPause
          MainForm_IconsMouseUp(2)
        Case #KbdC_CRepSingle, #KbdC_GRepSingle
          xRep = 0: MainForm_ApplyRepMode()
        Case #KbdC_CRepAll, #KbdC_GRepAll
          xRep = 1: MainForm_ApplyRepMode()
        Case #KbdC_CRepRnd, #KbdC_GRepRnd
          xRep = 2: MainForm_ApplyRepMode()
        Case #KbdC_CRepToggle, #KbdC_GRepToggle
          xRep = (xRep + 1) % 3: MainForm_ApplyRepMode()
        Case #KbdC_CIntroMode, #KbdC_GIntroMode
          If IntroModeActive
            IntroModeActive = #False
            Else
            IntroModeActive = #True
            EndIf
          MainForm_ApplyRepMode()
        Case #KbdC_CSeekB, #KbdC_GSeekB
          xTrackSeekA(-1)
        Case #KbdC_CSeekF, #KbdC_GSeekF
          xTrackSeekA(1)
        Case #KbdC_CCSRemFile, #KbdC_GRemFile
          If Not vKioskMode
            If Not (CurMusic = #ctSSLayer_MusicTypeNone Or (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3))
              RemoveCurrentSongFromList()
              EndIf
            EndIf
        Case #KbdC_CCSDelFile, #KbdC_GDelFile
          If xDelMode And Not xSecureMode
            If Not (CurMusic = #ctSSLayer_MusicTypeNone Or (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3))
              xDeleteFileNow(#True)
              EndIf
            EndIf
        Case #KbdC_CCSExplorer, #KbdC_GExplorer
          If Not xSecureMode
            If Not (CurMusic = #ctSSLayer_MusicTypeNone Or (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3))
              OpenInExplorerDef()
              EndIf
            EndIf
        Case #KbdC_PInvSel
          For xLong1 = 0 To PLCount - 1
            If SendMessage_(xListHWnd(2), #LB_GETSEL, xLong1, 0) = 0
              SendMessage_(xListHWnd(2), #LB_SETSEL, 1, xLong1)
              Else
              SendMessage_(xListHWnd(2), #LB_SETSEL, 0, xLong1)
              EndIf
            ;SetlPlayList_Selected xLong1, Not GetlPlayList_Selected(xLong1)
            Next
          MainForm_CheckDir(#False)
        Case #KbdC_PRemSongs
          xRemoveItems(#True)
        Case #KbdC_PRem
          xRemoveItems(#False)
        Case #KbdC_PCopyPLEnd
          MainForm_MenuEventPlaylist(13)
        Case #KbdC_PCrop
          MainForm_MenuEventPlaylist(14)
        Case #KbdC_PDelFiles
          If xDelMode And Not xSecureMode
            xDeleteFileNow(#False)
            EndIf
        Case #KbdC_PExplorer
          If Not xSecureMode
            If GetListIndexMS(xListHWnd(2), @xLong1)
              CompilerIf #BoldDirs = 98
                OpenInExplorer(PLI(xLong1)\Filename)
                CompilerElse
                OpenInExplorer(PLIFile(xLong1))
                CompilerEndIf
              EndIf
            EndIf
        Case #KbdC_OFading
          If xGenFading
            xGenFading = #False
            Else
            xGenFading = #True
            EndIf
          CheckApiMenu(301, xGenFading)
        Case #KbdC_OSpektrum
          If Not xNoSpectrumForce
            SpektrumToggleEvent()
            EndIf
        Case #KbdC_OFileInfos
          If MP3GetID3Tag
            MP3GetID3Tag = #False
            Else
            MP3GetID3Tag = #True
            EndIf
          CheckApiMenu(303, MP3GetID3Tag)
          If MP3GetID3Tag
            ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Tags), 5)
            Else
            ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Tags), 0)
            EndIf
          SetPanelSize()
        Case #KbdC_OFollowSong
          If xFollowCurSong
            xFollowCurSong = #False
            Else
            xFollowCurSong = #True
            EndIf
          CheckApiMenu(310, xFollowCurSong)
          If xFollowCurSong And SendMessage_(xListHWnd(2), $190, 0, 0) < 2
            xLong1 = xFindSong()
            If Not xLong1 = 0
              xMarkSong(xLong1, #False, #False)
              EndIf
            EndIf
        Case #KbdC_ORemMissing
          If xRemoveMissingSongs
            xRemoveMissingSongs = #False
            Else
            xRemoveMissingSongs = #True
            EndIf
          CheckApiMenu(320, xRemoveMissingSongs)
        Case #KbdC_ORemSkipped
          If xRemoveSkippedSongs
            xRemoveSkippedSongs = #False
            Else
            xRemoveSkippedSongs = #True
            EndIf
          CheckApiMenu(321, xRemoveSkippedSongs)
        Case #KbdC_ORemPlayed
          If xRemovePlayedSongs
            xRemovePlayedSongs = #False
            Else
            xRemovePlayedSongs = #True
            EndIf
          CheckApiMenu(322, xRemovePlayedSongs)
        Case #KbdC_OXFade
          ;If xProcessMode = 1
            ;xProcessMode = 0 Else xProcessMode = 1
            ;EndIf
          xProcessMode = 1
          MainForm_ApplyProcessMode()
        Case #KbdC_OMDMode
          ;If xProcessMode = 2
            ;xProcessMode = 0 Else xProcessMode = 2
            ;EndIf
          xProcessMode = 2
          MainForm_ApplyProcessMode()
        Case #KbdC_OStopEach
          ;If xProcessMode = 3
            ;xProcessMode = 0
            ;Else
            ;xProcessMode = 3
            ;EndIf
          xProcessMode = 3
          MainForm_ApplyProcessMode()
        Case #KbdC_OEndModeTggle
          xProcessMode = (xProcessMode + 1) & 3
          MainForm_ApplyProcessMode()
        Case #KbdC_ONoEndMode
          xProcessMode = 0
          MainForm_ApplyProcessMode()
        Case #KbdC_OInternetRadio, #KbdC_GIRadio
          If Not vKioskMode
            If Not InterfaceMode = #Interface_Mode_Radio
              ToggleInterface(#Interface_Mode_Radio)
              EndIf
            EndIf
        Case #KbdC_OInternetRadioRe, #KbdC_GIRadioRe
          If Not vKioskMode
            If Not Len(PLCurFullURL) = 0
              StartWeb(PLCurFullURL, #True)
              EndIf
            EndIf
        Case #KbdC_OInternetRadioHP, #KbdC_GIRadioHP
          If CurMusic = #ctSSLayer_MusicTypeStream And (xSongIsMidi = 3)
            SaveOpenURL(SenderURL)
            EndIf
        Case #KbdC_OAutoRF, #KbdC_GAutoRF
          If Not xNoAutoRefreshByUser
            MainForm_xAutoRefreshNow(#False, #False, #False, #False, #False)
            CheckReplay()
            EndIf
        Case #KbdC_OAutoRFRem
          If Not xNoAutoRefreshByUser
            AutoRefreshHandler(1)
            EndIf
        Case #KbdC_OAutoRFRemI
          If Not xNoAutoRefreshByUser
            AutoRefreshHandler(2)
            EndIf
        Case #KbdC_OAutoRFSetup
          If Not (xNoAutoRefreshByUser Or xNoAutoSetup)
            AutoRefresh_ShowDialog()
            EndIf
        Case #KbdC_OAutoRFAlt, #KbdC_GAutoRFAlt
          If Not xNoAutoRefreshByUser
            AutoRefreshHandler(4)
            EndIf
        Case #KbdC_OTimerEdit
          If Not xNoTimers
          ;If Not xSecureMode
            TimerMenuEvent(0)
            EndIf
        Case #KbdC_OTimerImport
          If Not (xNoTimers Or xSecureMode)
            TimerMenuEvent(2)
            EndIf
        Case #KbdC_OTimerExport
          If Not (xNoTimers Or xSecureMode)
            TimerMenuEvent(3)
            EndIf
        Case #KbdC_OTimerClear
          If Not xNoTimers
            TimerMenuEvent(5)
            EndIf
        Case #KbdC_OPresetSave
          If Not xSecureMode
            MenuEventPlaylistLoader(0)
            EndIf
        Case #KbdC_OPresetLoad
          If Not xSecureMode
            MenuEventPlaylistLoader(1)
            EndIf
        Case #KbdC_OSaveSetts
          If xCmdSaveSet And Not xNoSetup
            MainForm_SaveSettings(0, #False)
            PLWriter_Save(AppBase_GetByExt(#DefaultPLExtension), #True)
            EndIf
        Case #KbdC_OResetSnd, #KbdC_GResetSND
          MainForm_OutputChange(MainHWnd, #False, #True)
        Case #KbdC_OVolCtrl, #KbdC_GVolCtrl
          ;On Error Resume Next
          ;Shell "sndvol32", vbNormalFocus
          If Not ShellExecute_(0, @"open", @"sndvol32", 0, 0, 5)
            ShellExecute_(0, @"open", @"sndvol", 0, 0, 5)
            EndIf
          ;On Error GoTo 0
        Case #KbdC_CMoreSetts
          If Not xNoSetup
;;            If SetupDialogHWnd = 0
;              ;LockMe #True
;              ShowIcon 0
            ShowSetup()
;              ;LockMe #False
;              ShowIcon 0
;            ;ShowVBWindowX frmSetup, SetupVisible
            EndIf
        Case #KbdC_GShowMenu ;show menu/advmenu
          SetMenuDefaultItem_(xMenu(3), -1, #True)
          ;MenuEvent GetAPIPopupMenu(MainHWnd, xMenu(3), 0, 0)
          MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(3), 0))
        Case #KbdC_GShowAltMenu
          SetMenuDefaultItem_(xMenu(2), -1, #True)
          ;MenuEvent GetAPIPopupMenu(MainHWnd, xMenu(2), 0, 0)
          MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(2), 0))
        EndSelect
      EndIf
    
    If Index >= #KbdC_GPrevSel And Index <= #KbdC_GRandSel
      If Not InterfaceMode = #Interface_Mode_None
        ToggleInterface(#Interface_Mode_None)
        Goto SkipButs
        EndIf
      EndIf
    
    
    Select Index
      Case #KbdC_FRefreshCD
        MenuEventCDDrive(CDDriveLetters, #True, #True)
      Case #KbdC_FQuitSD, #KbdC_GQuit ;quit
        If Not xNoQuitMenu
          Select xCmdQuitMode
            Case 1, 4, 5
              If hwndShutDownDialog = 0
                If xCmdQuitMode = 1
                  QuitModePending = 1
                  Else
                  QuitModePending = xCmdQuitMode - 2
                  EndIf
                If (PlayerIsLocked Or xAutoDoing)
                  ;PostMessageA(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 2)
                  WantsShutdownDialog = #True
                  Else
                  StartShutDownStuff()
                  EndIf
                EndIf
            Case 2
              ExitWindowsDialog(MainHWnd)
            Default
              MainForm_UnloadPlayer()
            EndSelect
          EndIf
      
      
      Case #KbdC_CPlay, #KbdC_GPlay
        If Not xKioskModeParam Or PlDClickAction = 0
          MainForm_IconsMouseUp(1)
          EndIf
      Case #KbdC_GPlayPause ;play/pause
        If Not xKioskModeParam Or PlDClickAction = 0
          If xPStateIconPlaying
            MainForm_IconsMouseUp(2)
            Else
            MainForm_IconsMouseUp(1)
            EndIf
          EndIf
      Case #KbdC_CStop, #KbdC_GStop ;stop/abort
        MainForm_IconsMouseUp(3)
      Case #KbdC_CNext, #KbdC_GNext ;next
        If Not xKioskModeParam Or PlDClickAction = 0
          MainForm_IconsMouseUp(4)
          EndIf
      Case #KbdC_CEnd, #KbdC_GEnd ;endsong
        If Not (xKioskModeParam And PlDClickAction = 2)
          MainForm_IconsMouseUp(5)
          EndIf
        Case #KbdC_CCSSelFile
          If Not (CurMusic = #ctSSLayer_MusicTypeNone Or (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3))
            xLong1 = xFindSong()
            If Not xLong1 = 0
              xMarkSong(xLong1, #False, #False)
              EndIf
            EndIf
      Case #KbdC_CVolUp, #KbdC_GVolUp
        If Not xKioskModeParam Or vCanVolume
          ChangeVolumeMenu(0)
          EndIf
      Case #KbdC_CVolDown, #KbdC_GVolDown
        If Not xKioskModeParam Or vCanVolume
          ChangeVolumeMenu(1)
          EndIf
      Case #KbdC_CVolMute To #KbdC_CVolFull ;Vol 0-100
        If Not xKioskModeParam Or vCanVolume
          ChangeVolumeMenu(3 + (Index - #KbdC_CVolMute))
          EndIf
      Case #KbdC_GVolMute To #KbdC_GVolFull ;Vol 0-100
        If Not xKioskModeParam Or vCanVolume
          ChangeVolumeMenu(3 + (Index - #KbdC_GVolMute))
          EndIf
  
  
  
      Case #KbdC_CPrevSongs
        If IsWindowVisible_(xListHWnd(1))
          ShowWindow_(xListHWnd(1), 0)
          DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
          Else
          ShowWindow_(xListHWnd(1), 5)
          DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 1)
          SetFocus_(xListHWnd(1))
          EndIf
      
      
      
      Case #KbdC_GPlayDef
        MainForm_PlayListDoubleClickEvent()
      Case #KbdC_PPlaySkip, #KbdC_GPlaySkp
        If Not xKioskModeParam Or PlDClickAction = 0
          MainForm_MenuEventPlaylist(0)
          EndIf
      Case #KbdC_PPlayEnd, #KbdC_GPlayEnd
        If Not (xKioskModeParam And PlDClickAction = 2)
          MainForm_MenuEventPlaylist(1)
          EndIf
      Case #KbdC_PPlayNext, #KbdC_GPlayNxt
        MainForm_MenuEventPlaylist(2)
      Case #KbdC_GPrevSel
        xFindNextItemExPL(-1)
      Case #KbdC_GNextSel
        xFindNextItemExPL(1)
      Case #KbdC_GPrevPage
        SendMessage_(xListHWnd(2), $100, $21, 0)
        SendMessage_(xListHWnd(2), $101, $21, 0)
      Case #KbdC_GNextPage
        SendMessage_(xListHWnd(2), $100, $22, 0)
        SendMessage_(xListHWnd(2), $101, $22, 0)
      Case #KbdC_PFindCurrent, #KbdC_GCurNSel
        MainForm_MenuEventPlaylist(4)
      Case #KbdC_PFind
        MainForm_MenuEventPlaylist(5)
      Case #KbdC_PFindNext
        MainForm_MenuEventPlaylist(6)
      Case #KbdC_PFindQuick
        ToggleInterface(#Interface_Mode_Search)
      Case #KbdC_PSelRnd, #KbdC_GRandSel
        If Not PLCount = 0
          xLong1 = RandomSong()
          If Not xLong1 = -1
            xMarkSong(xLong1, #False, #False)
            EndIf
          EndIf
      
      Case #KbdC_PGotoDir
        If xDirListModeCur = 0
          If IsWindowVisible_(xListHWnd(0))
            ShowWindow_(xListHWnd(0), 0)
            DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
            Else
            ShowWindow_(xListHWnd(0), 5)
            DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 1)
            SetFocus_(xListHWnd(0))
            EndIf
          EndIf
      
      
      
      
      Case #KbdC_ODirToggle
        DirListEvent(5, #False)
      Case #KbdC_ODirCombo
        DirListEvent(0, #True)
      Case #KbdC_ODirTop
        DirListEvent(1, #True)
      Case #KbdC_ODirLeft
        DirListEvent(2, #True)
      Case #KbdC_ODirAuto
        DirListEvent(3, #True)
      Case #KbdC_ODirInc
        DirListEvent(9, #True)
      Case #KbdC_ODirDec
        DirListEvent(8, #True)
      Case #KbdC_IHelp
        If Not (xKioskModeParam Or xSecureMode)
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
            HtmlHelp(MainHWnd, xRealBaseFile + "chm", 0, @"welcome.htm")
            CompilerElse
            If xUseChmHelp
              HtmlHelp(MainHWnd, xRealBaseFile + "chm", 0, @"welcome.htm")
              Else
              WinHelp(MainHWnd, xRealBaseFile + "hlp", $101, @"Welcome")
              EndIf
            CompilerEndIf
          EndIf
      Case #KbdC_IAbout
        ShowInfo()
      Case #KbdC_GShowVolMenu ;show volmenu
        If Not xKioskModeParam Or vCanVolume
          MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(4), 0))
          EndIf
      Case #KbdC_GShowTitle
        If xPStateIconPlaying And Not (CurMusic = #ctSSLayer_MusicTypeNone Or PlayerIsLocked)
          ShowIR_Do(#False)
          EndIf
      EndSelect
    EndIf

  If Index = #KbdC_GShowPlayer And Not xInfoQuit
    ShowPlayer(#True)
    ElseIf Index = #KbdC_GShowPlayerPS And Not xInfoQuit
    ShowPlayer(#False)
    ElseIf Index = #KbdC_GAbortReading And Not vKioskMode
    AbortReading = #True
    EndIf
SkipButs:
  CompilerIf #UseFileLogging And #DetailLog
    MainForm_ctConsoleA_AddLog("Keyprocessing finished")
    CompilerEndIf
  EndProcedure

Procedure.i MainForm_GetMessageA_CopyData(*lParam.COPYDATASTRUCT)
  Define.i xResult

  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("SendMessageA_CopyData Received") ;, pushing to cds (" & CStr(PointerToCDStruct) & ")")
    CompilerEndIf
  
  If GMCD_Pending
    xResult = 2
    ElseIf *lParam
    If *lParam\lpData And *lParam\cbData
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  Receiving data")
        CompilerEndIf
      If *lParam\dwdata
        GMCD_URL = PeekS(*lParam\lpData, *lParam\cbData >> 1, #PB_Unicode)
        GMCD_Mode = *lParam\dwdata
        Else
        GMCD_URL = PeekS(*lParam\lpData, *lParam\cbData, #PB_Ascii)
        GMCD_Mode = -1
        EndIf
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  Received (Mode " + Str(*lParam\dwdata) + "): " + ReplaceString(GMCD_URL, #CRLF$, #CRLF$ + Space(8)))
        CompilerEndIf
      xResult = 1
      GMCD_Pending = #True
      PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 3)
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure PostGetMessage()
  Define.i xLong1

  If Not (PlayerIsLocked Or xAutoDoing)
    If Not FindString(GMCD_URL, "://") = 0 Or GMCD_Mode = 3
      StartWeb(GMCD_URL, #True)
      ElseIf AllowedItem(GMCD_URL, #True) = 255 And Not LCase(GMCD_URL) = LCase(xCurPlistFilename)
      If (GMCD_Mode = 2)
        xLong1 = #True
        EndIf
      LoadPList(GMCD_URL, xLong1, #False)
      ElseIf AllowedItem(GMCD_URL, #True) = 0
      If Not (GMCD_Mode = 2)
        xLong1 = #True
        EndIf
      AddFDirNowSubEx(GMCD_URL, xLong1)
      ElseIf GMCD_URL = "test"
      ShowPlayer(#True)
      EndIf
    EndIf
  DoEvents() ;fetch all other pendings to be ignored
  GMCD_Pending = #False
  EndProcedure

Procedure MainForm_SetStandby(SetMe.i)
  Static xStandby.i
;  Static xBool1 As Boolean
  
  If SetMe
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("  Standing by / Hybernate")
      CompilerEndIf
    If Not PlayerIsLocked Or xStandby
      xStandby = #True
      MainForm_LockMe(#True)
      xPStateIconSndcard = #True
      MainForm_UpdateMainIcon()
      
      ResetSystem(#False, #False)
      Tear_WaitFor(-2)
      ctSSLayer_Close(0)
      EndIf
    ElseIf xStandby
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("  Done: Standing by / Hybernate")
      CompilerEndIf
    xStandby = #False
    ctSSLayer_RefreshDeviceList(MainHWnd)
    xInitMe(MainHWnd, #False, #False, #False)
    ResetSystem(#True, #False)
    ;xEndSongTimerEventTime = GetTickTimeMS()
    ;LastPosTime = xEndSongTimerEventTime
    xPStateIconSndcard = #False
    MainForm_UpdateMainIcon()
    MainForm_LockMe(#False)
CompilerIf #UseFileLogging
    Else
    MainForm_ctConsoleA_AddLog("  (Done: Standing by / Hybernate)")
CompilerEndIf
    EndIf
  EndProcedure

Procedure MainForm_EndSongCallback(ptrSong.i)
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Callback event occurred (pointer: " + Str(ptrSong) + ")")
    CompilerEndIf
  If ptrSong = SongPointer(CurrentSongID) And Not (CurMusic = #ctSSLayer_MusicTypeNone Or PlayerIsLocked Or xAutoDoing)
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Callback valid, processing ;CheckAfter; procedure")
      CompilerEndIf
    MainForm_CheckAfter(#False, #False, #False, #False)
    CompilerIf #UseFileLogging
      MainForm_ctConsoleA_AddLog("Callback done")
      CompilerEndIf
    EndIf
  EndProcedure
  
Procedure.i ProcessTimerEvent(EventID.i, Filename.s) ;, TimerIndex.i) As Boolean
  CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("  Event #" + Right(Space(4) + Str(EventID), 4) + ": " + LoadResString(3700 + EventID))
    If TimerHasSubFile(EventID)
      MainForm_ctConsoleA_AddLog("  with file: " + Filename)
      EndIf
    CompilerEndIf
  Define.i xLong1
  Define.s xChar1
  
  If Not (PlayerIsLocked Or xAutoDoing)
    Select EventID
      Case #KbdC_FAddFileS
        If AllowedItem(Filename, #True) = 1
          If PLCount < PLCountMaxX
            xChar1 = SimpleDir(Filename)
            CompilerIf #BoldDirs = 98
              PLI(PLCount)\Filename = xChar1
              PLI(PLCount)\Caption = xChar1
              PLI(PLCount)\DirDepthFlags = #PLI_IsDir
              PLCount = PLCount + 1
              PLI(PLCount)\Filename = Filename
              PLI(PLCount)\Caption = SimpleFile(Filename)
              PLI(PLCount)\DirDepthFlags = 1
              CompilerElse
              PLIFile(PLCount) = xChar1
              PLICap(PLCount) = xChar1
              PLIDF(PLCount) = #PLI_IsDir
              PLCount = PLCount + 1
              PLIFile(PLCount) = Filename
              PLICap(PLCount) = SimpleFile(Filename)
              PLIDF(PLCount) = 1
              CompilerEndIf
            PLCount = PLCount + 1
            RealPLAdd(PLCount - 2)
            EndIf
          EndIf
      Case #KbdC_FAddDir
        If AllowedItem(Filename, #True) = 0
          SetAutoDoing(#True)
          xPStateIconRefreshing = #True
          MainForm_UpdateMainIcon()
          AbortReading = #False
          MainForm_LockMe(#True)
          DoEvents()
          xLong1 = PLCount
          ReadDirInit()
          ReadDirectory(Filename, 0, #True, 0, 0, #xDefBWDifL)
          ReadDirDone()
          RealPLAdd(xLong1)
          MainForm_LockMe(#False)
          xPStateIconRefreshing = #False
          MainForm_UpdateMainIcon()
          SetAutoDoing(#False)
          CheckReplay()
          EndIf
      Case #KbdC_FLoadPL, #KbdC_FAddPList
        If AllowedItem(Filename, #True) = 255
          If EventID = #KbdC_FLoadPL
            PLCount = 0
            xRadioCount = 0
            RadioForm_PrePreset()
            EndIf
          If EventID = #KbdC_FAddPList
            xLong1 = #True
            EndIf
          LoadPList(xChar1, xLong1, #False) ;, #False)
          EndIf
;      Case #KbdC_FLoadPL
      Case #KbdC_FSavePLas
        If AllowedItem(Filename, #False) = 255
          PLWriter_Save(Filename, #False)
          EndIf
      Case #KbdC_OTimerImport
        If AllowedItem(Filename, #True) = 254
          MainForm_LoadTimers(MainHWnd, Filename, #True)
          EndIf
      Case #KbdC_OTimerExport
        If LCase(Right(Filename, 4)) = ".cpt"
          ; silent mode!
          MainForm_SaveTimers(0, Filename, #True) ;, xShowSpectrum
          EndIf
      Case #KbdC_OPresetSave
        If LCase(Right(Filename, 4)) = ".cps"
          SavePreset(Filename)
          EndIf
      Case #KbdC_OPresetLoad
        If AllowedItem(Filename, #True) = 253
          MainForm_LoadSettings(Filename)
          EndIf
      Case #KbdCTm_FShutDown
        PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 2)
      Case #KbdCTm_FHibernate
        PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 4)
      Case #KbdCTm_FStandby
        PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 5)
      Case #KbdCTm_FMonitoff
        PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 6)
      Case #KbdCTm_CPlay
        If xPStateIconPlaying
          If xPStateIconPaused
            MainForm_xPauseClick()
            EndIf
          Else
          MainForm_xPlayClick(#False)
          EndIf
      Case #KbdCTm_CPause
        If xPStateIconPlaying And xPStateIconPaused
          MainForm_xPauseClick()
          EndIf
      Case #KbdCTm_CStop
        If Len(PlNextSong)
          SetNextSong(#False)
          EndIf
        MainForm_IconsMouseUp(3)
        MainForm_LockMe(#True)
        Tear_WaitFor(-2)
        MainForm_LockMe(#False)
      Case #KbdCTm_CIntroModeOn
        If Not IntroModeActive
          MainForm_ProcessKey(#KbdC_CIntroMode)
          EndIf
      Case #KbdCTm_CIntroModeOff
        If IntroModeActive
          MainForm_ProcessKey(#KbdC_CIntroMode)
          EndIf
      Case #KbdCTm_PFindCurrent
        MainForm_MenuEventPlaylist(400)
      Case #KbdCTm_OFadingOn, #KbdCTm_OFadingOff
        If xGenFading = (EventID = #KbdCTm_OFadingOff)
          MainForm_ProcessKey(#KbdC_OFading)
          EndIf
      Case #KbdCTm_OSpektrumOn, #KbdCTm_OSpektrumOff
        ;If Not vKioskMode
          If xShowSpectrum = (EventID = #KbdCTm_OSpektrumOff)
            MainForm_ProcessKey(#KbdC_OSpektrum, #False)
            EndIf
        ;  endif
      Case #KbdCTm_OFileInfosOn, #KbdCTm_OFileInfosOff
        If MP3GetID3Tag = (EventID = #KbdCTm_OFileInfosOff)
          MainForm_ProcessKey(#KbdC_OFileInfos)
          EndIf
      Case #KbdCTm_OFollowSongOn, #KbdCTm_OFollowSongOff
        If xFollowCurSong = (EventID = #KbdCTm_OFollowSongOff)
          MainForm_ProcessKey(#KbdC_OFollowSong)
          EndIf
      Case #KbdCTm_ORemMissingOn, #KbdCTm_ORemMissingOff
        If xRemoveMissingSongs = (EventID = #KbdCTm_ORemMissingOff)
          MainForm_ProcessKey(#KbdC_ORemMissing)
          EndIf
      Case #KbdCTm_ORemSkippedOn, #KbdCTm_ORemSkippedOff
        If xRemoveSkippedSongs = (EventID = #KbdCTm_ORemSkippedOff)
          MainForm_ProcessKey(#KbdC_ORemSkipped)
          EndIf
      Case #KbdCTm_ORemPlayedOn, #KbdCTm_ORemPlayedOff
        If xRemovePlayedSongs = (EventID = #KbdCTm_ORemPlayedOff)
          MainForm_ProcessKey(#KbdC_ORemPlayed)
          EndIf
      Case #KbdCTm_ONoEndMode
        If Not xProcessMode = 0
          MainForm_ProcessKey(#KbdC_ONoEndMode)
          EndIf
      Case #KbdCTm_OXFadeOn
        If Not xProcessMode = 1
          MainForm_ProcessKey(#KbdC_OXFade)
          EndIf
      Case #KbdCTm_OMDModeOff
        If Not xProcessMode = 2
          MainForm_ProcessKey(#KbdC_OMDMode)
          EndIf
      Case #KbdCTm_OStopEachOn
        If Not xProcessMode = 3
          MainForm_ProcessKey(#KbdC_OStopEach)
          EndIf
      Default
        MainForm_ProcessKey(EventID, #False)
      EndSelect
    EndIf
  ;ProcedureReturn xResult
  ProcedureReturn 0
  EndProcedure

Procedure.i FindNext()
  Define.i xResult
  Define.i xLong1
  Define.i xLong2


  
  If Not (xFindNextString = "" Or PLCount = 0)
    xLong2 = SendMessage_(xListHWnd(2), #LB_GETCARETINDEX, 0, 0) + 1
    GetListIndexMS(xListHWnd(2), @xLong2)
    If xLong2 = -1
      xLong2 = 0
      EndIf
    xLong1 = xLong2
    ;xLong2 = xLong2 + CurrentFindInvert
    ;If xLong2 = -1
    ;  xLong2 = PLCount - 1
    ;  ElseIf xLong2 = PLCount
    ;  xLong2 = 0
    ;  endif
    Repeat
      xLong1 = xLong1 + CurrentFindInvert
      If xLong1 = -1
        xLong1 = PLCount - 1
        ElseIf xLong1 = PLCount
        xLong1 = 0
        ;ElseIf xLong1 = xLong2
        ;Exit Do
        EndIf
      ;vbBinaryCompare
      ;#PB_String_NoCase
CompilerIf #BoldDirs = 98
      If FindString(PLI(xLong1)\Caption, xFindNextString, 1, #PB_String_NoCase)
CompilerElse
      If FindString(PLICap(xLong1), xFindNextString, 1, #PB_String_NoCase)
CompilerEndIf
        xMarkSong(xLong1, #False, #False)
        xResult = #True
        Break
        ElseIf xLong1 = xLong2
        Break
        EndIf
      ForEver
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure FindNowCB()
  Define.s xChar1
  
  CompilerIf #PB_Compiler_Unicode
    xChar1 = PeekS(CurrentFindHMem, 256)
    CompilerElse
    xChar1 = PeekS(CurrentFindHMem, 513)
    CompilerEndIf
  If Not Len(Trim(xChar1)) = 0
          ;  xChar1 = InputBox(LoadResString(1441), LoadResString(1440), xFindNextString)
          ;  If Trim(xChar1) = ""
          ;    Exit Do
          ;    Else
    xFindNextString = xChar1
    If FindNext()
      EnableWindow_(MainHWnd, 1)
      DestroyWindow_(CurrentFindHWnd)
      SetForegroundWindow_(MainHWnd)
      SetFocus_(MainHWnd)
      If Not CurrentFindHWnd = 0
        CurrentFindHWnd = 0
        LocalFree_(CurrentFindHMem)
        CurrentFindHMem = 0
        DialogTimer(#False)
        EnableWindow_(MainHWnd, 1)
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure.f GetGDU(xFont.i)
  Define.f xResult
  Define.i xLong1
  xFont = SelectObject_(xSharedDC, xFont)
  xResult = GetTextOutWidth(xSharedDC, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
  xLong1 = GetDialogBaseUnits_() & $FFFF
  xResult = xLong1 / (2 * Int(xResult / 62))
  ProcedureReturn xResult
  EndProcedure

Procedure MainForm_AdvanceSong(TabMode.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3

;0 updir
;1 any
;2 any inv
;3 same
;4 same inv

;compilerif #0

  If Not PlayerIsLocked Or xAutoDoing
    GetListIndexMS(xListHWnd(2), @xLong1)
    If xLong1 = -1
      xLong1 = 0
      EndIf
      
    Select TabMode
      Case 0
        
        CompilerIf #BoldDirs = 98
          xLong2 = (PLI(xLong1)\DirDepthFlags & #PLI_Depth) - 2 ; Len(PLCap(xLong1)) - Len(LTrim(PLCap(xLong1))) - 4
          CompilerElse
          xLong2 = (PLIDF(xLong1) & #PLI_Depth) - 2 ; Len(PLCap(xLong1)) - Len(LTrim(PLCap(xLong1))) - 4
          CompilerEndIf
        CompilerIf #BoldDirs = 98
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
            xLong2 = xLong2 + 1
            EndIf
          CompilerElse
          If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
            xLong2 = xLong2 + 1
            EndIf
          CompilerEndIf
        If Not xLong2 < 0
          For xLong1 = xLong1 - 1 To 0 Step -1
CompilerIf #BoldDirs = 98
            If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
              If (PLI(xLong1)\DirDepthFlags & #PLI_Depth) = xLong2
CompilerElse
            If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
              If (PLIDF(xLong1) & #PLI_Depth) = xLong2
CompilerEndIf
                xMarkSong(xLong1, #False, #False)
                Break
                EndIf
              EndIf
            Next
          EndIf
      Case 1
        CompilerIf #BoldDirs = 98
          xLong2 = (PLI(xLong1)\DirDepthFlags & #PLI_Depth)
          CompilerElse
          xLong2 = (PLIDF(xLong1) & #PLI_Depth)
          CompilerEndIf
        While xLong1 <> PLCount - 1
          xLong3 = xLong1 + 1
CompilerIf #BoldDirs = 98
          If (PLI(xLong3)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir And (PLI(xLong3)\DirDepthFlags & #PLI_Depth) > xLong2
CompilerElse
          If (PLIDF(xLong3) & #PLI_IsDir) = #PLI_IsDir And (PLIDF(xLong3) & #PLI_Depth) > xLong2
CompilerEndIf
            xLong1 = xLong3
            Else
            Break
            EndIf
          Wend
        For xLong1 = xLong1 + 1 To PLCount - 1
CompilerIf #BoldDirs = 98
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
          If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
            While xLong1 <> PLCount - 1
              xLong3 = xLong1 + 1
CompilerIf #BoldDirs = 98
              If (PLI(xLong3)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir And (PLI(xLong3)\DirDepthFlags & #PLI_Depth) > xLong2
CompilerElse
              If (PLIDF(xLong3) & #PLI_IsDir) = #PLI_IsDir And (PLIDF(xLong3) & #PLI_Depth) > xLong2
CompilerEndIf
                xLong1 = xLong3
                Else
                Break
                EndIf
              Wend
            xMarkSong(xLong1, #False, #False)
            Break
            EndIf
          Next
      Case 2
        CompilerIf #BoldDirs = 98
          xLong2 = (PLI(xLong1)\DirDepthFlags & #PLI_Depth)
          CompilerElse
          xLong2 = (PLIDF(xLong1) & #PLI_Depth)
          CompilerEndIf
        While xLong1
          xLong3 = xLong1 - 1
CompilerIf #BoldDirs = 98
          If (PLI(xLong3)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir And (PLI(xLong3)\DirDepthFlags & #PLI_Depth) < xLong2
CompilerElse
          If (PLIDF(xLong3) & #PLI_IsDir) = #PLI_IsDir And (PLIDF(xLong3) & #PLI_Depth) < xLong2
CompilerEndIf
            xLong1 = xLong3
            Else
            Break
            EndIf
          Wend
        For xLong1 = xLong1 - 1 To 0 Step -1
CompilerIf #BoldDirs = 98
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
CompilerElse
          If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
CompilerEndIf
            While xLong1
              xLong3 = xLong1 - 1
CompilerIf #BoldDirs = 98
              If (PLI(xLong3)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir And (PLI(xLong3)\DirDepthFlags & #PLI_Depth) < xLong2
CompilerElse
              If (PLIDF(xLong3) & #PLI_IsDir) = #PLI_IsDir And (PLIDF(xLong3) & #PLI_Depth) < xLong2
CompilerEndIf
                xLong1 = xLong3
                Else
                Break
                EndIf
              Wend
            xMarkSong(xLong1, #False, #False)
            Break
            EndIf
          Next
      
      Case 3
        CompilerIf #BoldDirs = 98
          xLong2 = (PLI(xLong1)\DirDepthFlags & #PLI_Depth)
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = 0
            xLong2 = xLong2 - 1
            EndIf
          CompilerElse
          xLong2 = (PLIDF(xLong1) & #PLI_Depth)
          If (PLIDF(xLong1) & #PLI_IsDir) = 0
            xLong2 = xLong2 - 1
            EndIf
          CompilerEndIf
        For xLong1 = xLong1 + 1 To PLCount - 1
          CompilerIf #BoldDirs = 98
            If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
              If (PLI(xLong1)\DirDepthFlags & #PLI_Depth) = xLong2
                xMarkSong(xLong1, #False, #False)
                Break
                ElseIf (PLI(xLong1)\DirDepthFlags & #PLI_Depth) < xLong2
                Break
                EndIf
              EndIf
            CompilerElse
            If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
              If (PLIDF(xLong1) & #PLI_Depth) = xLong2
                xMarkSong(xLong1, #False, #False)
                Break
                ElseIf (PLIDF(xLong1) & #PLI_Depth) < xLong2
                Break
                EndIf
              EndIf
            CompilerEndIf
          Next
      Case 4
        CompilerIf #BoldDirs = 98
          xLong2 = (PLI(xLong1)\DirDepthFlags & #PLI_Depth)
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = 0
            xLong2 = xLong2 - 1
            EndIf
          CompilerElse
          xLong2 = (PLIDF(xLong1) & #PLI_Depth)
          If (PLIDF(xLong1) & #PLI_IsDir) = 0
            xLong2 = xLong2 - 1
            EndIf
          CompilerEndIf
        For xLong1 = xLong1 - 1 To 0 Step -1
          CompilerIf #BoldDirs = 98
            If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
              If (PLI(xLong1)\DirDepthFlags & #PLI_Depth) = xLong2
                xMarkSong(xLong1, #False, #False)
                Break
                ElseIf (PLI(xLong1)\DirDepthFlags & #PLI_Depth) < xLong2
                Break
                EndIf
              EndIf
            CompilerElse
            If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
              If (PLIDF(xLong1) & #PLI_Depth) = xLong2
                xMarkSong(xLong1, #False, #False)
                Break
                ElseIf (PLIDF(xLong1) & #PLI_Depth) = xLong2
                Break
                EndIf
              EndIf
            CompilerEndIf
          Next
      EndSelect
    EndIf
  ;endif
  
;compilerendif
  EndProcedure

Procedure.i xTimerChange(Index.i, xTimer.i, xEvents.s, IsBlank.i)
  Define.i xLong1
  Define.s xChar1
  
  If Index = -1
    xTimerEvTime(xTimerEvCount) = xTimer
    xTimerEv(xTimerEvCount) = xEvents
    Index = xTimerEvCount
    xTimerEvCount = xTimerEvCount + 1
    Else
    If Not IsBlank
      xTimerEv(Index) = xEvents
      EndIf
    xTimerEvTime(Index) = xTimer
    EndIf
  
  Repeat
    If Index = 0
      Break
      EndIf
    If xTimerEvTime(Index) >= xTimerEvTime(Index - 1)
      Break
      EndIf
    xLong1 = xTimerEvTime(Index)
    xChar1 = xTimerEv(Index)
    xTimerEv(Index) = xTimerEv(Index - 1)
    xTimerEv(Index - 1) = xChar1
    xTimerEvTime(Index) = xTimerEvTime(Index - 1)
    xTimerEvTime(Index - 1) = xLong1
    Index = Index - 1
    ForEver
  Repeat
    If Index = xTimerEvCount - 1
      Break
      EndIf
    If xTimerEvTime(Index) < xTimerEvTime(Index + 1)
      Break
      EndIf
    Break
    xLong1 = xTimerEvTime(Index)
    xChar1 = xTimerEv(Index)
    xTimerEv(Index) = xTimerEv(Index + 1)
    xTimerEv(Index + 1) = xChar1
    xTimerEvTime(Index) = xTimerEvTime(Index + 1)
    xTimerEvTime(Index + 1) = xLong1
    Index = Index + 1
    ForEver
  
  ProcedureReturn Index
  EndProcedure

Procedure.s GetTimeSMQ(Index.i)
  ProcedureReturn xLastPathTime(Index) + "   "
  EndProcedure

Procedure.i SMQueryString(wParam.i, MapFileID.i) ;, AsUnicode As Boolean).i
  Define.i xResult
  Define.i xLong1
  ;im xLong2.i
  Define.i hMapFile
  Define.i hMapFileView
  Define.i hMapFilePos
  Define.i hMapFileSize
  Define.s xChar1
  Define.i CopyMode
  
  xChar1 = "calaym_" + StrU(MapFileID)
  hMapFile = OpenFileMapping_(2, 0, @xChar1)
  If Not hMapFile
    xChar1 = "calaym_" + StrS(MapFileID)
    hMapFile = OpenFileMapping_(2, 0, @xChar1)
    EndIf
  If hMapFile
    hMapFileView = MapViewOfFile_(hMapFile, $F001F, 0, 0, 0)  ;FILE_MAP_ALL_ACCESS
    If hMapFileView
      ;RtlMoveMemory(VarPtr(hMapFileSize), hMapFileView, 4)
      hMapFileSize = GetAccessSize(hMapFileView) >> 1
      If hMapFileSize > 1
        PokeW(hMapFileView, 0)
        hMapFilePos = hMapFileView
        Select wParam
          Case 800, 801
            If xPStateIconPlaying
              If wParam = 801
                xChar1 = GetCurSong(#True)
                Else
                xChar1 = GetCurSong(#False)
                EndIf
              EndIf
            If Not xPStateIconPlaying Or CurMusic = #ctSSLayer_MusicTypeNone Or xPStateIconSndcard Or xPStateIconQuit Or xPStateIconStartup Or PLCurSongLength = 0
              CopyMode = 1
              Else
              CopyMode = 2
              EndIf
          Case 804, 805
            If Not LastLoudestTearID = -1
              If wParam = 804
                xChar1 = LastLoudestTearFn
                Else
                xChar1 = LastLoudestTearCp
                EndIf
              EndIf
            CopyMode = 1
          Case 810 To 817
            Select wParam
              Case 810
                For xLong1 = 0 To xLastPathCount - 1
                  xChar1 = xChar1 + #CRLF$ + GetTimeSMQ(xLong1) + SimpleFile(xLastPath(xLong1))
                  Next
              Case 811
                For xLong1 = 0 To xLastPathCount - 1
                  xChar1 = xChar1 + #CRLF$ + GetTimeSMQ(xLong1) + xLastPath(xLong1)
                  Next
              Case 812
                For xLong1 = 0 To xLastPathCount - 1
                  xChar1 = xChar1 + #CRLF$ + SimpleFile(xLastPath(xLong1))
                  Next
              Case 813
                For xLong1 = 0 To xLastPathCount - 1
                  xChar1 = xChar1 + #CRLF$ + xLastPath(xLong1)
                  Next
              Case 814
                For xLong1 = xLastPathCount - 1 To 0 Step -1
                  xChar1 = xChar1 + #CRLF$ + GetTimeSMQ(xLong1) + SimpleFile(xLastPath(xLong1))
                  Next
              Case 815
                For xLong1 = xLastPathCount - 1 To 0 Step -1
                  xChar1 = xChar1 + #CRLF$ + GetTimeSMQ(xLong1) + xLastPath(xLong1)
                  Next
              Case 816
                For xLong1 = xLastPathCount - 1 To 0 Step -1
                  xChar1 = xChar1 + #CRLF$ + SimpleFile(xLastPath(xLong1))
                  Next
              Case 817
                For xLong1 = xLastPathCount - 1 To 0 Step -1
                  xChar1 = xChar1 + #CRLF$ + xLastPath(xLong1)
                  Next
              EndSelect
            xChar1 = Mid(xChar1, 3)
            xLong1 = Len(xChar1)
            If ((xLong1+1)<<1) <= hMapFileSize
              xResult = xLong1
              PokeS(hMapFileView, xChar1, #PB_Unicode)
              EndIf
          EndSelect
        If CopyMode
          xLong1 = Len(xChar1)
          If Not (xLong1 + 12 > hMapFileSize Or xLong1 + 12 > $FFFF)
            PokeS(hMapFilePos, xChar1, xLong1, #PB_Unicode)
            hMapFilePos + (xLong1 << 1)
            If CopyMode = 1
              PokeL(hMapFilePos, 0) ;     0byte +2
              PokeL(hMapFilePos + 4, 0) ;       +6
              PokeW(hMapFilePos + 8, 0) ;       +10
              Else
              PokeW(hMapFilePos, 0) ;     0byte
              hMapFilePos + 2
              If (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
                PokeB(hMapFilePos+0, #ctSSLayer_MusicTypeInetStream)
                Else
                PokeB(hMapFilePos+0, CurMusic)
                EndIf
              PokeB(hMapFilePos+1, 0) ; reserved
              PokeL(hMapFilePos+2, PLCurSongPos)
              PokeL(hMapFilePos+6, PLCurSongLength)
              EndIf
            If xPStateIconPlaying And Not CurMusic = #ctSSLayer_MusicTypeNone
              If xPStateIconPaused
                xResult = $2000000
                Else
                xResult = $1000000
                EndIf
              EndIf
            xResult | xLong1 | (xRep << 26) | ((xSetVolume >> 5) << 28)
            If xOldIconState = -1
              xResult | $30000
              Else
              xResult | (xOldIconState << 16)
              EndIf
            EndIf
          EndIf
        EndIf
      UnmapViewOfFile_(hMapFileView)
      EndIf
    CloseHandle_(hMapFile)
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.i RemoveDevicesLock(*lParam.DEV_BROADCAST_HDR, IsOnQuery.i)
  Define.i xResult
  Define.i xLong1
  Define *xType1.DEV_BROADCAST_VOLUME
  Define.s xChar1
  Define.i xBool1
  
  If IsDevicePlugging
    xResult = #True
    ElseIf *lParam And Not (PlayerIsLocked Or xAutoDoing Or xPStateIconQuit)
    If *lParam\dbch_devicetype = 6
      xLong1 = RemovableDevices_ResolveDriveID(*lParam)
      If Not xLong1 = -1
        xChar1 = Chr(xLong1 + 65)
        xBool1 = #True
        EndIf
      ElseIf *lParam\dbch_devicetype = 2
      *xType1 = *lParam
      For xLong1 = #FirstNonFloppy To 25
        If (*xType1\dbcv_unitmask & (1 << xLong1))
          xChar1 = xChar1 + Chr(65 + xLong1)
          EndIf
        Next
      xBool1 = #True
      Else
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  ignored (no volume!)")
        CompilerEndIf
      xResult = #True
      EndIf
    If xBool1
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  AffectedVolumes(s): " + xChar1)
        CompilerEndIf
      If Mid(xRealBaseFile, 2, 1) = ":"
        If Not FindString(xChar1, UCase(Left(xRealBaseFile, 1))) = 0
          If xPStateIconQuit
            xResult = #True
            ElseIf xAutoUSBQuit
  ;          Exit Function
  ;QuitHack: ; testing
            If xCmdQuitMode = 3 And IsOnQuery
              If Not IsDevicePlugging
                SendMessage_(MainHWnd, $10, 0, 0)
                If xPStateIconQuit
                  xResult = #True
                  ;Exit Function
                  EndIf
                EndIf
              EndIf
            EndIf
          ProcedureReturn xResult
          EndIf
        EndIf
      
      MainForm_LockMe(#True)
      SetAutoDoing(#True)
      xPStateIconSndcard = #True
      xPStateIconPlugging = #True
      MainForm_UpdateMainIcon()
      IsDevicePlugging = #True
      xResult = #True
  
      For xLong1 = 0 To xAutoDirCount - 1
        If Not xAutoDirHWnd(xLong1) = 0
          If Mid(xAutoDir(xLong1), 2, 1) = ":"
            If Not FindString(xChar1, UCase(Left(xAutoDir(xLong1), 1))) = 0
              CompilerIf #UseFileLogging
                MainForm_ctConsoleA_AddLog("  Temp. disable AR for " + xAutoDir(xLong1))
                CompilerEndIf
              FindCloseChangeNotification_(xAutoDirHWnd(xLong1))
              xAutoDirHWnd(xLong1) = 0
              EndIf
            EndIf
          EndIf
        Next
      EndIf
  ;GoTo QuitHack
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.i RemoveDevicesAffectsVolumes(*lParam.DEV_BROADCAST_HDR)
  Define.i xResult

  If *lParam  
    If *lParam\dbch_devicetype = 2 Or *lParam\dbch_devicetype = 6
      xResult = #True
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure RemoveDevicesUnlock()
  Define.i xLong1
;debug "Unlock?"
  If IsDevicePlugging
;debug "  Unlock!"
    IsDevicePlugging = #False
    HasDevicePlugStoppedSong = #False
    SetAutoDoing(#False)
    xPStateIconPlugging = #False
    xPStateIconSndcard = #False
    If xAutoRefreshTimer(1) > 0
      For xLong1 = 0 To xAutoDirCount - 1
        If xAutoDirHWnd(xLong1) = 0
          If Mid(xAutoDir(xLong1), 2, 1) = ":"
            CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  Re-Enable AR for " + xAutoDir(xLong1))
              CompilerEndIf
            xAutoDirHWnd(xLong1) = FindFirstChangeNotification_(@xAutoDir(xLong1), 1, 3)
            EndIf
          EndIf
        Next
      EndIf
    MainForm_UpdateMainIcon()
    MainForm_LockMe(#False)
    EndIf
  EndProcedure

Procedure RemoveDevices(*lParam.DEV_BROADCAST_HDR, AffectPL.i)
  Define.i xLong1
  Define.s xChar1
  Define.i ByBrdCstHnd
  Define.i UnitMask
  Define *xType1.DEV_BROADCAST_VOLUME

  If *lParam
    If IsDevicePlugging Or Not (PlayerIsLocked Or xAutoDoing Or xPStateIconQuit)
      If *lParam\dbch_devicetype = 6
        xLong1 = RemovableDevices_ResolveDriveID(*lParam)
        If Not xLong1 = -1
          xChar1 = Chr(xLong1 + 65)
          UnitMask = 1 << xLong1
          ByBrdCstHnd = #True
          EndIf
        ElseIf *lParam\dbch_devicetype = 2
        *xType1 = *lParam
        UnitMask = *xType1\dbcv_unitmask
        For xLong1 = #FirstNonFloppy To 25
          If (*xType1\dbcv_unitmask & (1 << xLong1))
            xChar1 = xChar1 + Chr(65 + xLong1)
            EndIf
          Next
        ByBrdCstHnd = #True
        EndIf
      
      
      If ByBrdCstHnd
        IsDevicePlugging = #True
        HasDevicePlugged = #True
        MainForm_LockMe(#True)
        xPStateIconSndcard = #True
        xPStateIconPlugging = #True
        MainForm_UpdateMainIcon()
        CompilerIf #UseFileLogging
          MainForm_ctConsoleA_AddLog("  AffectedDevices: " + xChar1)
          CompilerEndIf
        
        If xPStateIconPlaying And Not (CurMusic = #ctSSLayer_MusicTypeNone)
          If Mid(PLCurSong, 2, 2) = ":\"
  ;          debug "Mask:", Hex(xType1.dbcv_unitmask)
            If (UnitMask & (1 << (Asc(UCase(Left(PLCurSong, 1))) - 65)))
              HasDevicePlugStoppedSong = #True
  CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  CurrentSong: affected")
              Else
              MainForm_ctConsoleA_AddLog("  CurrentSong: not affected")
  CompilerEndIf
              EndIf
  CompilerIf #UseFileLogging
            Else
            MainForm_ctConsoleA_AddLog("  CurrentSong: not affected")
  CompilerEndIf
            EndIf
  CompilerIf #UseFileLogging
          Else
          MainForm_ctConsoleA_AddLog("  CurrentSong: not affected")
  CompilerEndIf
          EndIf
        If AffectPL
          If Mid(PlNextSong, 2, 2) = ":\"
            If (UnitMask & (1 << (Asc(UCase(Left(PlNextSong, 1))) - 65)))
              SetNextSong(#False)
  CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  NextSong: affected")
              Else
              MainForm_ctConsoleA_AddLog("  NextSong: not affected")
  CompilerEndIf
              EndIf
  CompilerIf #UseFileLogging
            Else
            MainForm_ctConsoleA_AddLog("  NextSong: not affected")
  CompilerEndIf
            EndIf
          EndIf
        
        If AffectPL And (xRemoveMissingSongs Or vKioskMode Or xAutoDirCount)
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("  Removing affected songs from list")
            CompilerEndIf
          If xRemoveMissingSongs Or vKioskMode
            MenuEventCDDrive(xChar1, #False, #True)
            Else
            MenuEventCDDrive(xChar1, #False, #False)
            EndIf
          EndIf
    
        If HasDevicePlugStoppedSong Or CurMusic = #ctSSLayer_MusicTypeNone ;And xPStateIconPlaying
          Tear_WaitFor(-2)
          Else
          Tear_WaitFor(-3)
          EndIf
        ;Stop
        EndIf
      
      EndIf
    EndIf
  EndProcedure

Procedure RemoveDevicesAutoAdd(*lParam.DEV_BROADCAST_HDR)
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  Define.s xChar2
  Define *xType1.DEV_BROADCAST_VOLUME

  If *lParam And Not (PlayerIsLocked Or xAutoDoing Or xPStateIconQuit)
    If *lParam\dbch_devicetype = 2
      *xType1 = *lParam
      For xLong1 = #FirstNonFloppy To 25
        If (*xType1\dbcv_unitmask & (1 << xLong1))
          xChar2 = Chr(65 + xLong1)
          If FindString(CDDriveLetters, xChar2)
            xChar1 = xChar1 + Chr(65 + xLong1)
            EndIf
          EndIf
        Next
;ByBrdCstHnd:
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("  AffectedDevices: " + xChar1)
        CompilerEndIf
      If Not Len(xChar1) = 0
        ;ReAutoPlayDR = #False
        MainForm_LockMe(#True)
        xPStateIconRefreshing = #True
        SetAutoDoing(#True)
        MainForm_UpdateMainIcon()
        
        If vKioskMode
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("  Refresh (drives: " + xChar1 + ")")
            CompilerEndIf
          MenuEventCDDrive(xChar1, #True, #True)
          Else
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("Trying AutoRefresh on new device (drives: " + xChar1 + ")")
            CompilerEndIf
          AbortReading = #False
          xLong2 = PLCount
          ReadDirInit()
          For xLong1 = 0 To xAutoDirCount - 1
            If Mid(xAutoDir(xLong1), 2, 1) = ":"
              If Not FindString(xChar1, UCase(Left(xAutoDir(xLong1), 1))) = 0
                If Not xAutoDirHWnd(xLong1) = 0
                  FindCloseChangeNotification_(xAutoDirHWnd(xLong1))
                  EndIf
                CompilerIf #UseFileLogging
                  MainForm_ctConsoleA_AddLog("  adding " + xAutoDir(xLong1))
                  CompilerEndIf
                ReadDirectory(xAutoDir(xLong1), 0, #True, #PLI_IsAuto, Int((#xDefBWDifL * xLong1) / xAutoDirCount), Int(#xDefBWDifL / xAutoDirCount))
                If xAutoRefreshTimer(1) > 0
                  xAutoDirHWnd(xLong1) = FindFirstChangeNotification_(@xAutoDir(xLong1), 1, 3)
                  EndIf
                If AbortReading
                  Break
                  EndIf
                EndIf
              EndIf
            Next
          ReadDirDone()
          If Not PLCount = xLong2
            RealPLAdd(xLong2)
            EndIf
          EndIf
        
        xPStateIconRefreshing = #False
        MainForm_UpdateMainIcon()
        SetAutoDoing(#False)
        MainForm_LockMe(#False)
        CheckReplay()
        CheckOldItems()
        xAutoRefreshTimerEventTime(0) = GetTickTimeMS()
        xAutoRefreshTimerEventTime(1) = xAutoRefreshTimerEventTime(0)
        InitResearch(#False)
        
        CompilerIf #PB_Compiler_Unicode And #XPDeviceRemoveDetect
          CompilerIf #XPDeviceRemoveDetectPST
            PendingDeviceRegB = #True
            PendingDeviceRegT = GetTickTimeMS()
            CompilerElse
            RemovableDevices_UnregisterAll()
            RemovableDevices_RegisterAll(MainHWnd)
            CompilerEndIf
          CompilerEndIf
        EndIf
      ;compilerif #UseFileLogging
      ;  MainForm_ctConsoleA_AddLog("  AutoAddDevices: " + xChar1
      ;  compilerendif
      EndIf
    EndIf
  EndProcedure

CompilerIf #LoadShellDriveIcons
  Procedure MainMenu_MeasureItem(*lParam.MEASUREITEMSTRUCT)
    Define.RECT xType2
    Define.i xLong1
    Define.i xLong2
    Define.i xLong3
    Define.i hFont
    Define.i hFontOld

    If *lParam
      xLong2 = GetSystemMetrics_(45)
      xLong3 = GetSystemMetrics_(71)
      If xLong3 < 16
        xLong3 = 16
        EndIf
      *lParam\itemWidth = xLong3 + 2 * xLong2
      
      xLong2 = *lParam\itemHeight
      If xLong2 < 16
        xLong2 = 16
        EndIf
      xLong3 = GetSystemMetrics_(72)
      If xLong3 > xLong2
        xLong2 = xLong3
        EndIf
      xLong3 = GetSystemMetrics_(15)
      If xLong3 > xLong2
        xLong2 = xLong3
        EndIf
      *lParam\itemHeight = xLong2
      
      If *lParam\ItemID = 0
        xLong1 = *lParam\itemData - 1970
        Else
        xLong1 = *lParam\ItemID - 1970
        EndIf
      If xLong1 > 999
        xLong1 = xLong1 - 1000
        EndIf
      If xLong1 < 26 And Not xLong1 < 0
        hFont = GetStockObject_(13) ;SYSTEM_FONT
        If hFont
          hFontOld = SelectObject_(xSharedDC, hFont)
          If hFontOld
            DrawText_(xSharedDC, @ShellDrvDCap(xLong1), Len(ShellDrvDCap(xLong1)), xType2, $424)
            *lParam\itemWidth = *lParam\itemWidth + xType2\Right
            If xType2\Bottom > *lParam\itemHeight
              *lParam\itemHeight = xType2\Bottom
              EndIf
            SelectObject_(xSharedDC, hFontOld)
            EndIf
          EndIf
        EndIf
      EndIf
    EndProcedure
  
  Procedure.i MainMenu_MenuChar(wParam.i, lParam.i)
    Define.i xResult
    Define.i xLong1
    Define.i xLong2
    Define.i xLong3

    If Not lParam = 0
      wParam = (wParam & $FFFF)
      If wParam > 96
        wParam = wParam - 32
        EndIf
      If wParam > 64 And wParam < 91
        wParam = FindString(CDDriveLetters, Chr(wParam)) - 1
        If Not wParam = -1
          xLong3 = GetMenuItemCount_(lParam) - 1
          For xLong1 = 0 To xLong3
            xLong2 = GetMenuItemID_(lParam, xLong1)
            If xLong2 = 1970 + wParam
              xResult = xLong1 | $20000
              Debug "DefaultMenu!"
              Break
              ElseIf xLong2 = 2970 + wParam
              Debug "GlobalMenu!"
              xResult = xLong1 | $20000
              Break
              EndIf
            Next
          EndIf
        EndIf
      EndIf
    ProcedureReturn xResult
  EndProcedure

  Procedure MainMenu_DrawItem(*lParam)
    Define.DRAWITEMSTRUCT xType1
    Define.i xLong1
    Define.i xLong2
    Define.i xLong3
    Define.i xLong4

    If *lParam
      RtlMoveMemory_(@xType1, *lParam, SizeOf(DRAWITEMSTRUCT))
      If xType1\hdc
        xType1\ItemID - 1970
        If xType1\ItemID > 999
          xType1\ItemID - 1000
          EndIf
        If xType1\ItemID < 26 And Not xType1\ItemID < 0
          xLong1 = GetBkColor_(xType1\hdc)
          xLong2 = GetTextColor_(xType1\hdc)
          xLong3 = GetSystemMetrics_(45)
          If xType1\itemState & $1
            FillRect_(xType1\hdc, @xType1\rcItem, 14)
            SetBkColor_(xType1\hdc, FLineColor)
            SetTextColor_(xType1\hdc, SysColor14)
            Else
            FillRect_(xType1\hdc, @xType1\rcItem, 5)
            EndIf
  
          If Not ShellDrvIcons(ShellDrvDIco(xType1\ItemID)) = 0
            DrawIconEx_(xType1\hdc, xType1\rcItem\left + xLong3, xType1\rcItem\Top + (xType1\rcItem\Bottom - xType1\rcItem\Top - 16) / 2, ShellDrvIcons(ShellDrvDIco(xType1\ItemID)), 16, 16, 0, 0, 3)
            EndIf
          xLong4 = GetSystemMetrics_(71)
          If xLong4 < 16
            xLong4 = 16
            EndIf
          xType1\rcItem\left + xLong4 + 2 * xLong3
          DrawText_(xType1\hdc, @ShellDrvDCap(xType1\ItemID), Len(ShellDrvDCap(xType1\ItemID)), xType1\rcItem, $24)
          SetBkColor_(xType1\hdc, xLong1)
          SetTextColor_(xType1\hdc, xLong2)
          EndIf
        EndIf
      EndIf
    EndProcedure
  CompilerEndIf
  
Procedure DrawPLItem(*lParam)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.i xDrawMode
  
  Define.RECT xType2
  Define.RECT xType3
  Define.i xULCheck
  Define.i xULColor
  Define.i ThisTimeShift
  Define.i xFntOld
  Define.DRAWITEMSTRUCT xType1
  Define.i IndirectDirs
  Define.i PostFakeIconDraw
  Define.i NotNoDraw
  
  If *lParam
    ;11/12 = 44/48
    RtlMoveMemory_(xType1, *lParam, SizeOf(DRAWITEMSTRUCT))
    If xType1\hdc
      Select xType1\hwndItem
        Case xListHWnd(0)
          If Not xType1\ItemID = -1
            ThisTimeShift = PLSIconTopShift
            xType1\ItemID = xDirPath(xType1\ItemID)
            If ShowFullPath
              If PLIconFolder = 0
                xDrawMode = #PLIconFolderFake
                Else
                xDrawMode = PLIconFolder
                EndIf
              EndIf
            IndirectDirs = #True
            EndIf
        Case xListHWnd(1)
          If Not xType1\ItemID = -1
            ThisTimeShift = xDefIconTopShift16
            If PLIconFolder = 0
              xDrawMode = #PLIconFileFake
              Else
              xDrawMode = PLIconFile
              EndIf
            IndirectDirs = #True
            EndIf
        Case Interface_Control(#Interface_Control_Search_Results)
          ThisTimeShift = PLODIconTopShift
          If xSearchCount = 0 Or xSearchCount = #xSearchCountOver Or CPListMustDo
            xDrawMode = -2
            Else
            xDrawMode = -1
            EndIf
  ;        GoTo IndirectDirsFonter
          IndirectDirs = #True
        Case Interface_Control(#Interface_Control_Radio_List)
          ThisTimeShift = PLODIconTopShift
          If PLIconURL = 0
            xDrawMode = -5
            Else
            xDrawMode = -4 ;pliconurl
            EndIf
  ;        GoTo IndirectDirsFonter
          IndirectDirs = #True
        Case xListHWnd(2)
          xDrawMode = 0
          xULCheck = #PLI_IsDir
          ThisTimeShift = PLODIconTopShift
          
          If Not xType1\ItemID = -1
            xType1\ItemID = xType1\itemData
  CompilerIf #BoldDirs = 98
            If (PLI(xType1\itemData)\DirDepthFlags & #PLI_IsDir) = 0
  CompilerElse
            If (PLIDF(xType1\itemData) & #PLI_IsDir) = 0
  CompilerEndIf
              xFntOld = SelectObject_(xType1\hdc, hFontPLLg)
              EndIf
            EndIf
          IndirectDirs = #True
  CompilerIf #LoadShellDriveIcons
        Default
          ;#ODT_MENU.i = 1
          If xType1\CtlType = 1
            MainMenu_DrawItem(*lParam)
            EndIf
  CompilerEndIf
        EndSelect








  If IndirectDirs
    xLong1 = GetBkColor_(xType1\hdc)
    xLong2 = GetTextColor_(xType1\hdc)
    xType3 = xType1\rcItem
    
    If (xType1\itemState & $1)
CompilerIf #ListFocusedLists
      If xType1\hwndItem = xCurFocusHWnd
CompilerEndIf
        FillRect_(xType1\hdc, xType1\rcItem, 14)
        SetBkColor_(xType1\hdc, FLineColor)
        SetTextColor_(xType1\hdc, SysColor14)
CompilerIf #ListFocusedLists
        Else
        FillRect_(xType1\hdc, xType1\rcItem, 16)
        SetBkColor_(xType1\hdc, FormatIconBack)
        SetTextColor_(xType1\hdc, FLineColorWDCTxt)
        EndIf
CompilerEndIf
      Else
      FillRect_(xType1\hdc, xType1\rcItem, 6)
      EndIf
      
    If Not xType1\ItemID = -1
      Select xDrawMode
        Case 0
          CompilerIf #BoldDirs = 98
            xLong3 = 24 + 20 * (PLI(xType1\ItemID)\DirDepthFlags & #PLI_Depth)
            CompilerElse
            xLong3 = 24 + 20 * (PLIDF(xType1\ItemID) & #PLI_Depth)
            CompilerEndIf
          xType1\rcItem\Right - xLong3
          If Not xType1\rcItem\Right < 1
            xType1\rcItem\left + xLong3
CompilerIf #BoldDirs = 98
            DrawText_(xType1\hdc, @PLI(xType1\ItemID)\Caption, Len(PLI(xType1\ItemID)\Caption), xType1\rcItem, $924)   ;$104)
            If (PLI(xType1\ItemID)\DirDepthFlags & xULCheck) = #PLI_IsDir
              xType2 = xType1\rcItem
              DrawText_(xType1\hdc, @PLI(xType1\ItemID)\Caption, Len(PLI(xType1\ItemID)\Caption), xType2, $D24)
CompilerElse
            DrawText_(xType1\hdc, @PLICap(xType1\ItemID), Len(PLICap(xType1\ItemID)), xType1\rcItem, $924) ;$104)
            If (PLIDF(xType1\ItemID) & xULCheck) = #PLI_IsDir
              xType2 = xType1\rcItem
              DrawText_(xType1\hdc, @PLICap(xType1\ItemID), Len(PLICap(xType1\ItemID)), xType2, $D24)
CompilerEndIf
SearchPostUnderline:
              xType2\Top = xType2\Bottom - 1
              xType2\left - 3
              xType2\Right + 4
              
CompilerIf #ListFocusedLists
              If (xType1\itemState & $1) And xType1\hwndItem = xCurFocusHWnd
CompilerElse
              If (xType1\itemState & $1)
CompilerEndIf
                xULColor = 15
                Else
                xULColor = 9
                EndIf
              FillRect_(xType1\hdc, xType2, xULColor)
              Else
              xULCheck = 0
              EndIf
            xType1\rcItem\left - xLong3
            EndIf
        
        Case PLIconFolder, #PLIconFolderFake ;, PLIconURL
          xType1\rcItem\left + 24
CompilerIf #BoldDirs = 98
            DrawText_(xType1\hdc, @PLI(xType1\ItemID)\Filename, Len(PLI(xType1\ItemID)\Filename), xType1\rcItem, $924)
CompilerElse
            DrawText_(xType1\hdc, @PLIFile(xType1\ItemID), Len(PLIFile(xType1\ItemID)), xType1\rcItem\left, $924)
CompilerEndIf
          xType1\rcItem\left - 24
          ;  endif
        Case PLIconFile, #PLIconFileFake
          xType1\rcItem\left + 4
          DrawText_(xType1\hdc, @xLastPathTime(xType1\ItemID), Len(xLastPathTime(xType1\ItemID)), xType1\rcItem, $924)
          xType1\rcItem\left + 20 + xLastPathTimeSpace
          DrawText_(xType1\hdc, @xLastPathCap(xType1\ItemID), Len(xLastPathCap(xType1\ItemID)), xType1\rcItem, $924)
          xType1\rcItem\left - 24 - xLastPathTimeSpace
        Case -1
          xType1\rcItem\left + 24
          xDrawMode = xSearchSortDir(xSearchSortAlias(xType1\ItemID))
          If xDrawMode = -3
            xFntOld = SelectObject_(xType1\hdc, hFontPLLg)
            DrawText_(xType1\hdc, @xSearchSortCap(xSearchSortAlias(xType1\ItemID)), Len(xSearchSortCap(xSearchSortAlias(xType1\ItemID))), xType1\rcItem, $924) ;$104)
            xType1\rcItem\left - 24
            Else
            DrawText_(xType1\hdc, @xSearchSortCap(xSearchSortAlias(xType1\ItemID)), Len(xSearchSortCap(xSearchSortAlias(xType1\ItemID))), xType1\rcItem, $924) ;$104)
CompilerIf #BoldDirs = 98
            xType2 = xType1\rcItem
            DrawText_(xType1\hdc, @xSearchSortCap(xSearchSortAlias(xType1\ItemID)), Len(xSearchSortCap(xSearchSortAlias(xType1\ItemID))), xType2, $D24)
CompilerElse
            xType2 = xType1\rcItem
            DrawText_(xType1\hdc, @xSearchSortCap(xSearchSortAlias(xType1\ItemID)), Len(xSearchSortCap(xSearchSortAlias(xType1\ItemID))), xType2, $D24)
CompilerEndIf
            xType1\rcItem\left - 24
            xULCheck = #PLI_IsDir
            Goto SearchPostUnderline
            EndIf
        
        Case -2
          SetTextColor_(xType1\hdc, SysColor17)
          xType1\rcItem\left + 4
          DrawText_(xType1\hdc, @xSearchError, Len(xSearchError), xType1\rcItem, $924)
          xType1\rcItem\left - 4
        Case -4
          xType1\rcItem\left + 24
          DrawText_(xType1\hdc, @xRadioCap(xType1\ItemID), Len(xRadioCap(xType1\ItemID)), xType1\rcItem, $924)
          xType1\rcItem\left - 24
          ;xDrawMode = PLIconURL
        Case -5
          xType1\rcItem\left + 4
          DrawText_(xType1\hdc, @xRadioCap(xType1\ItemID), Len(xRadioCap(xType1\ItemID)), xType1\rcItem, $924)
          xType1\rcItem\left - 4
          ;xDrawMode = PLIconURL
        EndSelect
      EndIf
    
;NoDrawTxt:
    If Not xType1\ItemID = -1
      Select xDrawMode
        Case 0
CompilerIf #BoldDirs = 98
          If (PLI(xType1\ItemID)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
            If PLIconFolder = 0
              xLong3 = 4 + 20 * (PLI(xType1\ItemID)\DirDepthFlags & #PLI_Depth)
CompilerElse
          If (PLIDF(xType1\ItemID) & #PLI_IsDir) = #PLI_IsDir
            If PLIconFolder = 0
              xLong3 = 4 + 20 * (PLIDF(xType1\ItemID) & #PLI_Depth)
CompilerEndIf
              PostFakeIconDraw = #True
              Else
CompilerIf #BoldDirs = 98
              DrawIconEx_(xType1\hdc, 4 + xType1\rcItem\left + 20 * (PLI(xType1\ItemID)\DirDepthFlags & #PLI_Depth), xType1\rcItem\Top + ThisTimeShift, PLIconFolder, 16, 16, 0, 0, 3)
CompilerElse
              DrawIconEx_(xType1\hdc, 4 + xType1\rcItem\left + 20 * (PLIDF(xType1\ItemID) & #PLI_Depth), xType1\rcItem\Top + ThisTimeShift, PLIconFolder, 16, 16, 0, 0, 3)
CompilerEndIf
              EndIf
            ElseIf Not PLIconFolder = 0
CompilerIf #BoldDirs = 98
            DrawIconEx_(xType1\hdc, 4 + xType1\rcItem\left + 20 * (PLI(xType1\ItemID)\DirDepthFlags & #PLI_Depth), xType1\rcItem\Top + ThisTimeShift, PLIconFile, 16, 16, 0, 0, 3)
CompilerElse
            DrawIconEx_(xType1\hdc, 4 + xType1\rcItem\left + 20 * (PLIDF(xType1\ItemID) & #PLI_Depth), xType1\rcItem\Top + ThisTimeShift, PLIconFile, 16, 16, 0, 0, 3)
CompilerEndIf
            EndIf
        Case PLIconFolder, #PLIconFolderFake
          If PLIconFolder = 0
            xLong3 = 4
            PostFakeIconDraw = #True
            Else
            DrawIconEx_(xType1\hdc, 4 + xType1\rcItem\left, xType1\rcItem\Top + ThisTimeShift, PLIconFolder, 16, 16, 0, 0, 3)
            EndIf
        Case PLIconFile, #PLIconFileFake
          If Not PLIconFolder = 0
            DrawIconEx_(xType1\hdc, 4 + xType1\rcItem\left + xLastPathTimeSpace, xType1\rcItem\Top + ThisTimeShift, PLIconFile, 16, 16, 0, 0, 3)
            EndIf
        Case -3
          If Not PLIconFolder = 0
            DrawIconEx_(xType1\hdc, 4 + xType1\rcItem\left, xType1\rcItem\Top + ThisTimeShift, PLIconFile, 16, 16, 0, 0, 3)
            EndIf
        Case -4
          If Not PLIconFolder = 0
            DrawIconEx_(xType1\hdc, 4 + xType1\rcItem\left, xType1\rcItem\Top + ThisTimeShift, PLIconURL, 16, 16, 0, 0, 3)
            EndIf
        EndSelect
      If Not xFntOld = 0
        SelectObject_(xType1\hdc, xFntOld)
        EndIf
      EndIf

    If PostFakeIconDraw:
      xLong4 = xType1\rcItem\Right
      xType1\rcItem\left + xLong3
      If xType1\rcItem\left + 16 < xType1\rcItem\Right
        xType1\rcItem\Right = xType1\rcItem\left + 16
        NotNoDraw = #True
        ElseIf xType1\rcItem\left > xType1\rcItem\left
        Else
        NotNoDraw = #True
        EndIf
      
      If NotNoDraw
        DrawText_(xType1\hdc, @">", 1, xType1\rcItem, $926)
        If xULCheck = #PLI_IsDir
          xType2 = xType1\rcItem
          DrawText_(xType1\hdc, @">", 1, xType2, $D26)
          xType2\Top = xType2\Bottom - 1
          xType2\Right = (xType2\Right - xType2\left)
          xType2\left = xType1\rcItem\Right - xType2\Right - 3
          xType2\Right = xType1\rcItem\Right + 4
          FillRect_(xType1\hdc, @xType2, xULColor)
          EndIf
        xType1\rcItem\Right = xLong4
        EndIf
      EndIf
    SetBkColor_(xType1\hdc, xLong1)
    SetTextColor_(xType1\hdc, xLong2)
    EndIf






;  NoDraw:
      If (xType1\itemState & $10)
        DrawFocusRect_(xType1\hdc, @xType3)
        EndIf
      EndIf
    EndIf
  EndProcedure

;Commonfiles
;commondir
;DialogTimer
;MessageBox
;winhelp?

Procedure SearchForm_UnInterface()
  CPListMustDo = #False
  
  If Not Interface_Icon = 0
    SendMessage_(Interface_Control(#Interface_Control_Search_Image), $170, 0, 0)
    DestroyIcon_(Interface_Icon)
    Interface_Icon = 0
    EndIf
  EndProcedure

Procedure UnInterface()
  Define.i xLong1
  
  SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_DirList), 0, 0, 0, 0, 19, $215)
  For xLong1 = 0 To #Interface_Control_Last
    If Not Interface_Control(xLong1) = 0
      DestroyWindow_(Interface_Control(xLong1))
      Interface_Control(xLong1) = 0
      EndIf
    Next
  For xLong1 = 0 To #Interface_Control_AccelLast
    Interface_Control_Accel(xLong1) = 0
    Next
  SetForegroundWindow_(MainHWnd)
  SetFocus_(MainHWnd)
  EndProcedure

Procedure SearchForm_Resize(xRight.i, xBottom.i, xTop.i)
  Define.i xLong1
  Define.i xLong2
  
  If Not Interface_Icon = 0
    xLong1 = 2 * eSPTopX + 32
    TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Image), 0, eSPTopX, xTop + (xDefCtlHeight16 + xDefHeight16 - 32) / 2, 32, 32, $215)
    EndIf
  xLong2 = xRight - xLong1
  If xLong2 < 0
    xLong2 = 0
    EndIf
  TrDeferWindowPos(Interface_Control(#Interface_Control_Search_CapLabel), 0, xLong1, xTop, xLong2, xDefHeight16, $214)
  xTop = xTop + xDefHeight16
  TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Txt), 0, xLong1, xTop, xLong2, xDefCtlHeight16, $214)
  xTop = xTop + xDefCtlHeight16 + eSPTopY
  ;TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Txt), 0, 0, 16, xRight, 19, $216)
  ;TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_DirList), 0, 0, 20 + xTop, xRight, 19, $214)
  xBottom = xBottom - 2 * eSPTopY - xTop - xDefButtonHeight - xDefHeight16
  If xBottom < xDefCtlHeight16 - xDefHeight16
    xBottom = xDefCtlHeight16 - xDefHeight16
    EndIf

  TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Results), 0, 0, xTop, xRight, xBottom, $214)
  xTop = xTop + xBottom + eSPTopY

  xLong1 = (xRight - eSPTopX * 3) / 2
  If xLong1 < 0
    xLong1 = 0
    EndIf
  TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Check1), 0, eSPTopX, xTop, xLong1, xDefHeight16, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Check2), 0, xLong1 + 2 * eSPTopX, xTop, xLong1, xDefHeight16, $214)
  xTop = xTop + eSPTopY + xDefHeight16

  xLong1 = (xRight - eSPTopX * 4) / 3
  If xLong1 < 0
    xLong1 = 0
    EndIf
  TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Play), 0, eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Select), 0, xLong1 + 2 * eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Search_Return), 0, (xLong1 + eSPTopX) * 2 + eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  
  EndProcedure

Procedure SearchForm_CheckBoxTxtChange()
  Define.s xChar1
  xChar1 = LoadResString(2310 + PlDClickAction)
  SetWindowText_(Interface_Control(#Interface_Control_Search_SpecialCheck), @xChar1)
  SetAccel(#Interface_Control_Search_SpecialCheck, 2310 + PlDClickAction)
  EndProcedure

Procedure InterfacePlayer(ShowMode.i)
  ;define.i xLong1
  ;
  If xDirListModeCur = 2
    If Not HWndSplitterLW = 0
      ShowWindow_(HWndSplitterLW, ShowMode)
      EndIf
    If Not HWndSplitterMoveLW = 0
      ShowWindow_(HWndSplitterMoveLW, ShowMode)
      EndIf
    Else
    If Not HWndSplitterTH = 0
      ShowWindow_(HWndSplitterTH, ShowMode)
      EndIf
    If Not HWndSplitterMoveTH = 0
      ShowWindow_(HWndSplitterMoveTH, ShowMode)
      EndIf
    EndIf
  If Not xListHWnd(2) = 0
    ShowWindow_(xListHWnd(2), ShowMode)
    EndIf
  If IsWindowVisible_(xListHWnd(1))
    ShowWindow_(xListHWnd(0), 0)
    DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
    EndIf
;    If Not xListHWnd(0) = 0
;      ShowWindow_(xListHWnd(0), 0)
;      EndIf
  
  If ShowMode = 0 And CurShownToolTip = #xStaticIcons_DirList
    CurShownToolTip = -1
    If ToolTipInitTime = -1
      ShowWindow_(xStaticIconsHWnd(#xStaticIcons_ToolTip), 0)
      EndIf
    EndIf
  If xDirListModeCur = 0
    ShowWindow_(xStaticIconsHWnd(#xStaticIcons_DirList), ShowMode)
    Else
    ShowWindow_(xStaticIconsHWnd(#xStaticIcons_DirList), 0)
    EndIf
  If ShowMode = 0 ;And xDirList > 0
    ShowWindow_(xListHWnd(0), 0)
    ElseIf xDirListModeCur > 0
    ShowWindow_(xListHWnd(0), 5)
    EndIf
  If ShowMode = 0 Or xMenu(0) = 0
    SetMenu_(MainHWnd, 0)
    Else
    SetMenu_(MainHWnd, xMenu(0))
    EndIf
  EndProcedure

Procedure BestFocus()
  Select InterfaceMode
    Case #Interface_Mode_None:   SetFocus_(xListHWnd(2))
    Case #Interface_Mode_Search: SetFocus_(Interface_Control(#Interface_Control_Search_Txt))
    Case #Interface_Mode_Timer:  SetFocus_(Interface_Control(#Interface_Control_Timer_List))
    Case #Interface_Mode_Radio:
      If Len(xRadioLastEnteredURL) = 0 And xRadioCount And Interface_Control(#Interface_Control_Radio_List)
        SetFocus_(Interface_Control(#Interface_Control_Radio_Txt))
        ElseIf CanIRadio And Interface_Control(#Interface_Control_Radio_Txt)
        SetFocus_(Interface_Control(#Interface_Control_Radio_Txt))
        ElseIf Interface_Control(#Interface_Control_Radio_Return)
        SetFocus_(Interface_Control(#Interface_Control_Radio_Return))
        EndIf
    Case #Interface_Mode_Wizard: SetFocus_(Interface_Control(#Interface_Control_Wizard_Holder))
    EndSelect
  EndProcedure

Procedure TimerListForm_LoadTimerDlg()
  Define.s xChar1
  
  xChar1 = CalaymLoadSingleFile(LoadResString(1605) + #FileFilterVBNullChar + "*.cpt", LoadResString(1600), TimerDir, MainHWnd, #False)
  If Not xChar1 = ""
    MainForm_LoadTimers(MainHWnd, xChar1, #False)
    EndIf
  EndProcedure

Procedure TimerListForm_MenuEvent(wParam.i)
  Select wParam
    Case 2608
      TimerListForm_LoadTimerDlg()
    Case 2609
      MainForm_SaveTimers(MainHWnd, "", #False)
    Case 2600 To 2604
      TimerListForm_TrySCommandEx(MainHWnd, wParam - 2600)
    Case 2699
      ToggleInterface(#Interface_Mode_None)
    EndSelect
  EndProcedure

Procedure.i TimerListForm_ListProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Select Message
    Case $100
      Select wParam
        Case 46
          TimerListForm_TrySCommandEx(MainHWnd, 2)
        Case 93
          If (lParam & $40000000) = 0
            TimerListForm_MenuEvent(GetAPIPopupMenu(MainHWnd, TimerListForm_xMenu2, Interface_Control(#Interface_Control_Timer_List)))
            EndIf
        Case 9
          LoadResEx_Window_ManualTab(MainHWnd, hWnd)
        Case 27
          ToggleInterface(#Interface_Mode_None)
        EndSelect
    Case $105 ;syskeyup
      TimerListForm_TryAccel(wParam)
    Case $205 ;rightmouseup
      If Not TimerListForm_xLocked
        TimerListForm_MenuEvent(TrackListBox(xStaticIconsHWnd(#xStaticIcons_ShowIR), hWnd, SignedHigherWord(lParam), #True, TimerListForm_xMenu2, 1))
        EndIf
    Case $203 ; l-dblclick
      If Not xTimerEvCount = 0
        TimerListForm_TrySCommandEx(MainHWnd, 1)
        EndIf
    Default
      ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
    EndSelect
  ProcedureReturn 0
  EndProcedure




Procedure.i TimerListForm_ButtonProc(hWnd.i, Message.i, wParam.i, lParam.i)
  If Message = $100
    If wParam = 9
      LoadResEx_Window_ManualTab(MainHWnd, hWnd)
      ProcedureReturn 0
      ElseIf wParam = 27
      ToggleInterface(#Interface_Mode_None)
      ProcedureReturn 0
      EndIf
    ElseIf Message = $105 ;And (lParam & $40000000) = 0
    TimerListForm_TryAccel(wParam)
    EndIf
  ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
  EndProcedure


Procedure TimerListForm_Interface()
  Define.i xLong1

  TimerListForm_xMenu = LoadResEx_Menu(2600)
  TimerListForm_xMenu2 = LoadResEx_Menu(2610)
  If Not TimerListForm_xMenu = 0
    SetMenu_(MainHWnd, TimerListForm_xMenu)
    DrawMenuBar_(MainHWnd)
    EndIf
    
  Interface_Icon = LoadResEx_Image_MultiOS(#PLIconTimer_ResID, 1, 32)
  If Interface_Icon
    Interface_Control(#Interface_Control_Timer_Image) = CreateWindowExOC(0, #W_STATIC, "", $56000003, 0, 4, 32, 32, MainHWnd, 0, 0)
    If Interface_Control(#Interface_Control_Timer_Image) = 0
      DestroyIcon_(Interface_Icon)
      Interface_Icon = 0
      Else
      SendMessage_(Interface_Control(#Interface_Control_Timer_Image), $170, Interface_Icon, 0)
      EndIf
    EndIf

  TimerListUpdateHWnd = CreateWindowExOC(0, #W_STATIC, ReplaceString(LoadResString(2600), "$", GetTimeFormatNow()), $56000000, 4, 3, 417, 17, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Timer_CapLabel) = TimerListUpdateHWnd


  TimerListForm_xPopupMenu2 = MakePopupMenu(TimerListForm_xMenu2)
  If xSecureMode
    EnableMenuItem_(TimerListForm_xMenu, 2601, 3)
    EndIf
  If xSecureMode
    EnableMenuItem_(TimerListForm_xMenu2, 2601, 3)
    EndIf
    
  SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Anim), 0, 0, 0, 0, 0, $213)
    
  Interface_Control(#Interface_Control_Timer_List) = CreateWindowExOC($200, #W_LISTBOX, "", $56311988, 0, 0, 409, 220, MainHWnd, 0, 0)
  
  For xLong1 = 0 To #Interface_Control_Timer_Close
    Interface_Control(xLong1) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2605 + xLong1), $56010000, 8 + 80 * xLong1, 224, 80, 25, MainHWnd, 0, 0)
    If Not Interface_Control(xLong1) = 0
      SetAccel(xLong1, 2605 + xLong1)
      HookWindow(Interface_Control(xLong1), @TimerListForm_ButtonProc())
      EndIf
    Next
  SetAccel(#Interface_Control_Timer_List, 2600)


  TimerListForm_UpdateTimerListWinFont(hFontGFix)
  
  If Not Interface_Control(#Interface_Control_Timer_List) = 0
    HookWindow(Interface_Control(#Interface_Control_Timer_List), @TimerListForm_ListProc())
    EndIf
  
  
  TimerListForm_ListUpdate()
  
  If Not Interface_Control(#Interface_Control_Timer_List) = 0
    SetFocus_(Interface_Control(#Interface_Control_Timer_List))
    EndIf
  EndProcedure


Procedure TimerListForm_UnInterface()
  MainForm_SetTimerImage()
  EnableWindow_(MainHWnd, 1)
  
  
  If Not Interface_Icon = 0
    SendMessage_(Interface_Control(#Interface_Control_Timer_Image), $170, 0, 0)
    DestroyIcon_(Interface_Icon)
    Interface_Icon = 0
    EndIf
  
  If TimerListForm_xMenu2
    DestroyMenu_(TimerListForm_xMenu2)
    EndIf
  If TimerListForm_xPopupMenu2
    DestroyMenu_(TimerListForm_xPopupMenu2)
    EndIf
  ;TimerListMainHWnd = 0
  TimerListUpdateHWnd = 0
  TimerListForm_xLocked = #False
  SetForegroundWindow_(MainHWnd)
  SetFocus_(MainHWnd)
  EndProcedure




Procedure TimerListForm_Resize(xRight.i, xBottom.i, xTop.i)
  Define.i xLong1
  Define.i xLong2
  
  If Not Interface_Icon = 0
    xLong1 = 2 * eSPTopX + 32
    TrDeferWindowPos(Interface_Control(#Interface_Control_Timer_Image), 0, eSPTopX, xTop + (xDefCtlHeight16 + xDefHeight16 - 32) / 2, 32, 32, $215)
    EndIf
  xLong2 = xRight - xLong1
  If xLong2 < 0
    xLong2 = 0
    EndIf
  TrDeferWindowPos(Interface_Control(#Interface_Control_Timer_CapLabel), 0, xLong1, xTop, xLong2, 2 * xDefHeight16, $214)
  xTop = xTop + 2 * xDefHeight16 + eSPTopY

  xBottom = xBottom - eSPTopY - xTop - xDefButtonHeight
  If xBottom < xDefCtlHeight16 - xDefHeight16
    xBottom = xDefCtlHeight16 - xDefHeight16
    EndIf
  TrDeferWindowPos(Interface_Control(#Interface_Control_Timer_List), 0, 0, xTop, xRight, xBottom, $214)

  xTop = xTop + xBottom + eSPTopY
  xLong1 = (xRight - eSPTopX * 6) / 5
  If xLong1 < 0
    xLong1 = 0
    EndIf
  
  For xLong2 = 0 To 4
    TrDeferWindowPos(Interface_Control(xLong2), 0, (xLong1 + eSPTopX) * xLong2 + eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
    Next
  EndProcedure

Procedure TimerListForm_ButtonEvent(hWnd.i) ;, wParam.i)
  ; -> TimerListForm_TrySCommandEx
  Define.i xLong1
  
  For xLong1 = 0 To #Interface_Control_Timer_Close
    If Interface_Control(xLong1) = hWnd
      TimerListForm_TrySCommandEx(MainHWnd, xLong1)
      Break
      EndIf
    Next
  EndProcedure

Procedure TimerListForm_DoneTimerEditing()
  Define.i xBool1
  Define.i xLong1
  
  If ((xTimerEvCount < #xTimerEvMax Or (xTimerEvCount = #xTimerEvMax And Not xTimerEvIR = -1))) And Not (PlayerIsLocked Or TimerListForm_xLocked)
    xBool1 = #True
    Else
    xLong1 = 3
    EndIf
  
  EnableWindow_(Interface_Control(#Interface_Control_Timer_Add), xBool1)
  EnableMenuItem_(TimerListForm_xMenu, 2600, xLong1)
  EnableMenuItem_(TimerListForm_xMenu2, 2600, xLong1)
  If Not (xTimerEvCount = 0 Or PlayerIsLocked Or TimerListForm_xLocked)
    xBool1 = #True
    Else
    xBool1 = #False
    EndIf
  EnableWindow_(Interface_Control(#Interface_Control_Timer_Edit), xBool1)
  EnableWindow_(Interface_Control(#Interface_Control_Timer_Remove), xBool1)
  EnableWindow_(Interface_Control(#Interface_Control_Timer_RemoveAll), xBool1)
  If xBool1
    If Not xSecureMode
      EnableMenuItem_(TimerListForm_xMenu, 2609, 0)
      EnableMenuItem_(TimerListForm_xMenu2, 2609, 0)
      EndIf
    xLong1 = 0
    Else
    EnableMenuItem_(TimerListForm_xMenu, 2609, 3)
    EnableMenuItem_(TimerListForm_xMenu2, 2609, 3)
    xLong1 = 3
    EndIf
  EnableMenuItem_(TimerListForm_xMenu, 2601, xLong1)
  EnableMenuItem_(TimerListForm_xMenu2, 2601, xLong1)
  EnableMenuItem_(TimerListForm_xMenu, 2602, xLong1)
  EnableMenuItem_(TimerListForm_xMenu2, 2602, xLong1)
  EnableMenuItem_(TimerListForm_xMenu, 2603, xLong1)
  EnableMenuItem_(TimerListForm_xMenu2, 2603, xLong1)
  EndProcedure

Procedure TimerListForm_UpdateTimerListWidths(xLen.i, xLenPL.i)
  Dim xLongA1.l(2)
  If xLen = 0
    SendMessage_(Interface_Control(#Interface_Control_Timer_List), $192, 0, 0)  ;xLongA1(0))
    SendMessage_(Interface_Control(#Interface_Control_Timer_List), $194, 0, 0)
    Else
    xLongA1(0) = xTimerDisplayExtraLen * xGlobalDialogUnitsGFix ;* 4
    xLongA1(1) = (xTimerDisplayExtraLen + xLen + #xTimerDisplaySpace2) * xGlobalDialogUnitsGFix ;* 4
    If xLenPL = 0
      SendMessage_(Interface_Control(#Interface_Control_Timer_List), $192, 2, @xLongA1(0))
      SendMessage_(Interface_Control(#Interface_Control_Timer_List), $194, xLen + 4 + xTimerDisplayExtraLenT, 0)
      Else
      xLongA1(2) = (xTimerDisplayExtraLenT + xLen + #xTimerDisplaySpace2) * xGlobalDialogUnitsGFix  ;* 4
      SendMessage_(Interface_Control(#Interface_Control_Timer_List), $192, 3, @xLongA1(0))
      SendMessage_(Interface_Control(#Interface_Control_Timer_List), $194, xLen + 4 + xTimerDisplayExtraLenT + xLenPL + #xTimerDisplaySpace2, 0)
      EndIf
    EndIf
  EndProcedure

Procedure TimerListForm_TrySCommandEx(hWndOwner.i, Index.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.s xChar1
  Define.s xChar2
  Define.i xLong4
  
  If Not TimerListForm_xLocked
    If IsWindowEnabled_(Interface_Control(Index))
      Select Index
        Case 0
          xTimerEvMode = -1
          ShowTimerEditor()
          TimerListForm_DoneTimerEditing()
        Case 1
          If GetListIndexMS(Interface_Control(#Interface_Control_Timer_List), @xTimerEvMode)
          ;If eList.SelCount = 1
            ;xTimerEvMode = eList.ListIndex
            ;If Not xTimerEvMode = -1 Or xTimerEvMode = xTimerEvIR
            If Not xTimerEvMode = xTimerEvIR
              ;TimerListForm_xLocked = #True
              ShowTimerEditor()
              TimerListForm_DoneTimerEditing()
              EndIf
            EndIf
        Case 2
          xTimerEditing = #True
          xTimerEvCount = 0
          SelectObject_(xSharedDC, hFontGSys)
          hWndOwner = xTimerEvCount - 1
          For xLong1 = 0 To hWndOwner
            If SendMessage_(Interface_Control(#Interface_Control_Timer_List), #LB_GETSEL, xTimerEvCount, 0) = 0
              If xLong1 = xTimerEvIR
                xTimerEvIR = xTimerEvCount
                EndIf
              xTimerEvTime(xTimerEvCount) = xTimerEvTime(xLong1)
              xTimerEv(xTimerEvCount) = xTimerEv(xLong1)
              
              xTimerDisplayLastParamValue = xChar2
              xChar1 = MainForm_xTimerDisplay(xLong1, 0, 0)
              xChar2 = xTimerDisplayLastParamValue
              xLong4 = GetTextOutWidth(xSharedDC, xChar1)
              If xLong4 > xLong2
                xLong2 = xLong4
                EndIf
              If Not xChar2 = ""
                xLong4 = GetTextOutWidth(xSharedDC, xChar2)
                If xLong4 > xLong3
                  xLong3 = xLong4
                  EndIf
                EndIf
              xTimerEvCount = xTimerEvCount + 1
              Else
              If xLong1 = xTimerEvIR
                xTimerEvIR = -1
                EndIf
              SendMessage_(Interface_Control(#Interface_Control_Timer_List), #LB_DELETESTRING, xTimerEvCount, 0)
              EndIf
            Next
          TimerListForm_DoneTimerEditing()
          TimerListForm_UpdateTimerListWidths(xLong2, xLong3)
          MainForm_SetTimerImage()
          xTimerEditing = #False
        Case 3
          If Not xTimerEvIR = -1
            If CalaymMessageBox(hWndOwner, LoadResString(1619), LoadResString(1618), 68) = #IDNO
              xTimerEvIR = -1
              EndIf
            EndIf
          SendMessage_(Interface_Control(#Interface_Control_Timer_List), $184, 0, 0)
          If xTimerEvIR = -1
            xTimerEvCount = 0
            Else
            xTimerEv(0) = xTimerEv(xTimerEvIR)
            xTimerEvTime(0) = xTimerEvTime(xTimerEvIR)
            xTimerDisplayLastParamValue = ""
            xChar1 = MainForm_xTimerDisplay(0, 1, 0)
            SendMessage_(Interface_Control(#Interface_Control_Timer_List), #LB_ADDSTRING, 0, @xChar1)
            ;eList.AddItem xChar1
            xTimerDisplayLastParamValue = xChar2
            xChar1 = MainForm_xTimerDisplay(0, 0, 0)
            xChar2 = xTimerDisplayLastParamValue
            SelectObject_(xSharedDC, hFontGFix)
            xLong1 = GetTextOutWidth(xSharedDC, xChar1)
            If xChar2 = ""
              xLong1 = 0
              Else
              xLong1 = GetTextOutWidth(xSharedDC, xChar2)
              EndIf
            xTimerEvCount = 1
            xTimerEvIR = 0
            EndIf
          TimerListForm_DoneTimerEditing()
          TimerListForm_UpdateTimerListWidths(xLong1, xLong1)
          MainForm_SetTimerImage()
        Case 4
          ToggleInterface(#Interface_Mode_None)
        EndSelect
      EndIf
    EndIf
  EndProcedure

Procedure TimerListForm_UpdateTimerListWinFont(xFont.i)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.s xChar1

  For xLong1 = 0 To #Interface_Control_Timer_LastFont
    SendMessage_(Interface_Control(xLong1), $30, xFont, 1)
    Next
  xTimerDisplayExtraLen = 0
  SelectObject_(xSharedDC, xFont)
  For xLong1 = 0 To 9
    xChar1 = Chr(48 + xLong1) + Chr(48 + xLong1) + ":" + Chr(48 + xLong1) + Chr(48 + xLong1)
    xLong2 = GetTextOutWidth(xSharedDC, xChar1) + #xTimerDisplaySpace1
    If xLong2 > xTimerDisplayExtraLen
      xTimerDisplayExtraLen = xLong2
      EndIf
    
    xChar1 = ReplaceString(LoadResString(2655), "$", xChar1)
    xLong2 = GetTextOutWidth(xSharedDC, xChar1)
    If xLong2 > xLong3
      xLong3 = xLong2
      EndIf
    Next
  xTimerDisplayExtraLenT = xTimerDisplayExtraLen + xLong3 + #xTimerDisplaySpace2
  ;debug "WidthInitial:", xTimerDisplayExtraLen, xLong3, xTimerDisplayExtraLenT
  EndProcedure

Procedure TimerListForm_ListUpdate()
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.i xLong5
  Define.s xChar1
  Define.s xChar2
  ;Dim xType1 As POINT
  
  If xTimerEvCount = 0
    xLong2 = -1
    Else
    GetListIndexMS(Interface_Control(#Interface_Control_Timer_List), @xLong2)
    EndIf
  
  ResortTimers()
  
  SendMessage_(Interface_Control(#Interface_Control_Timer_List), $184, 0, 0)
  CompilerIf #TimeTestDebug
    MainForm_ctConsoleA_AddLog("TimeDebug: Refreshing list"
    CompilerEndIf
  SelectObject_(xSharedDC, hFontGFix)
  For xLong1 = 0 To xTimerEvCount - 1
    xTimerDisplayLastParamValue = ""
    xChar1 = MainForm_xTimerDisplay(xLong1, 1, 0)
    SendMessage_(Interface_Control(#Interface_Control_Timer_List), #LB_ADDSTRING, 0, @xChar1)
    xTimerDisplayLastParamValue = xChar2
    xChar1 = MainForm_xTimerDisplay(xLong1, 0, 0)
    xChar2 = xTimerDisplayLastParamValue
    xLong5 = GetTextOutWidth(xSharedDC, xChar1)
    If xLong5 > xLong3
      xLong3 = xLong5
      EndIf
    If Not xChar2 = ""
      xLong5 = GetTextOutWidth(xSharedDC, xChar2)
      If xLong5 > xLong4
        xLong4 = xLong5
        EndIf
      EndIf
    ;If xLong3 > xLong4
      ;xLong4 = xLong3
      ;endif
    CompilerIf #TimeTestDebug
      xTimerDisplayLastParamValue = ""
      MainForm_ctConsoleA_AddLog("           " & "(" & CStr(xTimerEvTime(xLong1)) & "): " & MainForm_xTimerDisplay(xLong1, 2, 0)
      CompilerEndIf
    Next
  
  If Not xTimerEvCount = 0
    If xLong2 = -1
      xLong2 = 0
      EndIf
    SetListIndexMS(Interface_Control(#Interface_Control_Timer_List), xLong2)
    EndIf
  
  TimerListForm_DoneTimerEditing()
  GrabError()
  xTimerEvUpdateTimer = GetLocalTimeHMS_HS()
  TimerListForm_UpdateTimerListWidths(xLong3, xLong4)
  MainForm_SetTimerImage()
  EndProcedure

Procedure TimerListForm_ApplyLockState()
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3

  ;If InterfaceMode = #Interface_Mode_timer
    If PlayerIsLocked Or TimerListForm_xLocked
      xLong2 = 3
      EndIf
    xLong2 = xLong2 + $400
    xLong3 = GetMenuItemCount_(TimerListForm_xMenu) - 1
    For xLong1 = 0 To xLong3
      EnableMenuItem_(TimerListForm_xMenu, xLong1, xLong2)
      Next
    DrawMenuBar_(MainHWnd)
    If PlayerIsLocked Or TimerListForm_xLocked
      For xLong1 = 0 To #Interface_Control_Timer_RemoveAll ;#Interface_Control_Timer_List
        If Not xLong1 = #Interface_Control_Timer_Close
          EnableWindow_(Interface_Control(xLong1), 0)
          EndIf
        Next
      Else
      If xTimerEvCount < #xTimerEvMax Or (xTimerEvCount = #xTimerEvMax And Not xTimerEvIR = -1)
        xLong1 = #True
        Else
        xLong1 = #False
        EndIf
      EnableWindow_(Interface_Control(#Interface_Control_Timer_Add), xLong1)
      If xTimerEvCount
        xLong2 = #True
        Else
        xLong2 = #False
        EndIf
      For xLong1 = #Interface_Control_Timer_Edit To #Interface_Control_Timer_RemoveAll
        EnableWindow_(Interface_Control(xLong1), xLong2)
        Next
      EndIf
    ;endif
  EndProcedure

Procedure TimerListForm_ReDetectWidth()
  Define.i xLong1
  Define.i xLong3
  Define.i xLong4
  Define.i xLong5
  Define.s xChar1
  Define.s xChar2
  
  SelectObject_(xSharedDC, hFontGFix)
  For xLong1 = 0 To xTimerEvCount - 1
    xTimerDisplayLastParamValue = xChar2
    xChar1 = MainForm_xTimerDisplay(xLong1, 0, 0)
    xChar2 = xTimerDisplayLastParamValue
    xLong5 = GetTextOutWidth(xSharedDC, xChar1)
    If xLong5 > xLong3
      xLong3 = xLong5
      EndIf
    If Not xChar2 = ""
      xLong5 = GetTextOutWidth(xSharedDC, xChar2)
      If xLong5 > xLong4
        xLong4 = xLong5
        EndIf
      EndIf
    Next
  
  TimerListForm_UpdateTimerListWidths(xLong3, xLong4)
  EndProcedure

Procedure RadioForm_DetectListWidth()
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xFntS
  
  xFntS = SelectObject_(xSharedDC, hFontPLLg)
  For xLong1 = 0 To xRadioCount - 1
    xLong2 = GetTextOutWidth(xSharedDC, xRadioCap(xLong1))
    If xLong2 > xLong3
      xLong3 = xLong2
      EndIf
    Next
  If Not PLIconURL = 0
    xLong3 = xLong3 + 20
    EndIf
  SendMessage_(Interface_Control(#Interface_Control_Radio_List), $194, 8 + #lWidth + xLong3, 0)
  SelectObject_(xSharedDC, xFntS)
  EndProcedure

Procedure RadioForm_UpdateFont(HWndFont.i, UpdateFlag.i)
  Define.i xLong1

  For xLong1 = 0 To #Interface_Control_Radio_LastFontApply
    SendMessage_(Interface_Control(xLong1), $30, HWndFont, UpdateFlag)
    Next
  RadioForm_DetectListWidth()
  EndProcedure

Procedure RadioForm_TryAccel(wParam.i)
  Define.i xLong1
  
  ;If wParam = 40 Or wParam = 38
  If wParam = 93
;    debug "Radio menu key 2"
    Else
    For xLong1 = 0 To #Interface_Control_Radio_LastAccel
      If Interface_Control_Accel(xLong1) = wParam
;debug "Accelerator:", xLong1
        SetFocus_(Interface_Control(#Interface_Control_Radio_List))
        If Not xLong1 = #Interface_Control_Radio_List
          CheckboxAccelerate(Interface_Control(xLong1))
          RadioForm_TrySCommand(Interface_Control(xLong1))
          EndIf
        Break
        EndIf
      Next
    EndIf
  EndProcedure

Procedure.i RadioForm_ButtonProc(hWnd.i, Message.i, wParam.i, lParam.i)
  If Message = $100
    If wParam = 9
      LoadResEx_Window_ManualTab(MainHWnd, hWnd)
      ProcedureReturn 0
      ElseIf wParam = 27
      ToggleInterface(#Interface_Mode_None)
      ProcedureReturn 0
      EndIf
    ElseIf Message = $105 ;And (lParam & $40000000) = 0
    RadioForm_TryAccel(wParam)
    EndIf
  ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure RadioForm_StartManualURL()
  Define.s xChar1
  
  If CanIRadio
    xChar1 = GetWindowText(Interface_Control(#Interface_Control_Radio_Txt))
    If Not Len(xChar1) = 0
      If StartWeb(xChar1, #True)
        xRadioLastEnteredURL = xChar1
        If xRadioAutoClose
          ToggleInterface(#Interface_Mode_None)
          EndIf
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure.i RadioForm_TextProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Select Message
    Case $100
      ;down
      Select wParam
        Case 9
          LoadResEx_Window_ManualTab(MainHWnd, hWnd)
          ProcedureReturn 0
        Case 27
          ToggleInterface(#Interface_Mode_None)
          ProcedureReturn 0
        ;33=pgup, 34=pgdown, 36=home, 35=end
        Case 13
          RadioForm_StartManualURL()
          ProcedureReturn 0
        EndSelect
    Case $101
      ;up
      Select wParam
        Case 9, 13
          ProcedureReturn 0
        EndSelect
    Case $105
      RadioForm_TryAccel(wParam)
    EndSelect
  ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure RadioForm_MenuEvent(MenuID.i)
  Select MenuID
    Case 2802: RadioForm_TrySCommand(Interface_Control(#Interface_Control_Radio_Play))
    Case 2803: RadioForm_TrySCommand(Interface_Control(#Interface_Control_Radio_OpenHP))
    Case 2805: RadioForm_TrySCommand(Interface_Control(#Interface_Control_Radio_Add))
    Case 2806: RadioForm_TrySCommand(Interface_Control(#Interface_Control_Radio_Edit))
    Case 2807: RadioForm_TrySCommand(Interface_Control(#Interface_Control_Radio_Remove))
    Case 2899: ToggleInterface(#Interface_Mode_None)
    EndSelect
  EndProcedure

Procedure.i RadioForm_ResultListProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Select Message
    ;Case $200 ;move
    ;Case $201, $204 ;down
    Case $203 ;dblclick
      RadioForm_TrySCommand(Interface_Control(#Interface_Control_Radio_Play))
    Case $205 ;up
      wParam = HookedWindowProc(hWnd, Message, wParam, lParam)
      If Not (PlayerIsLocked Or xAutoDoing) ; Or xRadioCount = 0)
        RadioForm_MenuEvent(TrackListBox(xStaticIconsHWnd(#xStaticIcons_ShowIR), hWnd, SignedHigherWord(lParam), #True, xRadioMenu2, 1))
        EndIf
      ProcedureReturn wParam
    Case $100
      lParam = HookedWindowProc(hWnd, Message, wParam, lParam)
      Select wParam
        Case 9
          LoadResEx_Window_ManualTab(MainHWnd, hWnd)
        Case 13
          RadioForm_TrySCommand(Interface_Control(#Interface_Control_Radio_Play))
        Case 27
          ToggleInterface(#Interface_Mode_None)
        Case 93 ;menukey
          If Not (PlayerIsLocked Or xAutoDoing)
            ;debug "Radio menu key"
            RadioForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xRadioMenu2, Interface_Control(#Interface_Control_Radio_List)))
            EndIf
        EndSelect
      ProcedureReturn lParam
    Case $105
      RadioForm_TryAccel(wParam)
    Case $203 ; WM_LBUTTONDBLCLK
      lParam = HookedWindowProc(hWnd, Message, wParam, lParam)
      RadioForm_TrySCommand(Interface_Control(#Interface_Control_Radio_Play))
      ProcedureReturn lParam
CompilerIf #ListFocusedLists
    Case 7
      xCurFocusHWnd = hWnd
    Case 8
      xCurFocusHWnd = wParam
CompilerEndIf
    EndSelect
  ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure RadioForm_Interface()
  Define.i xLong1

  If CanIRadio
    Interface_Icon = LoadResEx_Image_MultiOS(#PLIconRadio_ResID1, 1, 32)
    Else
    Interface_Icon = LoadResEx_Image_MultiOS(#PLIconRadio_ResID2, 1, 32)
    EndIf
  If Not Interface_Icon = 0
    Interface_Control(#Interface_Control_Radio_Image) = CreateWindowExOC(0, #W_STATIC, "", $56000003, 0, 4, 32, 32, MainHWnd, 0, 0)
    If Interface_Control(#Interface_Control_Radio_Image) = 0
      DestroyIcon_(Interface_Icon)
      Interface_Icon = 0
      Else
      SendMessage_(Interface_Control(#Interface_Control_Radio_Image), $170, Interface_Icon, 0)
      EndIf
    EndIf
  
  If CanIRadio
    Interface_Control(#Interface_Control_Radio_CapLabel) = CreateWindowExOC(0, #W_STATIC, LoadResString(2800), $56000000, 4, 3, 417, 17, MainHWnd, 0, 0)
    Interface_Control(#Interface_Control_Radio_Txt) = CreateWindowExOC($200, #W_EDIT, "", $56010090, 6, 17, 400, 14, MainHWnd, 0, 0)
    Interface_Control(#Interface_Control_Radio_Go) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2801), $56010000, 400, 17, 14, 14, MainHWnd, 0, 0)
    Else
    Interface_Control(#Interface_Control_Radio_CapLabel) = CreateWindowExOC(0, #W_STATIC, LoadResString(2820), $56000000, 4, 3, 417, 31, MainHWnd, 0, 0)
    EndIf
  
  TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_Anim), 0, 0, 0, 0, 0, $213)
  Interface_Control(#Interface_Control_Radio_List) = CreateWindowExOC($200, #W_LISTBOX, "", $56300918, 0, 48, 425, 160, MainHWnd, 0, 0)
  If CanIRadio
    xLong1 = 1
    EndIf
  Interface_Control(#Interface_Control_Radio_Play) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2802), $56010000 | xLong1, 8, 208, 129, 25, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Radio_OpenHP) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2803), $56010000, 8, 208, 129, 25, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Radio_AutoCloseCheck) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2804), $56010003, 8, 232, 121, 17, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Radio_Add) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2805), $56010000, 8, 208, 129, 25, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Radio_Edit) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2806), $56010000, 8, 208, 129, 25, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Radio_Remove) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2807), $56010000, 8, 208, 129, 25, MainHWnd, 0, 0)
  Interface_Control(#Interface_Control_Radio_Return) = CreateWindowExOC(0, #W_BUTTON, LoadResString(2808), $56010000, 8, 208, 129, 25, MainHWnd, 0, 0)
  
  If CanIRadio
    SetAccel(#Interface_Control_Radio_Txt, 2800)
    EndIf
  For xLong1 = 0 To #Interface_Control_Radio_Return
    SetAccel(xLong1, 2801 + xLong1)
    HookWindow(Interface_Control(xLong1), @RadioForm_ButtonProc())
    Next
  
  RadioForm_UpdateFont(hFontGFix, 1)
  SendMessage_(Interface_Control(#Interface_Control_Radio_List), $30, hFontPLLg, 0)
  HookWindow(Interface_Control(#Interface_Control_Radio_Txt), @RadioForm_TextProc())
  HookWindow(Interface_Control(#Interface_Control_Radio_List), @RadioForm_ResultListProc())

  RadioForm_UpdateRadioVals()
  
  If CanIRadio And Len(xRadioLastEnteredURL)
    SendMessage_(Interface_Control(#Interface_Control_Radio_Txt), $C, 0, @xRadioLastEnteredURL)
    SendMessage_(Interface_Control(#Interface_Control_Radio_Txt), $B1, 0, -1)
    EndIf
  
  SendMessage_(Interface_Control(#Interface_Control_Radio_List), $1A0, 0, PLODHeight)
  
  xRadioMenu = LoadResEx_Menu(2800)
  xRadioMenu2 = LoadResEx_Menu(2810)
  xRadioPopupMenu2 = MakePopupMenu(xRadioMenu2)
  If xRadioMenu
    SetMenu_(MainHWnd, xRadioMenu)
    DrawMenuBar_(MainHWnd)
    EndIf
  
  RadioForm_ReListRadios(#True)
  ;InterfaceChangePostResize
  EndProcedure

Procedure RadioForm_UnInterface()
  If Not Interface_Icon = 0
    SendMessage_(Interface_Control(#Interface_Control_Radio_Image), $170, 0, 0)
    DestroyIcon_(Interface_Icon)
    Interface_Icon = 0
    EndIf
  If xRadioMenu
    DestroyMenu_(xRadioMenu)
    EndIf
  If xRadioMenu2
    DestroyMenu_(xRadioMenu2)
    EndIf
  If xRadioPopupMenu2
    DestroyMenu_(xRadioPopupMenu2)
    EndIf
  EndProcedure

Procedure RadioForm_EnableButtons()
  Define.i xBool1

  If xRadioCount
    xBool1 = #True
    EndIf
  EnableWindow_(Interface_Control(#Interface_Control_Radio_List), xBool1)
  EnableWindow_(Interface_Control(#Interface_Control_Radio_Edit), xBool1)
  EnableWindow_(Interface_Control(#Interface_Control_Radio_Remove), xBool1)
  If Not CanIRadio
    xBool1 = #False
    EndIf
  EnableWindow_(Interface_Control(#Interface_Control_Radio_Play), xBool1)
  If xRadioCount And UrlsAllowed
    xBool1 = #True
    Else
    xBool1 = #False
    EndIf
  EnableWindow_(Interface_Control(#Interface_Control_Radio_OpenHP), xBool1)
  If xRadioCount < #xRadioCountMax
    xBool1 = #True
    Else
    xBool1 = #False
    EndIf
  EnableWindow_(Interface_Control(#Interface_Control_Radio_Add), xBool1)
  
  If xRadioCount = 0
    EnableMenuItem_(xRadioMenu, 2802, 3)
    EnableMenuItem_(xRadioMenu2, 2802, 3)
    EnableMenuItem_(xRadioMenu, 2803, 3)
    EnableMenuItem_(xRadioMenu2, 2803, 3)
    EnableMenuItem_(xRadioMenu, 2806, 3)
    EnableMenuItem_(xRadioMenu2, 2806, 3)
    EnableMenuItem_(xRadioMenu, 2807, 3)
    EnableMenuItem_(xRadioMenu2, 2807, 3)
    If Not Interface_Control(#Interface_Control_Radio_Txt) = 0
      SetFocus_(Interface_Control(#Interface_Control_Radio_Txt))
      EndIf
    Else
    If CanIRadio
      EnableMenuItem_(xRadioMenu, 2802, 0)
      EnableMenuItem_(xRadioMenu2, 2802, 0)
      Else
      EnableMenuItem_(xRadioMenu, 2802, 3)
      EnableMenuItem_(xRadioMenu2, 2802, 3)
      EndIf
    If UrlsAllowed
      EnableMenuItem_(xRadioMenu, 2803, 0)
      EnableMenuItem_(xRadioMenu2, 2803, 0)
      Else
      EnableMenuItem_(xRadioMenu, 2803, 3)
      EnableMenuItem_(xRadioMenu2, 2803, 3)
      EndIf
    EnableMenuItem_(xRadioMenu, 2806, 0)
    EnableMenuItem_(xRadioMenu2, 2806, 0)
    EnableMenuItem_(xRadioMenu, 2807, 0)
    EnableMenuItem_(xRadioMenu2, 2807, 0)
    EndIf
  If xRadioCount < #xRadioCountMax
    EnableMenuItem_(xRadioMenu, 2805, 0)
    EnableMenuItem_(xRadioMenu2, 2805, 0)
    Else
    EnableMenuItem_(xRadioMenu, 2805, 3)
    EnableMenuItem_(xRadioMenu2, 2805, 3)
    EndIf
  EndProcedure

Procedure RadioForm_RemoveSelectedsFromList()
  Define.i xLong1
  Define.i xLong2
  
  For xLong1 = 0 To xRadioCount - 1
    If SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_GETSEL, xLong2, 0) > 0
      SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_DELETESTRING, xLong2, 0)
      Else
      xRadioCap(xLong2) = xRadioCap(xLong1)
      xRadioURL(xLong2) = xRadioURL(xLong1)
      xRadioHP(xLong2) = xRadioHP(xLong1)
      SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_SETITEMDATA, xLong2, xLong2)
      xLong2 = xLong2 + 1
      EndIf
    Next
  RadioForm_DetectListWidth()
  xRadioCount = xLong2
  RadioForm_EnableButtons()
  EndProcedure

Procedure RadioForm_EditUpdateRadioWithList(Caption.s, URL.s, Homepage.s)
  Define.i xLong1
  Define.i xLong2
  
  xLong2 = SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_GETCARETINDEX, 0, 0)
  If Not xLong2 = -1
    If SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_GETSEL, xLong2, 0) > 0
      SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_DELETESTRING, xLong2, 0)
      For xLong1 = xLong2 To xRadioCount - 2
        xRadioCap(xLong1) = xRadioCap(xLong1 + 1)
        xRadioURL(xLong1) = xRadioURL(xLong1 + 1)
        xRadioHP(xLong1) = xRadioHP(xLong1 + 1)
        SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_SETITEMDATA, xLong1, xLong1)
        Next
      xRadioCount = xRadioCount - 1
      RadioForm_AddRadioEx(Caption, URL, Homepage, #True)
      ;RadioForm_EditUpdateRadioWithList = RadioForm_AddRadioEx(Caption, URL, Homepage)
      EndIf
    EndIf
  EndProcedure

Procedure RadioForm_AddRadioEx(Caption.s, URL.s, Homepage.s, ShowInterface.i)
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1
  
  If xRadioCount < #xRadioCountMax
    URL = Trim(URL)
    If Not Len(URL) = 0
      Caption = Trim(Caption)
      If Len(Caption) = 0
        Caption = URL
        EndIf
      xChar1 = LCase(Caption)
      For xLong1 = 0 To xRadioCount - 1
        If LCase(xRadioCap(xLong1)) > xChar1
          Break
          EndIf
        Next
      For xLong2 = xRadioCount To xLong1 + 1 Step -1
        xRadioCap(xLong2) = xRadioCap(xLong2 - 1)
        xRadioURL(xLong2) = xRadioURL(xLong2 - 1)
        xRadioHP(xLong2) = xRadioHP(xLong2 - 1)
        If ShowInterface
          SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_SETITEMDATA, xLong2, xLong2)
          EndIf
        Next
      xRadioCap(xLong1) = Caption
      xRadioURL(xLong1) = URL
      xRadioHP(xLong1) = Homepage
      xRadioCount = xRadioCount + 1
      If ShowInterface
        SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_INSERTSTRING, xLong1, xLong1)
        SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_SETSEL, 0, -1)
        SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_SETSEL, 1, xLong1)
        SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_SETCARETINDEX, xLong1, #False)
        RadioForm_EnableButtons()
        RadioForm_DetectListWidth()
        EndIf
      ;RadioForm_AddRadioEx = #True
      EndIf
    EndIf
  EndProcedure

Procedure RadioForm_PrePreset()
  If InterfaceMode = #Interface_Mode_Radio
    SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_RESETCONTENT, 0, 0)
    SendMessage_(Interface_Control(#Interface_Control_Radio_List), $194, 0, 0)
    If Not xRadioEditingHWnd = 0
      EndDialog_(xRadioEditingHWnd, 1)
      EndIf
    EndIf
  EndProcedure

Procedure RadioForm_ReListRadios(ReSelect.i)
  Define.i xLong1
  Define.s xChar1

  If ReSelect
    If CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3
      xChar1 = LCase(RealURL(PLCurFullURL))
      If Len(xChar1) = 0
        ReSelect = #False
        EndIf
      Else
      ReSelect = #False
      EndIf
    EndIf

  SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_RESETCONTENT, 0, 0)
  For xLong1 = 0 To xRadioCount - 1
    SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_INSERTSTRING, xLong1, xLong1)
;debug CStr(ReSelect) + "#" + xChar1 + "#" + xRadioURL(xLong1)
    If ReSelect And LCase(xRadioURL(xLong1)) = xChar1
      SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_SETSEL, 1, xLong1)
      Break
      EndIf
    Next
  RadioForm_EnableButtons()
  RadioForm_DetectListWidth()
  EndProcedure

Procedure RadioForm_StartListURL(LoadHPOnly.i)
  Define.i xLong1

  xLong1 = SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_GETCARETINDEX, 0, 0)
  If Not xLong1 = -1
    If SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_GETSEL, xLong1, 0) > 0
      If LoadHPOnly
        SaveOpenURL(xRadioHP(xLong1))
        ElseIf StartWeb(xRadioURL(xLong1) + #CR$ + xRadioCap(xLong1) + #CR$ + xRadioHP(xLong1), #True)
        If xRadioAutoClose
          ToggleInterface(#Interface_Mode_None)
          EndIf
        EndIf
      EndIf
    EndIf
  EndProcedure

Procedure RadioForm_TrySCommand(hWnd.i)
;debug "TiemrSCommand", hwnd, Interface_Control(#Interface_Control_Radio_AutoCloseCheck)
  If IsWindowEnabled_(hWnd)
    Select hWnd
      Case Interface_Control(#Interface_Control_Radio_Go)
        RadioForm_StartManualURL()
      Case Interface_Control(#Interface_Control_Radio_Play)
        RadioForm_StartListURL(#False)
      Case Interface_Control(#Interface_Control_Radio_OpenHP)
;        debug "Radio homepage!"
        RadioForm_StartListURL(#True)
      Case Interface_Control(#Interface_Control_Radio_Add)
;        debug "Radio add"
        xRadioEditingEdit = -1
        RadioForm_ShowRadioEditor(2800)
      Case Interface_Control(#Interface_Control_Radio_Edit)
;        debug "Radio edit"
        xRadioEditingEdit = SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_GETCARETINDEX, 0, 0)
        If Not xRadioEditingEdit = -1
          If SendMessage_(Interface_Control(#Interface_Control_Radio_List), #LB_GETSEL, xRadioEditingEdit, 0) > 0
            ;xRadioEditingEdit = #True
            RadioForm_ShowRadioEditor(2810)
            EndIf
          EndIf
      Case Interface_Control(#Interface_Control_Radio_Remove)
;        debug "Radio remove"
        RadioForm_RemoveSelectedsFromList()
      Case Interface_Control(#Interface_Control_Radio_AutoCloseCheck)
        If SendMessage_(hWnd, $F0, 0, 0)
          xRadioAutoClose = #True
          Else
          xRadioAutoClose = #False
          EndIf
      Case Interface_Control(#Interface_Control_Radio_Return)
;        debug "Radio closeinterface"
        ToggleInterface(#Interface_Mode_None)
        ;RadioForm_TrySCommand = #True
      EndSelect
    EndIf
  EndProcedure

Procedure RadioForm_Resize(xRight.i, xBottom.i, xTop.i)
  Define.i xLong1
  Define.i xLong2

;  If xRight < 0
;    xRight = 0
;    EndIf
  
  If Not Interface_Icon = 0
    xLong1 = 2 * eSPTopX + 32
    TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_Image), 0, eSPTopX, xTop + (xDefCtlHeight16 + xDefHeight16 - 32) / 2, 32, 32, $215)
    EndIf
  xLong2 = xRight - xLong1
  If xLong2 < 0
    xLong2 = 0
    EndIf
  If CanIRadio
    TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_CapLabel), 0, xLong1, xTop, xLong2, xDefHeight16, $214)
    xTop = xTop + xDefHeight16
    xLong2 = xLong2 - 2 * xDefCtlHeight16
    If xLong2 < 0
      xLong2 = 0
      EndIf
    TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_Txt), 0, xLong1, xTop, xLong2, xDefCtlHeight16, $214)
    TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_Go), 0, xLong1 + xLong2, xTop, 2 * xDefCtlHeight16, xDefCtlHeight16, $214)
    xTop = xTop + xDefCtlHeight16 + eSPTopY
    Else
    TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_CapLabel), 0, xLong1, xTop, xLong2, xDefHeight16 * 2, $214)
    xTop = xTop + xDefHeight16 * 2 + eSPTopY
    EndIf
  ;TrDeferWindowPos(xStaticIconsHWnd(#xStaticIcons_DirList), 0, 0, 20 + xTop, xRight, 19, $214)

  xBottom = xBottom - 2 * eSPTopY - xTop - 2 * xDefButtonHeight
  If xBottom < xDefCtlHeight16 - xDefHeight16
    xBottom = xDefCtlHeight16 - xDefHeight16
    EndIf
  TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_List), 0, 0, xTop, xRight, xBottom, $214)
  xTop = xTop + xBottom + eSPTopY
  xLong1 = (xRight - eSPTopX * 5) / 4
  If xLong1 < 0
    xLong1 = 0
    EndIf
  
  TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_Play), 0, eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_OpenHP), 0, xLong1 + 2 * eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_AutoCloseCheck), 0, (xLong1 + eSPTopX) * 3 + eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  xTop = xTop + xDefButtonHeight + eSPTopY
  
  TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_Add), 0, eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_Edit), 0, xLong1 + 2 * eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_Remove), 0, (xLong1 + eSPTopX) * 2 + eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Radio_Return), 0, (xLong1 + eSPTopX) * 3 + eSPTopX, xTop, xLong1, xDefButtonHeight, $214)
  EndProcedure

Procedure RadioForm_UpdateRadioVals()
  Define.i xBool1
  If xRadioAutoClose
    xBool1 = #True
    Else
    xBool1 = #False
    EndIf
  SendMessage_(Interface_Control(#Interface_Control_Radio_AutoCloseCheck), $F1, xBool1, 0)
  EndProcedure

Procedure RadioForm_ApplyDialog(hWnd.i)
  Define.i xLong1
  Define.s xChar1
  
  xLong1 = GetDlgItem_(hWnd, 2800)
  If Not xLong1 = 0
    xChar1 = Trim(GetDlgItemText(hWnd, 2800))
    If Len(xChar1) = 0
      SetFocus_(xLong1)
      Else
      If xRadioEditingEdit = -1
        RadioForm_AddRadioEx(GetDlgItemText(hWnd, 2801), xChar1, GetDlgItemText(hWnd, 2802), #True)
        Else
        RadioForm_EditUpdateRadioWithList(GetDlgItemText(hWnd, 2801), xChar1, GetDlgItemText(hWnd, 2802))
        EndIf
      EndDialog_(hWnd, 1)
      EndIf
    EndIf
  EndProcedure

Procedure.i RadioForm_RadioEditorProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Select Message
    Case $111
      Select wParam
        Case 2808: RadioForm_ApplyDialog(hWnd)
        Case 2809: EndDialog_(hWnd, 1)
        EndSelect
    Case $10
      EndDialog_(hWnd, 1)
    Case $110
      xRadioEditingHWnd = hWnd
      If Not xRadioEditingEdit = -1
        SetDlgItemText_(hWnd, 2800, @xRadioURL(xRadioEditingEdit))
        SetDlgItemText_(hWnd, 2801, @xRadioCap(xRadioEditingEdit))
        SetDlgItemText_(hWnd, 2802, @xRadioHP(xRadioEditingEdit))
        EndIf
      ProcedureReturn 1
    EndSelect
  ProcedureReturn 0
  EndProcedure

Procedure PLWriter_Save_M3uCalaym(hTxtFileOut.i)
  Define.i xLong1
  Define.s xChar1

  TxtFileWriter_WriteLine(hTxtFileOut, #m3uIString)
  TxtFileWriter_WriteLine(hTxtFileOut, "#AutoRefreshTimer=" + StrS(xAutoRefreshTimer(0)))
  TxtFileWriter_WriteLine(hTxtFileOut, "#AutoRefreshTimerMonitor=" + Strs(xAutoRefreshTimer(1)))
  If PLCurSong = ""
    TxtFileWriter_WriteLine(hTxtFileOut, "#CurrentSong=" + StrU(PLCurItem + 1))
    Else
    TxtFileWriter_WriteLine(hTxtFileOut, "#CurrentSong=" + StrU(PLCurItem + 1) + "," + PLCurSong)
    EndIf
  If xPStateIconPlaying And Not (CurMusic = #ctSSLayer_MusicTypeNone Or xSongIsMidi = 2)
    ;else ... TxtFileWriter_WriteLine (hTxtFileOut, "#CurrentSongPos=0,0"
    If Not xPStateIconPaused
      xLong1 = 1
      EndIf
    If (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
      TxtFileWriter_WriteLine(hTxtFileOut, "#CurrentURL=" + Chr(48 + xLong1) + "," + ReplaceString(ReplaceString(ReplaceString(ReplaceString(ReplaceString(PLCurFullURL, #LF$, ""), #CR$, #LF$ + "#CurrentURLCaption="), #CR$, #LF$ + "#CurrentURLHomepage="), #CR$, ""), #LF$, #CRLF$))
      ElseIf Not PLCount = 0
      TxtFileWriter_WriteLine(hTxtFileOut, "#CurrentSongPos=" + Chr(48 + xLong1) + "," + StrU(PLCurSongPos) + "," + StrU(GetElapsedTickTimeMS(xEndSongTimerEventTime)))
      EndIf
    EndIf
  If Not (PLCount = 0 Or PlNextSong = "")
  ;  TxtFileWriter_WriteLine (hTxtFileOut, "#NextSong=0"
  ;  Else
    TxtFileWriter_WriteLine(hTxtFileOut, "#NextSong=" + StrU(PLNext + 1) + "," + PlNextSong)
    EndIf
  TxtFileWriter_WriteLine(hTxtFileOut, "#RemoveMissingSongs=" + BoolChar1(xRemoveMissingSongs))
  TxtFileWriter_WriteLine(hTxtFileOut, "#RemovePlayedSongs=" + BoolChar1(xRemovePlayedSongs))
  TxtFileWriter_WriteLine(hTxtFileOut, "#RemoveSkippedSongs=" + BoolChar1(xRemoveSkippedSongs))
  TxtFileWriter_WriteLine(hTxtFileOut, "#RepeatMode=" + Str(xRep))
  ;If Not xAutoDirCount = 0
    For xLong1 = 0 To xAutoDirCount - 1
      TxtFileWriter_WriteLine(hTxtFileOut, "#AutoDir=" + xAutoDir(xLong1))
      Next
  ;  endif
  For xLong1 = 0 To xRadioCount - 1
    TxtFileWriter_WriteLine(hTxtFileOut, "#Radio=" + xRadioCap(xLong1))
    If Not Len(xRadioHP(xLong1)) = 0
      TxtFileWriter_WriteLine(hTxtFileOut, "#RadioHomepage=" + xRadioHP(xLong1))
      EndIf
    TxtFileWriter_WriteLine(hTxtFileOut, xRadioURL(xLong1))
    Next
  For xLong1 = 0 To PLCount - 1
CompilerIf #BoldDirs = 98
    If (PLI(xLong1)\DirDepthFlags & #PLI_IsAuto) = 0
      If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = #PLI_IsDir
        xChar1 = PLI(xLong1)\Filename
        If Not xChar1 = ""
          xChar1 = "," + xChar1
          EndIf
        TxtFileWriter_WriteLine(hTxtFileOut, "#Dir=" + Str(PLI(xLong1)\DirDepthFlags & #PLI_Depth) + xChar1)
        Else
        TxtFileWriter_WriteLine(hTxtFileOut, PLI(xLong1)\Filename)
        EndIf
      EndIf
CompilerElse
    If (PLIDF(xLong1) & #PLI_IsAuto) = 0
      If (PLIDF(xLong1) & #PLI_IsDir) = #PLI_IsDir
        xChar1 = PLIFile(xLong1)
        If Not xChar1 = ""
          xChar1 = "," + xChar1
          EndIf
        TxtFileWriter_WriteLine(hTxtFileOut, "#Dir=" + Str(PLIDF(xLong1) & #PLI_Depth) + xChar1)
        Else
        TxtFileWriter_WriteLine(hTxtFileOut, PLIFile(xLong1))
        EndIf
      EndIf
CompilerEndIf
    Next
  EndProcedure


CompilerIf #WizardHasLabel
  Procedure WizardForm_UpdateFont(HWndFont.i, UpdateFlag.i)
  CompilerElse
  Procedure WizardForm_UpdateFont()
  CompilerEndIf
  
  Define.i xLong1
  Define.LOGFONT xType1
  Define.POINT xType2

  xStaticIcons_IntroWizCtlHeight = 40

  CompilerIf #WizardHasLabel
    SendMessage_(Interface_Control(#Interface_Control_Wizard_CapLabel), $30, HWndFont, UpdateFlag)
    CompilerEndIf
  
  SystemParametersInfo_(#SPI_GETICONTITLELOGFONT, SizeOf(LOGFONT), @xType1, 0)
  If DPIScaleY > 1
    xType1\lfHeight = Int((21 * DPIScaleY) / xGlobalDialogUnits)
    If xType1\lfQuality < 2
      xType1\lfQuality = 2
      EndIf
    Else
    xType1\lfHeight = Int(21 / xGlobalDialogUnits)
    EndIf
  If Not hFontIntroWiz = 0
    DeleteObject_(hFontIntroWiz)
    EndIf
  hFontIntroWiz = CreateFontIndirect_(@xType1)
  If Not hFontIntroWiz = 0
    If Not SelectObject_(xSharedDC, hFontIntroWiz) = 0
      GetTextExtentPoint32_(xSharedDC, #DefTxt, #LenDefTxt, xType2)
      xStaticIcons_IntroWizCtlHeight = xType2\y + 4
      SelectObject_(xSharedDC, hFontGFix)
      EndIf
    EndIf
  If xStaticIcons_IntroWizCtlHeight < 40
    xStaticIcons_IntroWizCtlHeight = 40
    EndIf

  For xLong1 = #Interface_Control_Wizard_ButtonFirst To #Interface_Control_Wizard_ButtonLast
    If Not Interface_Control(xLong1) = 0
      SendMessage_(Interface_Control(xLong1), $F, 0, 0)
      EndIf
    Next
CompilerIf #WizardHasLabel
  EndProcedure
CompilerElse
  EndProcedure
CompilerEndIf

Procedure WizardForm_TrySCommand(xIndex.i)
  If Not PlayerIsLocked
    Select xIndex
      Case #Interface_Control_Wizard_Help
        MainForm_ProcessKey(#KbdC_IHelp)
      Case #Interface_Control_Wizard_AddDir
        MenuEventFile(1)
      Case #Interface_Control_Wizard_AddPList
        MenuEventFile(2)
      Case #Interface_Control_Wizard_AutoRefresh
        MainForm_ProcessKey(#KbdC_OAutoRFSetup)
      Case #Interface_Control_Wizard_IRadio
        MainForm_ProcessKey(#KbdC_OInternetRadio)
      EndSelect
    EndIf
  EndProcedure

Procedure.i WizardForm_ButtonProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Define.i xLong1
  
  If Message = $200
    If Not PlayerIsLocked
      For xLong1 = #Interface_Control_Wizard_ButtonFirst To #Interface_Control_Wizard_ButtonLast
        If Interface_Control(xLong1) = hWnd
          If Not hWnd = WizardSelHWnd
            If Not WizardSelHWnd = 0
  ;debug Timer, "HClear"
              WizardSelHWnd = 0
              DrawWhiteDCWizButton(WizardSelIndex)
              EndIf
  ;debug Timer, "HDraw"
            WizardSelIndex = xLong1 - #Interface_Control_Wizard_ButtonFirst
            WizardSelHWnd = Interface_Control(#Interface_Control_Wizard_ButtonFirst + WizardSelIndex)
            DrawWhiteDCWizButton(WizardSelIndex)
            EndIf
          Break
          EndIf
        Next
      EndIf
    ElseIf Message = $201
;debug "Check"
    If Not PlayerIsLocked
      For xLong1 = #Interface_Control_Wizard_ButtonFirst To #Interface_Control_Wizard_ButtonLast
        If Interface_Control(xLong1) = hWnd
          WizardForm_TrySCommand(xLong1)
          Break
          EndIf
        Next
      EndIf
    EndIf
  ProcedureReturn HookedWindowProc(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure.i WizardMainHook(hWnd.i, Message.i, wParam.i, lParam.i)
  Define.i xLong1
  Define.i xLong2
  
  Select Message
    Case $100
      xLong2 = GetShiftCode()
      Select wParam
        Case 13
          If Not PlayerIsLocked
            WizardForm_TrySCommand(#Interface_Control_Wizard_ButtonFirst + WizardSelIndex)
            EndIf
          ProcedureReturn 0
        Case 27
          If Not vKioskMode
            AbortReading = #True
            EndIf
          ProcedureReturn 0
        Case 38 ; up
          If Not PlayerIsLocked
            If WizardSelIndex > 0
              xLong1 = WizardSelIndex - 1
              Goto SelNow
              ElseIf WizardSelHWnd = 0
              Goto SelNow
              EndIf
            EndIf
        Case 33, 36 ; pgup, home
          If Not PlayerIsLocked
            If WizardSelIndex > 0 Or WizardSelHWnd = 0
              xLong1 = 0
              Goto SelNow
              EndIf
            EndIf
        Case 34, 35 ; pgdn, end
          If Not PlayerIsLocked
            If WizardSelIndex < #xStaticIcons_IntroWizCountSub1
              xLong1 = #xStaticIcons_IntroWizCountSub1
              Goto SelNow
              EndIf
            EndIf
        Case 40 ;down
          If Not PlayerIsLocked
            If WizardSelIndex < #xStaticIcons_IntroWizCountSub1
              xLong1 = WizardSelIndex + 1
SelNow:
              If Not (WizardSelHWnd = 0 Or WizardSelIndex = xLong1)
  ;debug Timer, "BClear"
                WizardSelHWnd = 0
                DrawWhiteDCWizButton(WizardSelIndex)
                EndIf
  ;debug Timer, "BDraw"
              WizardSelIndex = xLong1
              WizardSelHWnd = Interface_Control(#Interface_Control_Wizard_ButtonFirst + WizardSelIndex)
              DrawWhiteDCWizButton(WizardSelIndex)
              EndIf
            EndIf
          ProcedureReturn 0
        ;Case 33 To 36, 38, 40
        ;  debug wParam
          ; 38 up
          ; 40 dn
          ; 33 pgup
          ; 34 pgdn
          ; 36 home
          ; 35 end
          ;xFollowCurSongLastDiff = 0
        Case 0 To 4, 7 To 32, 93 ; 38, 40, 93
          ProcedureReturn CallWindowProc_(WizardMainHookOld, hWnd, Message, wParam, lParam)
        Case 5, 6, 33 To 40 ;, $E7, $E8  ;40
          ProcedureReturn CallWindowProc_(WizardMainHookOld, hWnd, Message, wParam, lParam)
        EndSelect
      If Not IsAltPressed()
        MainForm_TryFindKeyEvent((wParam & $FF) + xLong2 * $100)
        ProcedureReturn 0
        EndIf
    ;Case $101 ;keyup
    Case $20B, $AB
      If (wParam & $60)
        MainForm_TryFindKeyEventWParam(wParam)
        EndIf
      ProcedureReturn 0
    EndSelect
  ProcedureReturn CallWindowProc_(WizardMainHookOld, hWnd, Message, wParam, lParam)
  EndProcedure

Procedure WizardForm_Interface()
  Define.i xLong1

  WizardSelIndex = 0
  WizardSelHWnd = 0

  CompilerIf #WizardHasLabel
    Interface_Control(#Interface_Control_Wizard_CapLabel) = CreateWindowExOC(0, #W_STATIC, "", $56000000, 4, 3, 417, 31, MainHWnd, 0, 0)
    CompilerEndIf
  IntroWizIcon(0) = LoadResEx_Image_MultiOS(1800, 1)
  IntroWizIcon(1) = LoadResEx_Image_MultiOS(1830, 1)
  IntroWizIcon(2) = LoadResEx_Image_MultiOS(1860, 1)
  IntroWizIcon(3) = LoadResEx_Image_MultiOS(1890, 1)
  If CanIRadio
    IntroWizIcon(4) = LoadResEx_Image_MultiOS(1920, 1)
    Else
    IntroWizIcon(4) = LoadResEx_Image_MultiOS(1950, 1)
    EndIf
  
  Interface_Control(#Interface_Control_Wizard_Holder) = CreateWindowExOC($200, #CalaymClassStaticWhiteDC, "", $56010003, 0, 0, 240, xStaticIcons_IntroWizCtlHeight, MainHWnd, 0, 0)
  If Not Interface_Control(#Interface_Control_Wizard_Holder) = 0
    ;SetWindowPos_(Interface_Control(#Interface_Control_Wizard_Holder), 0, 0, 0, 0, 0, $213)
    ;SetWindowPos_(xListHWnd(1), 0, 0, 0, 0, 0, $213)
    For xLong1 = 0 To #xStaticIcons_IntroWizCountSub1
      If Not IntroWizIcon(xLong1) = 0
        IntroWizIconHas = #True
        EndIf
      Interface_Control(#Interface_Control_Wizard_ButtonFirst + xLong1) = CreateWindowExOC(0, #CalaymClassStaticWhiteDC, "", $56000003, 4, 48 + xStaticIcons_IntroWizCtlHeight * xLong1, 240, xStaticIcons_IntroWizCtlHeight, Interface_Control(#Interface_Control_Wizard_Holder), 0, 1800 + xLong1)
      HookWindow(Interface_Control(#Interface_Control_Wizard_ButtonFirst + xLong1), @WizardForm_ButtonProc())
      IntroWizText(xLong1) = LoadResString(1800 + xLong1 * 2)
      Next
    CompilerIf #WizardHasLabel
      WizardForm_UpdateFont(hFontGFix, 1)
      CompilerElse
      WizardForm_UpdateFont()
      CompilerEndIf
    WizardMainHookOld = SetWindowLong_(Interface_Control(#Interface_Control_Wizard_Holder), -4, @WizardMainHook())
    EndIf
  
  SetFocus_(Interface_Control(#Interface_Control_Wizard_Holder))
  
  If Not xMenu(0) = 0
    SetMenu_(MainHWnd, xMenu(0))
    DrawMenuBar_(MainHWnd)
    EndIf
  EndProcedure

Procedure WizardForm_UnInterface()
  Define.i xLong1

  For xLong1 = 0 To #xStaticIcons_IntroWizCountSub1
    If Not IntroWizIcon(xLong1) = 0
      DestroyIcon_(IntroWizIcon(xLong1))
      EndIf
    Next
  For xLong1 = #Interface_Control_Wizard_ButtonFirst To #Interface_Control_Wizard_ButtonLast
    If Not Interface_Control(xLong1) = 0
      DestroyWindow_(Interface_Control(xLong1))
      Interface_Control(xLong1) = 0
      EndIf
    Next
  If Not Interface_Control(#Interface_Control_Wizard_Holder) = 0
    If Not WizardMainHookOld = 0
      SetWindowLong_(Interface_Control(#Interface_Control_Wizard_Holder), -4, WizardMainHookOld)
      WizardMainHookOld = 0
      EndIf
    EndIf
  If Not hFontIntroWiz = 0
    DeleteObject_(hFontIntroWiz)
    EndIf
  hFontIntroWiz = 0
  SetMenu_(MainHWnd, 0)
  EndProcedure

Procedure WizardForm_Resize(xRight.i, xBottom.i, xTop.i)
  Define.RECT xType1
  Define.i xLong1
  Define.i xLong2

  #WZCountPls2 = #xStaticIcons_IntroWizCount + 8
  
  xBottom = xBottom - xTop
  If xBottom < 0
    xBottom = 0
    EndIf
  ;TrDeferWindowPos(xListHWnd(2), 0, 0, xTop, xRight, xBottom, $214)
  TrDeferWindowPos(Interface_Control(#Interface_Control_Wizard_Holder), 0, 0, xTop, xRight, xBottom, $214)
  GetClientRect_(Interface_Control(#Interface_Control_Wizard_Holder), xType1)
  
  xLong1 = xType1\Bottom - xType1\Top - (#xStaticIcons_IntroWizCount * xStaticIcons_IntroWizCtlHeight)
  xBottom = xLong1 / #WZCountPls2
  If xBottom < 0
    xBottom = 0
    EndIf
  xLong1 = (xLong1 - #xStaticIcons_IntroWizCountSub1 * xBottom) >> 1
  If xLong1 < 0
    xLong1 = 0
    EndIf
  xTop = xType1\Top + xLong1
  xRight = xType1\Right - 12
  If xRight < 0
    xRight = 0
    EndIf
  xLong2 = xRight * 0.05
  xRight = xRight - 2 * xLong2
  If xRight < 0
    xRight = 0
    EndIf
  xBottom = xBottom + xStaticIcons_IntroWizCtlHeight
  For xLong1 = 0 To #xStaticIcons_IntroWizCountSub1
    TrDeferWindowPos(Interface_Control(#Interface_Control_Wizard_ButtonFirst + xLong1), 0, xType1\left + 6 + xLong2, xTop + xLong1 * xBottom, xRight, xStaticIcons_IntroWizCtlHeight, $214)
    Next
  EndProcedure

CompilerIf #False
Procedure MainForm_EndMenu()
  If PlayerInMenuLoop
    Debug "Closing menu"
    ;#WM_CANCELMODE = $1F
    SendMessage_(MainHWnd, $1F, 0, 0)
    EndIf
  EndProcedure
CompilerEndIf

;-* multi-function-depending callers, which are declared

Procedure MainForm_MenuEvent(MenuID.i)
  ;debug "  Undefined!!!: ", MenuID
  
  If MenuID > 999 And MenuID < 3000
    MenuID = MenuID % 1000
    
    Select MenuID
      ;quit
      ;case 1
        Case 10: MainForm_ProcessKey(#KbdC_FAddFileS)
        Case 11: MainForm_ProcessKey(#KbdC_FAddDir)
        Case 12: MainForm_ProcessKey(#KbdC_FAddPList)
        ;Case 20
        Case 20, 22: MainForm_ProcessKey(#KbdC_FRefreshCD)
          ;Case 870 To 896
        Case 30: MainForm_ProcessKey(#KbdC_FNewPL)
        Case 31: MainForm_ProcessKey(#KbdC_FLoadPL)
        ;Case 32
        Case 34: MainForm_ProcessKey(#KbdC_FReloadPL)
        Case 36: MainForm_ProcessKey(#KbdC_FLoadPLDefault)
          ;;;;;;
        Case 40: MainForm_ProcessKey(#KbdC_FSavePL)
        Case 41: MainForm_ProcessKey(#KbdC_FSavePLas)
        Case 50: MainForm_ProcessKey(#KbdC_FClearPL)
        Case 60: MainForm_ProcessKey(#KbdC_FQuitSD)
      
      ;defctrl
      ;Case 100
        Case 101: MainForm_ProcessKey(#KbdC_CPrev)
        Case 102: MainForm_ProcessKey(#KbdC_CPlay)
        Case 103: MainForm_ProcessKey(#KbdC_CPause)
        Case 104: MainForm_ProcessKey(#KbdC_CStop)
        Case 105: MainForm_ProcessKey(#KbdC_CNext)
        Case 106: MainForm_ProcessKey(#KbdC_CEnd)
        ;repeat
        Case 110: MainForm_ProcessKey(#KbdC_CRepSingle)
        Case 111: MainForm_ProcessKey(#KbdC_CRepAll)
        Case 112: MainForm_ProcessKey(#KbdC_CRepRnd)
        
        Case 113: MainForm_ProcessKey(#KbdC_CRepToggle)
        Case 119: MainForm_ProcessKey(#KbdC_CIntroMode)
        
        Case 120: MainForm_ProcessKey(#KbdC_CSeekB)
        Case 121: MainForm_ProcessKey(#KbdC_CSeekF)
        
        ;Case 130
          Case 131: MainForm_ProcessKey(#KbdC_CCSSelFile)
          Case 132: MainForm_ProcessKey(#KbdC_CCSRemFile)
          Case 133: MainForm_ProcessKey(#KbdC_CCSDelFile)
          Case 134: MainForm_ProcessKey(#KbdC_CCSExplorer)
      
      ;Case 200
        Case 201: MainForm_ProcessKey(#KbdC_PPlaySkip)
        Case 202: MainForm_ProcessKey(#KbdC_PPlayEnd)
        Case 203: MainForm_ProcessKey(#KbdC_PPlayNext)
        Case 210: MainForm_ProcessKey(#KbdC_PFindCurrent)
        Case 211: MainForm_ProcessKey(#KbdC_PFind)
        Case 212: MainForm_ProcessKey(#KbdC_PFindNext)
        Case 213: MainForm_ProcessKey(#KbdC_PFindQuick)
        Case 214: MainForm_ProcessKey(#KbdC_PSelRnd)
        Case 220: MainForm_ProcessKey(#KbdC_PInvSel)
        Case 221: MainForm_ProcessKey(#KbdC_PRemSongs)
        Case 222: MainForm_ProcessKey(#KbdC_PRem)
        Case 223: MainForm_ProcessKey(#KbdC_PCopyPLEnd)
        Case 224: MainForm_ProcessKey(#KbdC_PCrop)
        Case 230: MainForm_ProcessKey(#KbdC_PDelFiles)
        Case 250: MainForm_ProcessKey(#KbdC_PExplorer)
      
      ;Case 300
        Case 301: MainForm_ProcessKey(#KbdC_OFading)
        Case 302: MainForm_ProcessKey(#KbdC_OSpektrum)
        Case 303: MainForm_ProcessKey(#KbdC_OFileInfos)
        Case 310: MainForm_ProcessKey(#KbdC_OFollowSong)
        Case 320: MainForm_ProcessKey(#KbdC_ORemMissing)
        Case 321: MainForm_ProcessKey(#KbdC_ORemSkipped)
        Case 322: MainForm_ProcessKey(#KbdC_ORemPlayed)
        Case 330: MainForm_ProcessKey(#KbdC_ONoEndMode)
        Case 331: MainForm_ProcessKey(#KbdC_OXFade)
        Case 332: MainForm_ProcessKey(#KbdC_OMDMode)
        Case 333: MainForm_ProcessKey(#KbdC_OStopEach)
        Case 339: MainForm_ProcessKey(#KbdC_OEndModeTggle)
        ; Case 340 Volume menu
          Case 341: ChangeVolumeMenu(0)
          Case 342: ChangeVolumeMenu(1)
          Case 345 To 355: ChangeVolumeMenu(MenuID - 342)
        Case 360: MainForm_ProcessKey(#KbdC_CMoreSetts)
      
      ;Case 400
      ;  Case 405 = IRadioParent
        Case 406: MainForm_ProcessKey(#KbdC_OInternetRadio)
        Case 407: MainForm_ProcessKey(#KbdC_OInternetRadioRe)
        Case 408: MainForm_ProcessKey(#KbdC_OInternetRadioHP)
      ;case 410 = AutoRFParent (unused in resources, but disabled with /NoAutoRefresh anyway)
        Case 411: MainForm_ProcessKey(#KbdC_OAutoRF)
        Case 412: MainForm_ProcessKey(#KbdC_OAutoRFAlt)
        Case 413: MainForm_ProcessKey(#KbdC_OAutoRFRem)
        Case 414: MainForm_ProcessKey(#KbdC_OAutoRFRemI)
        Case 415: MainForm_ProcessKey(#KbdC_OAutoRFSetup)
        Case 419  ; = abortreading (unused)
          If Not vKioskMode
            AbortReading = #True
            EndIf
        Case 420
          If xDirListModeCur = 0
            ShowWindow_(xListHWnd(0), 5)
            DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 1)
            SetFocus_(xListHWnd(0))
            EndIf

        ;Case 422: MainForm_ProcessKey(#KbdC_
          Case 423: MainForm_ProcessKey(#KbdC_ODirToggle)
          Case 424: MainForm_ProcessKey(#KbdC_ODirCombo)
          Case 425: MainForm_ProcessKey(#KbdC_ODirTop)
          Case 426: MainForm_ProcessKey(#KbdC_ODirLeft)
          Case 427: MainForm_ProcessKey(#KbdC_ODirAuto)
          Case 428: MainForm_ProcessKey(#KbdC_ODirDec)
          Case 429: MainForm_ProcessKey(#KbdC_ODirInc)
        Case 421
                  ShowWindow_(xListHWnd(1), 5)
                  DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 1)
                  SetFocus_(xListHWnd(1))
        ;Case 440: MainForm_ProcessKey(#KbdC_
          Case 441: MainForm_ProcessKey(#KbdC_OTimerEdit)
          Case 442: MainForm_ProcessKey(#KbdC_OTimerImport)
          Case 443: MainForm_ProcessKey(#KbdC_OTimerExport)
          Case 444: MainForm_ProcessKey(#KbdC_OTimerClear)
        Case 450: MainForm_ProcessKey(#KbdC_OResetSnd)
        Case 455: MainForm_ProcessKey(#KbdC_OVolCtrl)
        ;Case 460: MainForm_ProcessKey(#KbdC_
          Case 461: MainForm_ProcessKey(#KbdC_OPresetSave)
          Case 462: MainForm_ProcessKey(#KbdC_OPresetLoad)
            ;case 464...? preset by ID
        Case 470: MainForm_ProcessKey(#KbdC_OSaveSetts)
      
      ;Case 500: MainForm_ProcessKey(#KbdC_IInfoMenu
        Case 501: MainForm_ProcessKey(#KbdC_IHelp)
        Case 502: MainForm_ProcessKey(#KbdC_IAbout)
        
      ;showplayer
      Case 800: MainForm_ProcessKey(#KbdC_GShowPlayer)
      ; 900+ => specialmenus / popups
      ; 970++ = CD drive IDs
      Case 970 To 995
        ;debug Chr(MenuID - 970 + 65)
        MenuEventCDDrive(Mid(CDDriveLetters, MenuID - 969, 1), #True, #True)
;      default
;        debug "  Undefined!!!: ", MenuID
      EndSelect
    ElseIf MenuID > 2999 And MenuID < 3000 + #vPLXMax
    ;debug "m3u: "; MenuID, vPLXMain & vPLX(MenuID - 3001)
    If Not xNoPLMenu
      LoadPList(vPLXMain + vPLX(MenuID - 3000), #False, #False) ;, #False)
      EndIf
    ElseIf MenuID > 3999 And MenuID < 4000 + #vPLXMax
    ;debug "cps: "; MenuID, vPLXMain & vPLX(#vPLXMax+ MenuID - 4001)
    If Not xNoPresets
      MainForm_LoadSettings(vPLXMain + vPLX(#vPLXMax + MenuID - 4000))
      EndIf
    ElseIf MenuID > 4999 And MenuID < 5000 + #vPLXMax
    If Not xNoTimers
      MainForm_LoadTimers(MainHWnd, vPLXMain + vPLX(2 * #vPLXMax + MenuID - 5000), #False)
      EndIf
    EndIf
  EndProcedure

Procedure MainForm_IconsMouseUp(Index.i)
  If Not (PlayerIsLocked Or xAutoDoing)
    xGUIClickDelayTimer = GetTickTimeMS()
    If (Index = #xStaticIcons_Def0 Or Index = #xStaticIcons_Def4 Or (Index = #xStaticIcons_Def5 And Not xRemovePlayedSongs)) And xPStateIconPlaying And xRemoveSkippedSongs And PLCount And Not (xNoRemove Or (PLNext = PLCurItem And Len(PlNextSong)))
      If Index = #xStaticIcons_Def0
        MainForm_RemoverX(#True)
        Else
        MainForm_RemoverX(#False)
        EndIf
      EndIf
    Select Index
      Case #xStaticIcons_Def0 ;previous
        MainForm_PlayNext(#True, -1, #False, #False)
      Case #xStaticIcons_Def1 ;play
        If xPStateIconPlaying And xPStateIconPaused
          MainForm_xPauseClick()
          Else
          xPStateIconPlaying = #True
          MainForm_xPlayClick(#False)
          EndIf
      Case #xStaticIcons_Def2 ;pause
        MainForm_xPauseClick()
      Case #xStaticIcons_Def3 ;stop
        If vKioskMode
          If Not PlNextSong = ""
            SetNextSong(#False)
            EndIf
          Else
          If PlNextSong = ""
            If xPStateIconPlaying
              xPStateIconPlaying = #False
              MainForm_LockMe(#True)
              MainForm_xEndSong(#True, xPStateIconPaused, #False, #False)
              MainForm_UpdateMainIcon()
              MainForm_LockMe(#False)
              EndIf
            xReAutoPlay = #False
            ReAutoPlayDR = #False
            Else
            SetNextSong(#False)
            EndIf
          EndIf
      Case #xStaticIcons_Def4 ;next
        MainForm_PlayNext(#True, 1, #False, #False)
      Case #xStaticIcons_Def5 ;endsong
        If xPStateIconPlaying
          If xPStateIconPaused
            xPStateIconPlaying = #False
            MainForm_UpdateMainIcon()
            xPStateIconPaused = #False
            xReAutoPlay = #False
            ReAutoPlayDR = #False
            MainForm_CheckAfter(#False, #True, #True, #False)
            Else
            MainForm_CheckAfter(#True, #True, #True, #False)
            EndIf
          EndIf
      Case #xStaticIcons_RepMode
        xRep = (xRep + 1) % 3
        MainForm_ApplyRepMode()
      EndSelect
    EndIf
  EndProcedure

CompilerIf #UseFileLogging
  Procedure MainForm_ctConsoleA_AddLog(MsgString.s)
    Define.SYSTEMTIME xType1

    CompilerIf #UseFileLoggingIDE
      Debug MsgString
      CompilerEndIf
    GetLocalTime_(@xType1)
    With xType1
      MsgString = Right("000" + Str(\wYear), 4) + "-" + Str(\wMonth) + "-" + Right("0" + Str(\wDay), 2) + ", " + Right("0" + Str(\wHour), 2) + ":" + Right("0" + Str(\wMinute), 2) + ":" + Right("0" + Str(\wSecond), 2) + "." + Right("00" + Str(\wMilliseconds), 3) + " " + MsgString
      EndWith
    If LogFileDoLog
      LogFileDoLog = AppendToTextFileEx(LogFileLog, MsgString)
      EndIf
    CompilerIf #UseFileLoggingKernel ;And UseFileLogging
      OutputDebugString_(@MsgString)
      CompilerEndIf
    EndProcedure
  CompilerEndIf

Procedure MainForm_LockMe(vBool1.i)
  Define.i xLong1
  Define.i xLong2
  
  PlayerIsLocked = vBool1
  xLong2 = GetMenuItemCount_(xMenu(0)) - 1
  For xLong1 = 0 To xLong2
    EnableMenuItem_(xMenu(0), xLong1, $400 - 3 * vBool1)
    Next
  
  Select InterfaceMode
    Case #Interface_Mode_None
      DrawMenuBar_(MainHWnd)
    ;Case #Interface_Mode_Search
    Case #Interface_Mode_Timer
      TimerListForm_ApplyLockState()
      DrawMenuBar_(MainHWnd)
    Case #Interface_Mode_Radio
      If PlayerIsLocked
        EnableWindow_(Interface_Control(#Interface_Control_Radio_Go), 0)
        EnableWindow_(Interface_Control(#Interface_Control_Radio_Play), 0)
        Else
        EnableWindow_(Interface_Control(#Interface_Control_Radio_Go), 1)
        RadioForm_EnableButtons()
        EndIf
    Case #Interface_Mode_Wizard
      For xLong1 = 0 To #xStaticIcons_IntroWizCountSub1
        DrawWhiteDCWizButton(xLong1)
        Next
      DrawMenuBar_(MainHWnd)
    EndSelect
  EndProcedure

Procedure.i SplitterProcTH(hWnd.i, Message.i, wParam.i, lParam.i)
  If Not PlayerIsLocked
    Select Message
      Case $200 ;#WM_MOUSEMOVE = $200
        If MainFormIsSplitterMovingTH
          SplitterMoveTH(SignedHigherWord(lParam))
          EndIf
      Case $20
        SetCursor_(NSCursor)
        ProcedureReturn 0
      Case $201 ;#WM_LBUTTONDOWN = $201
        If Not (xDirListModeCur = 2 Or MainFormIsSplitterMovingTH Or MainFormIsSplitterMovingLW)
          MainFormIsSplitterMovingTH = #True
          SetCapture_(HWndSplitterTH)
          SetWindowPos_(HWndSplitterMoveTH, 0, 0, 0, 0, 0, $213)
          ShowWindow_(HWndSplitterMoveTH, 5)
          EndIf
      Case $202 ;#WM_LBUTTONUP = $202
        If MainFormIsSplitterMovingTH
          SplitterMoveTH(SignedHigherWord(lParam))
          ReleaseCapture_()
          SetWindowPos_(HWndSplitterMoveTH, 1, 0, 0, 0, 0, $213)
          ShowWindow_(HWndSplitterMoveTH, 0)
          If SplitterPreResult = -1
            If xDirListModeCur = 1
              xDirListModeCur = 0
              xDirListModeSet = 0
              MainForm_ToggleDirList(#True, #True)
              EndIf
            ElseIf xDirListModeCur = 0
            xDirListTopHeight = SplitterPreResult
            xDirListModeCur = 1
            xDirListModeSet = 1
            MainForm_ToggleDirList(#True, #True)
            ElseIf xDirListModeCur = 1
            xDirListTopHeight = SplitterPreResult
            MainForm_ResizePlayer(#False)
            EndIf
          MainFormIsSplitterMovingTH = #False
          EndIf
      EndSelect
    EndIf
  ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure.i SplitterProcLW(hWnd.i, Message.i, wParam.i, lParam.i)
  If Not PlayerIsLocked
    Select Message
      Case $200 ;#WM_MOUSEMOVE = $200
        If MainFormIsSplitterMovingLW
          ;Debug Hex(lParam) + "/" + Hex(lparam & $ffff) + "/" + Str(SignedLowerWord(lParam))
          SplitterMoveLW(SignedLowerWord(lParam))
          EndIf
      Case $20
        SetCursor_(WECursor)
        ProcedureReturn 0
      Case $201 ;#WM_LBUTTONDOWN = $201
        If xDirListModeCur = 2 And Not (MainFormIsSplitterMovingTH Or MainFormIsSplitterMovingLW)
          MainFormIsSplitterMovingLW = #True
          SetCapture_(HWndSplitterLW)
          SetWindowPos_(HWndSplitterMoveLW, 0, 0, 0, 0, 0, $213)
          ShowWindow_(HWndSplitterMoveLW, 5)
          EndIf
      Case $202 ;#WM_LBUTTONUP = $202
        If MainFormIsSplitterMovingLW
          SplitterMoveLW(SignedLowerWord(lParam))
          ReleaseCapture_()
          SetWindowPos_(HWndSplitterMoveLW, 1, 0, 0, 0, 0, $213)
          ShowWindow_(HWndSplitterMoveLW, 0)
          If xDirListModeCur = 2
            xDirListLeftWidth = SplitterPreResult
            MainForm_ResizePlayer(#False)
            EndIf
          MainFormIsSplitterMovingLW = #False
          EndIf
      EndSelect
    EndIf
  ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
  EndProcedure

Procedure.i ListsHook(hWnd.i, Message.i, wParam.i, lParam.i)
  Define.i xLong1
  Define.i xLong2

  For xLong1 = 0 To 2
    If hWnd = xListHWnd(xLong1)
      If xLong1 = 2 And Not InterfaceMode = #Interface_Mode_None
        ProcedureReturn CallWindowProc_(xListHWndHook(xLong1), hWnd, Message, wParam, lParam)
        Else
        Select Message
          Case $200 ;move
            If xLong1 = 2 And MainFormDraggingIs And Not (lParam = MainFormDraggingLParam)
              MainForm_OleStartDrag()
              ;Load OLEHelperForm
              ;OLEHelperForm.OLEDrag
              ;Unload OLEHelperForm
              ;App.TaskVisible = #False
              ;ElseIf IsUnicode
              ;CallWindowProcW(xListHWndHook(2), hWnd, MainFormDraggingWMsgPlus, MainFormDraggingWParam, MainFormDraggingLParam)
              ;Else
              ;CallWindowProcA(xListHWndHook(2), hWnd, MainFormDraggingWMsgPlus, MainFormDraggingWParam, MainFormDraggingLParam)
              EndIf
            MainFormDraggingIs = #False
          Case $20A ;WM_MouseWheel
;debug "Scroll: 1 (wparam: " + Hex(wParam) + ")"
            If (wParam & $C) = 0
              Message = SignedHigherWord(wParam)
              wParam = SendMessage_(hWnd, #LB_GETTOPINDEX, 0, 0)
;debug "Scroll: 2 (TopIndex: " + wParam + ")"
              If wParam = -1
;debug "Scroll: 3 (topindex error)"
                MouseWheelDeltaLst(xLong1) = 0
                Else
                If Message < 0 And MouseWheelDeltaLst(xLong1) > 0
                  MouseWheelDeltaLst(xLong1) = 0
                  ElseIf Message > 0 And MouseWheelDeltaLst(xLong1) < 0
                  MouseWheelDeltaLst(xLong1) = 0
                  EndIf
;debug "Scroll: 4 (ScrollDiv: " + Message + ")"
                MouseWheelDeltaLst(xLong1) = MouseWheelDeltaLst(xLong1) + Message
                lParam = wParam - Int(MouseWheelDeltaLst(xLong1) / #MouseWheelDeltaDivLst)
                If lParam < 0
                  lParam = 0
                  Else
                  Message = SendMessage_(hWnd, #LB_GETCOUNT, 0, 0)
                  If Not Message = -1
                    If Not lParam < Message
                      lParam = Message - 1
                      EndIf
                    EndIf
                  EndIf
;debug "Scroll: 5 (ScrollDiv: " + lParam + ")"
                MouseWheelDeltaLst(xLong1) = MouseWheelDeltaLst(xLong1) % #MouseWheelDeltaDivLst
                If Not lParam = wParam
                  SendMessage_(hWnd, #LB_SETTOPINDEX, lParam, 0)
                  EndIf
                EndIf
              ElseIf Not PlayerIsLocked
              MouseWheelVolume(wParam)
              EndIf
            Break
          Case $201, $204 ;down
            If xLong1 = 2 And DragOut
              If DragDetectWinLikePL(lParam)
                MainFormDraggingIs = #True
                MainFormDraggingWParam = wParam
                MainFormDraggingLParam = lParam
                MainFormDraggingWMsgPlus = Message
                ProcedureReturn 0
                EndIf
              EndIf
            ;GoTo no
          Case $202, $205 ;up
            If xLong1 = 2 And MainFormDraggingIs
              CallWindowProc_(xListHWndHook(2), hWnd, MainFormDraggingWMsgPlus, MainFormDraggingWParam, MainFormDraggingLParam)
              MainFormDraggingIs = #False
              EndIf
            xLong2 = CallWindowProc_(xListHWndHook(xLong1), hWnd, Message, wParam, lParam)
              ;Else
  ;          Case $202, $205
    ;          FirstDown = -1
              Select xLong1
                Case 0
                  If xDirListModeCur = 0
                    ShowWindow_(xListHWnd(0), 0)
                    DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
                    EndIf
                  If Message = $202
                    MainForm_xSelDirNow()
                    If (wParam & $C) = 0 And xDirListModeCur
                      SetFocus_(xListHWnd(2))
                      EndIf
                    Else
                    MainForm_CheckDir(#True)
                    EndIf
                Case 1
                  If Message = $202
                    If MainForm_xLastDirNow(#False)
                      ShowWindow_(xListHWnd(1), 0)
                      DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
                      EndIf
                    Else
                    ShowWindow_(xListHWnd(1), 0)
                    DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
                    MainForm_xLastDirNot()
                    EndIf
                Case 2
                  If Message = $205 And Not (PlayerIsLocked Or xAutoDoing)
                    xLong1 = TrackListBox(xStaticIconsHWnd(#xStaticIcons_ShowIR), xListHWnd(2), SignedHigherWord(lParam), #True, 0, 1)
                    If Not xLong1 = -1
                      MainForm_CheckDir(#False)
                      MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(5), 0))
                      EndIf
                    EndIf
                  MainForm_CheckDir(#False)
                  ;GoTo NoProcKeyX
                EndSelect
              Break
            ProcedureReturn xLong2
          Case $100
            xLong2 = GetShiftCode()
            Select wParam
              Case 8, 9
                If Not IsAltPressed()
                  If wParam = 8
                    If xDirListModeCur = 0
                      MainForm_AdvanceSong(0)
                      EndIf
                    ElseIf xDirListModeCur = 0
                    If hWnd = xListHWnd(2)
                      MainForm_AdvanceSong(xLong2 + 1) ;- 2 * IsCtrlPressed
                      Else
                      SetFocus_(xListHWnd(2))
                      EndIf
                    Else
                    If hWnd = xListHWnd(2)
                      SetFocus_(xListHWnd(0))
                      Else
                      SetFocus_(xListHWnd(2))
                      EndIf
                    EndIf
                  EndIf
              Case 13
                Select xLong1
                  Case 0
                    If xDirListModeCur = 0
                      ShowWindow_(xListHWnd(0), 0)
                      DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
                      EndIf
                    MainForm_xSelDirNow()
                  Case 1
                    If MainForm_xLastDirNow(#True)
                      ShowWindow_(xListHWnd(1), 0)
                      DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
                      EndIf
                  Case 2
                    MainForm_PlayListDoubleClickEvent()
                  EndSelect
                Break
              Case 27
                If ((xLong1 = 1 And xDirListModeCur > 0) Or xLong1 = 2) And Not vKioskMode 
                  AbortReading = #True
                  EndIf
                Select xLong1
                  Case 0
                    If xDirListModeCur = 0
                      ShowWindow_(xListHWnd(0), 0)
                      DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
                      MainForm_CheckDir(#True)
                      EndIf
                  Case 1
                    ShowWindow_(xListHWnd(1), 0)
                    DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
                    MainForm_xLastDirNot()
                  EndSelect
                Break
              Case 33 To 36, 38, 40
                xFollowCurSongLastDiff = 0
                ProcedureReturn CallWindowProc_(xListHWndHook(xLong1), hWnd, Message, wParam, lParam)
              Case 0 To 4, 7 To 32, 93 ; 38, 40, 93
                ProcedureReturn CallWindowProc_(xListHWndHook(xLong1), hWnd, Message, wParam, lParam)
              Case 5, 6, 33 To 40 ;, $E7, $E8  ;40
                If xLong2 = 0 
                  ProcedureReturn CallWindowProc_(xListHWndHook(xLong1), hWnd, Message, wParam, lParam)
                  EndIf
              EndSelect
            If Not IsAltPressed()
              MainForm_TryFindKeyEvent((wParam & $FF) + xLong2 * $100)
              ProcedureReturn 0
              EndIf
          Case $101 ;keyup
            If xLong1 = 2
              MainForm_CheckDir(#False)
              If wParam = 93 And Not (GetShiftCode() Or PlayerIsLocked Or xAutoDoing)
                MainForm_MenuEvent(GetAPIPopupMenu(MainHWnd, xMenu(5), xListHWnd(2)))
                EndIf
              EndIf
          Case $20B, $AB
            If (wParam & $60)
              MainForm_TryFindKeyEventWParam(wParam)
              EndIf
            ProcedureReturn 0
          Case $203
            lParam = CallWindowProc_(xListHWndHook(xLong1), hWnd, Message, wParam, lParam)
            Select xLong1
              ;Case 0
              Case 1
                If Not xAutoDoing
                  If MainForm_xLastDirNow(#True)
                    ShowWindow_(xListHWnd(1), 0)
                    DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
                    EndIf
                  EndIf
              Case 2
               MainForm_PlayListDoubleClickEvent()
              EndSelect
            ProcedureReturn lParam
  CompilerIf #ListFocusedLists
          Case $7
            xCurFocusHWnd = hWnd
  CompilerEndIf
          Case $8
  CompilerIf #ListFocusedLists
            xCurFocusHWnd = wParam
  CompilerEndIf
            If xLong1 = 0 And xDirListModeCur = 0
              ShowWindow_(xListHWnd(0), 0)
              DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
              ElseIf xLong1 = 1
              ShowWindow_(xListHWnd(1), 0)
              DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
              EndIf
          EndSelect
;NoProcKey:
        ProcedureReturn CallWindowProc_(xListHWndHook(xLong1), hWnd, Message, wParam, lParam)
;NoProcKeyX:
        EndIf
      Break
      EndIf
    Next
  ;ProcedureReturn xResult
  EndProcedure

Procedure.i BARHook(hWnd.i, Message.i, wParam.i, lParam.i)
  Define.i xResult
  
  xResult = CallWindowProc_(BARHookOld, hWnd, Message, wParam, lParam)
  If Message = $111
    If wParam = 0
      MainForm_IconsMouseUpByHWnd(lParam)
      ElseIf wParam = $10000
      If lParam = xStaticIconsHWnd(#xStaticIcons_TimerInd)
        If Not (PlayerIsLocked Or xAutoDoing)
          ToggleInterface(#Interface_Mode_Timer)
          EndIf
        EndIf
      EndIf
    EndIf
  ProcedureReturn xResult
  EndProcedure

Procedure.i MainForm_DoCommand(EventID.i)
  Define.i xResult
  Define.i xLong1
  
  If EventID And Not (IsDialoging Or xNoIRMode Or PlayerIsLocked Or xAutoDoing)
    If vKioskMode
      Select EventID
        Case 510, 512, 513, 515 To 518, 520 To 522, 590
          If Not (xCmdQuitMode = 1 Or xCmdQuitMode = 3 Or xCmdQuitMode = 4)
            Goto OutFnc
            EndIf
        Case 222, 223, 230 To 240
          If Not vCanVolume
            Goto OutFnc
            EndIf
        Case 320, 330, 331, 340, 360
          Goto OutFnc
        EndSelect
      EndIf
    If vKioskMode
      Select EventID
        Case 220, 221, 390 To 392
          Goto OutFnc
        Case 400 To 403, 420 To 422, 430 To 432
          Goto OutFnc
        Case 440 To 442, 450, 460 To 463, 470 To 472
          Goto OutFnc
        Case 302 To 304
          If EventID - 302 > PlDClickAction
            Goto OutFnc
            EndIf
        EndSelect
      EndIf
    If (EventID > 510 And EventID < 518) Or (EventID > 519 And EventID < 523)
      If xTimerEditing
        Goto OutFnc
        EndIf
      EndIf
    xResult = 1
    Select EventID
      ;Case 1
      ;Case 2
      ;Case 100
      ;Case 101
      ;xOldIconState
      Case 200 To 205
        xNoRemove = #True
        MainForm_IconsMouseUp(EventID - 200)
        xNoRemove = #False
      ;seek back/volume
      Case 220
        xTrackSeekA(-1)
      Case 221
        xTrackSeekA(1)
      Case 222
        MainForm_ProcessKey(#KbdC_GVolUp)
        ChangeVolumeMenu(0)
      Case 223
        MainForm_ProcessKey(#KbdC_GVolDown)
        ChangeVolumeMenu(1)
      Case 230 To 240
        DoVolume(Int((EventID - 230) * 25.5), #True)
      Case 300
        MainForm_ProcessKey(#KbdC_GPrevSel)
      ;play song
      Case 301: MainForm_PlayListDoubleClickEvent()
      ;find current
      Case 302 To 304 ;play song ...
        MainForm_MenuEventPlaylist(EventID - 302)
      ;play next
      Case 305
      ;next item
        MainForm_ProcessKey(#KbdC_GNextSel, #False)
      ;Find Current:
      Case 306
        MainForm_ProcessKey(#KbdC_PFindCurrent, #False)
      ;select random
      Case 307
        MainForm_ProcessKey(#KbdC_PSelRnd, #False)
      ;page up/down
      Case 318
        MainForm_ProcessKey(#KbdC_GPrevPage, #False)
      Case 319
        MainForm_ProcessKey(#KbdC_GNextPage, #False)
      Case 320
        MainForm_xAutoRefreshNow(#False, #False, #False, #False, #False)
      Case 330
        xRemoveItems(#True)
      Case 331
        xRemoveItems(#False)
      Case 340 ;Stop, AutoRefresh, Start(Random)Song
        AutoRefreshHandler(4)
      Case 360 ; abortreading
        AbortReading = #True
      Case 390
        If MP3GetID3Tag
          MP3GetID3Tag = #False
          Else
          MP3GetID3Tag = #True
          EndIf
      Case 391
        MP3GetID3Tag = #True
      Case 392
        MP3GetID3Tag = #False
      Case 400
          xRep = (xRep + 1) % 3
          MainForm_ApplyRepMode()
      Case 401 To 403: xRep = EventID - 401
      ;Fading
      Case 410
        If xGenFading
          xGenFading = #False
          Else
          xGenFading = #True
          EndIf
      Case 411: xGenFading = #True
      Case 412: xGenFading = #False
      ;SpectrumToggle
      Case 420: SpektrumToggleEvent()
      Case 421
        If Not xShowSpectrum
          SpektrumToggleEvent()
          EndIf
      Case 422
        If xShowSpectrum
          SpektrumToggleEvent()
          EndIf
      ;RemoveMissing
      Case 430
        If xRemoveMissingSongs
          xRemoveMissingSongs = #False
          Else
          xRemoveMissingSongs = #True
          EndIf
      Case 431: xRemoveMissingSongs = #True
      Case 432: xRemoveMissingSongs = #False
      ;RemoveSkippedSongs
      Case 440
        If xRemoveSkippedSongs
          xRemoveSkippedSongs = #False
          Else
          xRemoveSkippedSongs = #True
          EndIf
      Case 441: xRemoveSkippedSongs = #True
      Case 442: xRemoveSkippedSongs = #False
      ;RemovePlayed
      Case 450
        If xRemovePlayedSongs
          xRemovePlayedSongs = #False
          Else
          xRemovePlayedSongs = #True
          EndIf
      Case 451: xRemovePlayedSongs = #True
      Case 452: xRemovePlayedSongs = #False
      ;EndSongMode
      Case 460
        xProcessMode = (xProcessMode + 1) & 3
      Case 461 To 464
        xProcessMode = EventID - 461
      Case 465 To 467
        If xProcessMode = EventID - 464
          xProcessMode = 0
          Else
          xProcessMode = EventID - 464
          EndIf
      ;Intromode
      Case 480
        If IntroModeActive
          IntroModeActive = #False
          Else
          IntroModeActive = #True
          EndIf
      Case 481: IntroModeActive = #True
      Case 482: IntroModeActive = #False
      
      Case 510 ;off
        If Not xTimerEvIR = -1
          xTimerRemove(xTimerEvIR)
          xTimerEvIR = -1
          If InterfaceMode = #Interface_Mode_Timer
            TimerListForm_ListUpdate()
            Else
            ResortTimers()
            MainForm_SetTimerImage()
            EndIf
          EndIf
      Case 512 ;+30
        GrabError()
        If xTimerEvIR = -1
          xTimerEvIR = xTimerChange(-1, (GetLocalTimeHM() + 30) % 1440, LoadResString(2799) + "=" + Str(#KbdCTm_FShutDown), #False)
          Else
          xLong1 = (xTimerEvTime(xTimerEvIR - GetLocalTimeHM()) + 30 + 1440) % 1440
          If xLong1 > 1410
            xLong1 = 1410
            EndIf
          xTimerEvIR = xTimerChange(xTimerEvIR, (GetLocalTimeHM() + xLong1) % 1440, "", #True)
          EndIf
        If InterfaceMode = #Interface_Mode_Timer
          TimerListForm_ListUpdate()
          Else
          ResortTimers()
          MainForm_SetTimerImage()
          EndIf
      Case 513 ;-30
        GrabError()
        If Not xTimerEvIR = -1
          xLong1 = (xTimerEvTime(xTimerEvIR) - GetLocalTimeHM() - 30 + 1440) % 1440
          If Not xLong1 > 0
            xTimerRemove(xTimerEvIR)
            xTimerEvIR = -1
            Else
            xTimerEvIR = xTimerChange(xTimerEvIR, (xLong1 + GetLocalTimeHM()) % 1440, "", #True)
            EndIf
          If InterfaceMode = #Interface_Mode_Timer
            TimerListForm_ListUpdate()
            Else
            ResortTimers()
            MainForm_SetTimerImage()
            EndIf
          EndIf
      Case 515 To 518 ;30-60-90-120
        GrabError()
        If xTimerEvIR = -1
          xTimerEvIR = xTimerChange(-1, (GetLocalTimeHM() + (EventID - 514) * 30) % 1440, LoadResString(2799) + "=" + Str(#KbdCTm_FShutDown), #False)
          Else
          xTimerEvIR = xTimerChange(xTimerEvIR, (GetLocalTimeHM() + (EventID - 514) * 30) % 1440, "", #True)
          EndIf
        If InterfaceMode = #Interface_Mode_Timer
          TimerListForm_ListUpdate()
          Else
          ResortTimers()
          MainForm_SetTimerImage()
          EndIf
      Case 590
        PostMessage_(xStaticIconsHWnd(#xStaticIcons_ShowIR), $400, -1, 2)
        Goto OutFnc
      Case 600
        MainForm_ProcessKey(#KbdC_GShowPlayer, #False)
      Case 601
        If xTrayIconEnabled
          ;Me.Visible = #False
          ShowWindow_(MainHWnd, 0)
          xTrayIconIndicator = #True
          MainForm_ShowTray(#False)
          Else
          ShowWindow_(MainHWnd, 7)
          EndIf
      Case 610
        If xPStateIconPlaying And Not (CurMusic = #ctSSLayer_MusicTypeNone Or PlayerIsLocked)
          ShowIR_Do(#False)
          EndIf
      EndSelect
    
    
    Select EventID
      Case 390 To 392
        CheckApiMenu(303, MP3GetID3Tag)
        If MP3GetID3Tag
          ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Tags), 5)
          Else
          ShowWindow_(xStaticIconsHWnd(#xStaticIcons_Tags), 0)
          EndIf
        ;ePic(7).Visible = MP3GetID3Tag
        If MP3GetID3Tag
          MainForm_ReadLate("", #True)
          EndIf
        SetPanelSize()
      Case 400 To 403
        MainForm_ApplyRepMode()
      Case 410 To 412
        CheckApiMenu(301, xGenFading)
      Case 430 To 432
        CheckApiMenu(320, xRemoveMissingSongs)
      Case 440 To 442
        CheckApiMenu(321, xRemoveSkippedSongs)
      Case 450 To 452
        CheckApiMenu(322, xRemovePlayedSongs)
      Case 460 To 467 ;, 470 To 472
        MainForm_ApplyProcessMode()
      Case 480 To 482
        ;CheckApiMenu 119, IntroModeActive
        MainForm_ApplyRepMode()
      EndSelect
    EndIf

OutFnc:
  Select EventID
    Case 1, 200 To 205
      xResult = 0
      If xPStateIconPlaying
        If xPStateIconPaused
          xResult = 2
          Else
          xResult = 1
          EndIf
        EndIf
    Case 2
      ;xResult = 0
      If xOldIconState = -1
        xResult = 3
        Else
        xResult = xOldIconState
        EndIf
    Case 222, 223, 230 To 240
      xResult = xSetVolume
    Case 390 To 392
      If MP3GetID3Tag
        xResult = 1
        Else
        xResult = 0
        EndIf
    Case 400 To 403: xResult = xRep
    Case 410 To 412
      If xGenFading
        xResult = 1
        Else
        xResult = 0
        EndIf
    Case 420 To 422
      If xShowSpectrum
        xResult = 1
        Else
        xResult = 0
        EndIf
    Case 430 To 432
      If xRemoveMissingSongs
        xResult = 1
        Else
        xResult = 0
        EndIf
    Case 440 To 442
      If xRemoveSkippedSongs
        xResult = 1
        Else
        xResult = 0
        EndIf
    Case 450 To 452
      If xRemovePlayedSongs
        xResult = 1
        Else
        xResult = 0
        EndIf
    Case 460 To 467
      If xProcessMode
        xResult = 1
        Else
        xResult = 0
        EndIf
    Case 480 To 482
      If IntroModeActive
        xResult = 1
        Else
        xResult = 0
        EndIf
    EndSelect
  ProcedureReturn xResult
  EndProcedure

Procedure.i ProcClassWnd(hWnd.i, Message.i, wParam.i, lParam.i)
  Select Message
    Case $F ;WM_PAINT = $F
      IRDraw()
      ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
    Case $1A ;, $1B ;WM_SETTINGCHANGE
      If wParam = 47
        CheckValidScreen(#True)
        IRPos(#True)
        EndIf
    Case $7E ; screenchange
      CheckValidScreen(#True)
      IRPos(#True)
    Case $200 ;Const WM_MOUSEMOVE = $200
      MainForm_TrayIconHandling(lParam & $FFFF)
    Case $113 ;Const WM_TIMER = $113
      IRPos(#False)
    Case 2 ;Forgotten :)
    Case $15 ;syscolorchange
      GetWhiteBackGrnd();#False
      MainForm_UpdateMyFont()
      ForceIRPosUpdate()
      MainForm_ResizePlayer(#False)
    Case $31A
      DoThemeUpdates()
      If InterfaceMode = #Interface_Mode_None
        DrawWhiteDC(xStaticIconsHWnd(#xStaticIcons_DirList), xListHWnd(0), 1, #True)
        EndIf
      DrawWhiteDC(xStaticIconsHWnd(#xStaticIcons_CurSong), xListHWnd(1), 0, #True)
    Case $4A ; senddata
      ProcedureReturn MainForm_GetMessageA_CopyData(lParam)
      ;ProcClassWnd =
    Case $218 ;$48 ;WM_PowerMsgs
      If wParam = 4 Or wParam = 5
        MainForm_SetStandby(#True)
        ElseIf wParam = 7 Or wParam = 8 Or wParam = $12
        If LEDMode = 0 Or Not wParam = $12
          MainForm_SetStandby(#False)
          EndIf
        EndIf
    Case $312 ;wm_HotKey
      CompilerIf #NewKeyMode
        wParam = #KbdSplitN + wParam
;debug "#HotKey: ", wParam
        If Not wParam = RGK_xOldKey
;debug "#HotKeyFirst", wParam, RGK_xOldKey
          RGK_xOldKeyTime = GetTickTimeMS()
          RGK_xOldKeyTimeWait = #RGK_xOldKeyTimeWaitLong
          If RGK_xOldKey = #KbdC_GShowTitle And RGK_xOldKeyTimeWait = #RGK_xOldKeyTimeWaitShort
            RGK_xOldKey = wParam
            MainForm_ProcessKey(wParam)
            MainForm_HideIRWin()
            Else
            RGK_xOldKey = wParam
            MainForm_ProcessKey(wParam)
            EndIf
;debug "LP: ", RGK_xOldKey
;Else
;debug "#HotKeyAgain"
          EndIf
        CompilerElse
        MainForm_ProcessKey(KbdSplitN + wParam)
        CompilerEndIf
    Case $400, $111
      ;wParam = 205
;debug "WM_COMMAND", wParam, lParam
      Select wParam
        Case 1, 2, 200 To 205, 220 To 223, 230 To 240
          ProcedureReturn MainForm_DoCommand(wParam) ;, lParam
        Case 300 To 307, 318, 319, 320, 330 To 331, 340, 360, 390 To 392
          ProcedureReturn MainForm_DoCommand(wParam) ;, lParam
        Case 400 To 403, 410 To 412, 420 To 421, 430 To 432, 440 To 442, 450 To 453, 460 To 467
          ProcedureReturn MainForm_DoCommand(wParam) ;, lParam
        Case 510, 512, 513, 515 To 518, 590, 600, 601, 610
          ProcedureReturn MainForm_DoCommand(wParam) ;, lParam
        Case 800, 801, 804, 805, 810 To 817
          ProcedureReturn SMQueryString(wParam, lParam)
        Case -2
          MainForm_EndSongCallback(lParam)
        Case -1
          Select lParam
            Case 1
              MainForm_DelayedDragDrop()
            Case 2, 4 To 6
              If hwndShutDownDialog = 0
                If lParam = 2
                  QuitModePending = 1
                  Else
                  QuitModePending = lParam - 2
                  EndIf
                If (PlayerIsLocked Or xAutoDoing)
                  WantsShutdownDialog = #True
                  Else
                  StartShutDownStuff()
                  EndIf
                EndIf
            Case 3
              PostGetMessage()
            ;Case 4 to 6 see 1
            EndSelect
        EndSelect
    Case $D ; WM_GETTEXT
      ProcedureReturn FastCopy(hWnd, wParam, lParam)
    Case $E ; WM_GETTEXTLENGTH = $E
      ProcedureReturn FastCopy(hWnd, wParam, *ptrTemp)
    Default
      If Not FinalTimersDisabled
;ForceProc:
        ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
        EndIf
    EndSelect
  ProcedureReturn 0
  EndProcedure

Procedure.i PlayerFormProc(hWnd.i, Message.i, wParam.i, lParam.i)
  Select Message
    Case $2B ; WM_DRAWITEM
      DrawPLItem(lParam)
      ProcedureReturn 1
    Case $3 ; WM_MOVE
      ResizeRemember()
    Case $5 ; WM_SIZE
      If wParam = 0
        ResizeRemember()
        EndIf
      MainForm_ResizePlayer(#True)
    Case $7 ; WM_SETFOCUS
      BestFocus()
    Case $6 ; WM_ACTIVATE
      If IsWindowVisible_(xListHWnd(0)) And xDirListModeCur = 0
        ShowWindow_(xListHWnd(0), 0)
        DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_DirList), 1, 0)
        EndIf
      If IsWindowVisible_(xListHWnd(1))
        ShowWindow_(xListHWnd(1), 0)
        DrawWhiteDCDropButton(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0)
        EndIf
      PlayerFormAbortMoveAndDrags()
      ;PlayerFormProc = 0
      ProcedureReturn 0
    Case $16 ; WM_ENDSESSION
      If Not wParam = 0
        Goto EndSessionClose
        EndIf
    Case $10 ; WM_CLOSE
EndSessionClose:
      PlayerFormAbortMoveAndDrags()
      MainForm_UnloadPlayer()
    Case $111 ; WM_COMMAND
      Select InterfaceMode
        Case #Interface_Mode_None, #Interface_Mode_Wizard
          If lParam = 0
            MainForm_MenuEvent(wParam)
            EndIf
        Case #Interface_Mode_Search
          If Not lParam = 0
            SearchForm_TrySCommand(lParam, wParam)
            EndIf
        Case #Interface_Mode_Timer
          If lParam = 0
            TimerListForm_MenuEvent(wParam)
            Else
            TimerListForm_ButtonEvent(lParam) ;, wParam
            EndIf
        Case #Interface_Mode_Radio
          If lParam = 0
            RadioForm_MenuEvent(wParam)
            Else
            RadioForm_TrySCommand(lParam)
            EndIf
        EndSelect
      ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
    Case $233 ; WM_DROPFILES

      If ((GetAsyncKeyState_($10) & #AsyncKeyPressedMask) And LEDMode = 0)
        lParam = 4
        Else
        lParam = 0
        EndIf
      MainForm_DropFiles(wParam, lParam)
      ;MainForm_DropFilesLite(wParam) ;, 1, 0
    Case $A1 ; WM_NCLBUTTONDOWN
      If hWnd = xStaticIconsHWnd(#xStaticIcons_CurSongPos)
        MainForm_ePic_MouseDown(100, 0)
        ProcedureReturn 0
        EndIf
      ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
    Case $100 ; WM_KEYDOWN
      Select wParam
        Case 9
          LoadResEx_Window_ManualTab(MainHWnd, hWnd)
          ProcedureReturn 0
        Case 27
          If Not InterfaceMode = #Interface_Mode_None
            ToggleInterface(#Interface_Mode_None)
            EndIf
        EndSelect
    Case $20B, $AB
      If (wParam & $60)
        MainForm_TryFindKeyEventWParam(wParam)
        EndIf
    Case $211 ; WM_ENTERMENULOOP
      PlayerInMenuLoop = #True
    Case $212 ; WM_EXITMENULOOP
      PlayerInMenuLoop = #False
    Case $105 ;syskeyup
      Select InterfaceMode
        Case #Interface_Mode_Search: SearchForm_TryAccel(wParam)
        Case #Interface_Mode_Timer:  TimerListForm_TryAccel(wParam)
        Case #Interface_Mode_Radio: RadioForm_TryAccel(wParam)
        ;Case #Interface_Mode_Wizard: WizardForm_TryAccel(wParam)
        EndSelect
    Case $20A ;WM_MouseWheel
      If (wParam & $C) And Not PlayerIsLocked
        MouseWheelVolume(wParam)
        EndIf
;$211
    Case RegisteredFindMsgID
      If RegisteredFindMsgID = 0
        ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
        ElseIf (CurrentFindType\Flags & $40) = 0
        If Not (CurrentFindType\Flags & $8) = 0
          If (CurrentFindType\Flags & $4) = 4
            CurrentFindMatchCase = #PB_String_CaseSensitive
            Else
            CurrentFindMatchCase = #PB_String_NoCase
            EndIf
          If (CurrentFindType\Flags & $1) = 1
            CurrentFindInvert = 1
            Else
            CurrentFindInvert = -1
            EndIf
          FindNowCB()
          EndIf
        ElseIf Not CurrentFindHWnd = 0
        CurrentFindHWnd = 0
        LocalFree_(CurrentFindHMem)
        CurrentFindHMem = 0
        DialogTimer(#False)
        EnableWindow_(MainHWnd, 1)
        EndIf
    Case $219 ;Const WM_DEVICECHANGE.i = $219
      ;Const BROADCAST_QUERY_DENY.i = $424D5144
      ;BROADCAST_QUERY_DENY
      Select wParam
        Case $8000 ; DBT_DEVICEARRIVAL
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("DeviceChange: DBT_DEVICEARRIVAL")
            CompilerEndIf
          If Not xPStateIconQuit
            MainForm_XMenuRefresherDevices()
            ;If vKioskMode                ;Or DeviceAddAutoPlay
              RemoveDevicesAutoAdd(lParam)
            ;  endif
            EndIf
          ProcedureReturn #True
        Case $8001 ; DBT_DEVICEQUERYREMOVE
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("DeviceChange: DBT_DEVICEQUERYREMOVE")
            CompilerEndIf
CompilerIf #UseFileLogging
          If RemoveDevicesLock(lParam, #True)
            MainForm_ctConsoleA_AddLog("  permitted (player is locked now)")
CompilerElse
          If RemoveDevicesLock(lParam, #True)
CompilerEndIf
            RemoveDevices(lParam, #False)
            ProcedureReturn 1
;GoTo AlsoRemoveNow
            Else
            CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  denied (player is locked)")
              CompilerEndIf
            ProcedureReturn $424D5144
            EndIf
        Case $8002 ; DBT_DEVICEQUERYREMOVEFAILED
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("DeviceChange: DBT_DEVICEQUERYREMOVEFAILED")
            CompilerEndIf
          If IsDevicePlugging And RemoveDevicesAffectsVolumes(lParam)
            If HasDevicePlugStoppedSong
              StoreResume(#True, 0)
              EndIf
            RemoveDevicesUnlock()
            EndIf
          ProcedureReturn #True
        Case $8003 ; DBT_DEVICEREMOVEPENDING
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("DeviceChange: DBT_DEVICEREMOVEPENDING")
            CompilerEndIf
          RemoveDevicesLock(lParam, #False)
;AlsoRemoveNow:
          RemoveDevices(lParam, #True)
          ;RemoveDevicesUnlock
          ProcedureReturn #True
        Case $8004 ; DBT_DEVICEREMOVECOMPLETE
          CompilerIf #UseFileLogging
            MainForm_ctConsoleA_AddLog("DeviceChange: DBT_DEVICEREMOVECOMPLETE")
            CompilerEndIf
          If RemoveDevicesAffectsVolumes(lParam)
            ;compilerif #UseFileLogging
            ;  MainForm_ctConsoleA_AddLog("  affects volumes")
            ;  compilerendif
            If Not HasDevicePlugged
              RemoveDevices(lParam, #True)
              EndIf
            HasDevicePlugged = #False
            MainForm_XMenuRefresherDevices()
            If HasDevicePlugStoppedSong
              RemoveDevicesUnlock()
              StoreResume(#True, 1)
              Else
              RemoveDevicesUnlock()
              EndIf
            CompilerIf #PB_Compiler_Unicode And #XPDeviceRemoveDetect
              CompilerIf #XPDeviceRemoveDetectPST
                PendingDeviceRegB = #True
                PendingDeviceRegT = GetTickTimeMS()
                CompilerElse
                RemovableDevices_UnregisterAll()
                RemovableDevices_RegisterAll(MainHWnd)
                CompilerEndIf
              CompilerEndIf
            EndIf
          ProcedureReturn #True
        Default
          ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
        EndSelect
CompilerIf #LoadShellDriveIcons
    Case $120 ; WM_MENUCHAR
      ProcedureReturn MainMenu_MenuChar(wParam, lParam)
    Case $2C ; WM_MEASUREITEM
      DefWindowProc_(hWnd, Message, wParam, lParam)
      MainMenu_MeasureItem(lParam)
      ProcedureReturn 1
CompilerEndIf
    Default
      ProcedureReturn DefWindowProc_(hWnd, Message, wParam, lParam)
    EndSelect
  ProcedureReturn 0
  EndProcedure

Procedure MainForm_MenuEventPlaylist(Index.i)
  Define.i xLong1
  Define.i xLong2
  Define.s xChar1

  If Not (PlayerIsLocked Or xAutoDoing)
    Select Index
      Case 0 To 2
        If PLCount And GetListIndexMS(xListHWnd(2), @xLong1)
CompilerIf #BoldDirs = 98
          If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = 0
            If IsFileExists(PLI(xLong1)\Filename)
CompilerElse
          If (PLIDF(xLong1) & #PLI_IsDir) = 0
            If IsFileExists(PLIFile(xLong1))
CompilerEndIf
              If Index = 2 And Not xPStateIconPlaying
                PLCurItem = xLong1
                Else
                If Not PlNextSong = ""
                  SetNextSong(#False)
                  EndIf
                If xPStateIconPaused And Not Index = 2
                  xPStateIconPlaying = #False
                  xPStateIconPaused = #False
                  xReAutoPlay = #False
                  ReAutoPlayDR = #False
                  MainForm_UpdateMainIcon()
                  MainForm_LockMe(#True) ;;;;;;;;;;;
                  MainForm_xEndSong(#False, #False, #False, #False)
                  MainForm_LockMe(#False) ;;;;;;;;;;;;
                  If xRemoveSkippedSongs And Not (xNoRemove Or (PLNext = PLCurItem And Len(PlNextSong)))
                    MainForm_RemoverX(#False)
                    xNoRemove = #True
                    EndIf
                  EndIf
                If Not xPStateIconPlaying
                  PLCurItem = xLong1
                  MainForm_xPlayClick(#False)
                  Else
                  If (Index = 0 Or Index = 1 And Not xRemovePlayedSongs) And xRemoveSkippedSongs And xPStateIconPlaying And PLCount And Not (xNoRemove Or (PLNext = xLong1 And Len(PlNextSong)))
                    PlNextSong = Chr(255)
                    PlNextSongCap = ""
                    PLNext = xLong1
                    MainForm_RemoverX(#False)
                    PLCurItem = PLNext
                    PlNextSong = ""
                    Else
                    PLNext = xLong1
                    EndIf
                  Select Index
                    Case 0
                      PLCurItem = PLNext
                      MainForm_LockMe(#True)
                      MainForm_xEndSong(#True, #False, #False, #False)
                      MainForm_LockMe(#False)
                      MainForm_xPlayClick(#False)
                    Case 1, 2
                      CompilerIf #BoldDirs = 98
                        PlNextSong = PLI(PLNext)\Filename
                        PlNextSongCap = PLI(PLNext)\Caption
                        CompilerElse
                        PlNextSong = PLIFile(PLNext)
                        PlNextSongCap = PLICap(PLNext)
                        CompilerEndIf
                      If Index = 1
                        MainForm_CheckAfter(#True, #True, #True, #False)
                        Else
                        SetNextSong(#True)
                        EndIf
                    EndSelect
                  EndIf
                EndIf
              Else
              CheckThisSong(xLong1)
              MainForm_LockMe(#False)
              EndIf
            EndIf
          EndIf
      Case 4, 400 ;find current
        xLong1 = xFindSong()
        If Not GetListIndexMS(xListHWnd(2), @xLong2)
          xLong2 = 0
          EndIf
        If Not (xLong1 = 0 Or xLong2 = xLong1)
          xMarkSong(xLong1, #False, #False)
          ElseIf Not Index = 400
          If Not PlNextSong = ""
CompilerIf #BoldDirs = 98
            If PLI(PLNext)\Filename = PlNextSong
CompilerElse
            If PLIFile(PLNext) = PlNextSong
CompilerEndIf
              xLong1 = PLNext
              Else
              xLong1 = xFindSong(PlNextSong)
              If Not xLong1 = 0
                PLNext = xLong1
                EndIf
              EndIf
            If Not xLong1 = 0
              xMarkSong(xLong1, #False, #False)
              EndIf
            Else
            If Not xLong1 = 0
              SendMessage_(xListHWnd(2), #LB_SETSEL, 0, xLong2)
              xMarkSong(xLong2, #False, #False)
              EndIf
            EndIf
          EndIf
      Case 5, 6 ;find...
        If Not PLCount = 0
          If Index = 6 And Len(xFindNextString)
            If FindNext()
              ProcedureReturn
              EndIf
            EndIf
          If CurrentFindHMem = 0 And CurrentFindHWnd = 0
            If RegisteredFindMsgID = 0
              RegisteredFindMsgID = RegisterWindowMessage_(@"commdlg_FindReplace")
              EndIf
            If Not RegisteredFindMsgID = 0
              CurrentFindHMem = LocalAlloc_(0, 514)
              If CurrentFindHMem
                RtlZeroMemory_(CurrentFindType, SizeOf(CurrentFindType))
                CurrentFindType\lStructSize = SizeOf(CurrentFindType)
                CurrentFindType\lpstrFindWhat = CurrentFindHMem
                ;CurrentFindType.hInstance = App.hInstance
                CurrentFindType\wFindWhatLen = 514
                ;CurrentFindType.flags = $1C000
                If CurrentFindInvert = -1
                  ;CurrentFindType.flags = $10000
                  CurrentFindType\Flags = $1000
                  Else
                  ;CurrentFindType.flags = $10001
                  CurrentFindType\Flags = $1001
                  EndIf
                If CurrentFindMatchCase = #PB_String_CaseSensitive
                  CurrentFindType\Flags = CurrentFindType\Flags | 4
                  EndIf
                  
                CurrentFindType\hWndOwner = MainHWnd
                xLong1 = Len(xFindNextString)
                EnableWindow_(MainHWnd, 0)
                CompilerIf #PB_Compiler_Unicode
                  RtlMoveMemory_(CurrentFindHMem, @xFindNextString, xLong1 << 1)
                  PokeW(CurrentFindHMem + xLong1 << 1, 0)
                  CompilerElse
                  RtlMoveMemory_(CurrentFindHMem, @xFindNextString, xLong1)
                  PokeB(CurrentFindHMem + xLong1 << 1, 0)
                  CompilerEndIf
                CurrentFindHWnd = FindText_(@CurrentFindType)
                If CurrentFindHWnd = 0
                  LocalFree_(CurrentFindHMem)
                  CurrentFindHMem = 0
                  EnableWindow_(MainHWnd, 1)
                  Else
                  DialogTimer(#True)
                  EndIf
                EndIf
              EndIf
            ;Do
            ;  xChar1 = InputBox(LoadResString(1441), LoadResString(1440), xFindNextString)
            ;  If Trim(xChar1) = ""
            ;    Exit Do
            ;    Else
            ;    xFindNextString = xChar1
            ;    If FindNext
            ;       Exit Do
            ;       EndIf
            ;    endif
            ; Loop
           EndIf
         EndIf
      Case 13, 14 ;move/merge at playlist end  /  merge in new playlist
        If PLCount > 1 And PLCount < PLCountMaxX And SendMessage_(xListHWnd(2), $190, 0, 0) > 0
          For xLong1 = 0 To PLCount - 1
CompilerIf #BoldDirs = 98
            If (PLI(xLong1)\DirDepthFlags & #PLI_IsDir) = 0
CompilerElse
            If (PLIDF(xLong1) & #PLI_IsDir) = 0
CompilerEndIf
              If SendMessage_(xListHWnd(2), #LB_GETSEL, xLong1, 0)
CompilerIf #BoldDirs = 98
                sCharA1(xLong2) = PLI(xLong1)\Filename
CompilerElse
                sCharA1(xLong2) = PLIFile(xLong1)
CompilerEndIf
;debug "Using: " + sCharA1(xLong2)
                xLong2 = xLong2 + 1
                If xLong2 = sCharA1Max
                  Break
                  EndIf
                EndIf
              EndIf
            Next
          If Not xLong2 = 0
            InitResearchClear()
            ;resetradiolist
            If Index = 14
              PLCount = 0
              PLCurItem = 0
              If Not PlNextSong = ""
                SetNextSong(#False)
                EndIf
              ClearPLEx()
              EndIf
            GenCalaymStructure(#False, xLong2, xSorting)
            If Index = 14
              CheckOldItems()
              If Not PLCurItem = 0
                xMarkSong(PLCurItem, #True, #False)
                EndIf
              EndIf
            InitResearch(#False)
            EndIf
          EndIf
      EndSelect
    EndIf
  EndProcedure

Procedure ToggleInterface(NewID.i)
  If Not NewID = InterfaceMode
    Select InterfaceMode
      Case #Interface_Mode_None:   InterfacePlayer(0)
      Case #Interface_Mode_Search: SearchForm_UnInterface()
      Case #Interface_Mode_Timer:  TimerListForm_UnInterface()
      Case #Interface_Mode_Radio:  RadioForm_UnInterface()
      Case #Interface_Mode_Wizard: WizardForm_UnInterface()
      EndSelect
    UnInterface()
    InterfaceMode = NewID
    Select InterfaceMode
      Case #Interface_Mode_None:   InterfacePlayer(5)
      Case #Interface_Mode_Search: SearchForm_Interface()
      Case #Interface_Mode_Timer:  TimerListForm_Interface()
      Case #Interface_Mode_Radio:  RadioForm_Interface()
      Case #Interface_Mode_Wizard: WizardForm_Interface()
      EndSelect
    DrawMenuBar_(MainHWnd)
    MainForm_ResizePlayer(#False)
    BestFocus()
    EndIf
  EndProcedure




Procedure MainForm_UpdateMyFont() ;(AlsoDefault As Boolean)
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i xLong4
  Define.s xChar1
  Define.LOGFONT xType1
  Define.POINT xType2
  Define.RECT xType3
  Define.NONCLIENTMETRICS xType4

  ;Const LenNONCLIENTMETRICS_A = 325
  ;Const LenNONCLIENTMETRICS_W = 485 ; - 4?
  
  
  hFontGSys = GetStockObject_(17)
  xGlobalDialogUnits = GetGDU(hFontGSys) ;CLng(GetDialogBaseUnits & $FFFF) / (2 * CLng(xType1\X / 62))
  
  
  
  SystemParametersInfo_(#SPI_GETICONTITLELOGFONT, SizeOf(LOGFONT), @xType1, 0)
  ;debug xType1\lfQuality
  If DPIScaleY > 1 And xType1\lfQuality < 2
    xType1\lfQuality = 2
    EndIf

  xLong3 = xType1\lfHeight
  xType1\lfHeight = -11 * DPIScaleY ; \ xGlobalDialogUnits)
  xLong1 = CreateFontIndirect_(@xType1)
  xGlobalDialogUnitsGFix = GetGDU(xLong1)
  SendMessage_(xStaticIconsHWnd(#xStaticIcons_Tags), $30, xLong1, 1)
  SendMessage_(xListHWnd(1), $30, xLong1, 1)
  Select InterfaceMode
    Case #Interface_Mode_Search: SearchForm_UpdateFont(xLong1, 1)
    Case #Interface_Mode_Timer:  TimerListForm_UpdateTimerListWinFont(xLong1)
    Case #Interface_Mode_Radio:  RadioForm_UpdateFont(xLong1, 1)
    Case #Interface_Mode_Wizard
      CompilerIf #WizardHasLabel
        WizardForm_UpdateFont(xLong1, 1)
        CompilerElse
        WizardForm_UpdateFont()
        CompilerEndIf
    EndSelect
  
  SelectObject_(xSharedDC, xSharedDCOldFont)
  If Not hFontGFix = 0
    DeleteObject_(hFontGFix)
    EndIf
  hFontGFix = xLong1
  If InterfaceMode = #Interface_Mode_Timer
    TimerListForm_ReDetectWidth()
    EndIf

  
  xLastPathCurMaxWidth = 0
  SelectObject_(xSharedDC, xLong1)
  For xLong2 = 0 To xLastPathCount - 1 ;maxx
    xLastPathLen(xLong2) = GetTextOutWidth(xSharedDC, xLastPathCap(xLong2))
    If xLastPathLen(xLong2) > xLastPathCurMaxWidth
      xLastPathCurMaxWidth = xLastPathLen(xLong2)
      EndIf
    Next

  
  If GetTextExtentPoint32_(xSharedDC, #DefTxt, #LenDefTxt, @xType2)
    xType3\Bottom = xType2\y << 1
    AdjustWindowRectEx_(xType3, $50000944, 0, $20000)
    xTagBoxHeight = xType3\Bottom - xType3\Top
    EndIf




  xLastPathTimeSpace = 0
  For xLong1 = 0 To 9
    xChar1 = Chr(xLong1 + 48) + Chr(xLong1 + 48)
    xChar1 = " " + xChar1 + ":" + xChar1 + ":" + xChar1 + xChar1
    xLong2 = GetTextOutWidth(xSharedDC, xChar1)
    If xLong2 > xLastPathTimeSpace
      xLastPathTimeSpace = xLong2 ;some space!
      EndIf
    Next
  
  ;xLongA1(0) = xLastPathTimeSpace * xGlobalDialogUnitsGFix
  ;xLongA1(1) = (xLastPathTimeSpace + xLastPathCurMaxWidth) * xGlobalDialogUnitsGFix ;* 4
  ;SendMessage_(xListHWnd(1), $192, 2, VarPtr(xLongA1(0)))
  SendMessage_(xListHWnd(1), $194, (32 + xLastPathTimeSpace + xLastPathCurMaxWidth), 0)
  
  ReCreateIRFont()
  
  xType1\lfHeight = xLong3
  xLong4 = xType1\lfWeight
  If xType1\lfWeight > 499
    xType1\lfWeight = 900
    ElseIf xType1\lfWeight < 300
    xType1\lfWeight = 600
    Else
    xType1\lfWeight = xType1\lfWeight + 300
    EndIf
  xLong1 = CreateFontIndirect_(@xType1)
  SendMessage_(xListHWnd(2), $30, xLong1, 1)
  If InterfaceMode = #Interface_Mode_Search
    SendMessage_(Interface_Control(#Interface_Control_Search_Results), $30, xLong1, 1)
    ;ElseIf InterfaceMode = #Interface_Mode_Radio
    ;SendMessage_(Interface_Control(#Interface_Control_Radio_List), $30, xLong1, 1)
    EndIf
  If Not hFontPLLgB = 0
    DeleteObject_(hFontPLLgB)
    EndIf
  hFontPLLgB = xLong1

  xType1\lfWeight = xType1\lfWeight - 300
  xType1\lfHeight = xLong3
  xLong1 = CreateFontIndirect_(@xType1)
  If InterfaceMode = #Interface_Mode_Radio
    SendMessage_(Interface_Control(#Interface_Control_Radio_List), $30, xLong1, 1)
    EndIf
  If Not hFontPLLg = 0
    DeleteObject_(hFontPLLg)
    EndIf
  hFontPLLg = xLong1



  xType1\lfWeight = xLong4
;  xType1\lfHeight = Int(21 / xGlobalDialogUnits)
  xType1\lfHeight = -11 * DPIScaleY ; \ xGlobalDialogUnits)
  xLong1 = CreateFontIndirect_(@xType1)
  SendMessage_(xListHWnd(0), $30, xLong1, 1)
  If Not hFontPLSm = 0
    DeleteObject_(hFontPLSm)
    EndIf
  hFontPLSm = xLong1
  xGlobalDialogUnitsPLSm = GetGDU(xLong1)
  SelectObject_(xSharedDC, hFontPLSm)
  GetTextExtentPoint32_(xSharedDC, #DefTxt, #LenDefTxt, xType2)
  PLSHeight = xType2\y
  If PLSHeight < 17
    PLSHeight = 17
    ;Else
    ;PLODHeight = PLODHeight + 4
    EndIf
  PLSIconTopShift = (PLSHeight - 16) >> 1
  SendMessage_(xListHWnd(0), $1A0, 0, PLSHeight)
  
  
  
  
  
  SelectObject_(xSharedDC, hFontPLLgB)
  GetTextExtentPoint32_(xSharedDC, #DefTxt, #LenDefTxt, xType2)
  PLODHeight = xType2\y
  If PLODHeight < 17
    PLODHeight = 17
    ;Else
    ;PLODHeight = PLODHeight + 4
    EndIf
  PLODIconTopShift = (PLODHeight - 16) >> 1
  SendMessage_(xListHWnd(2), $1A0, 0, PLODHeight)
  If InterfaceMode = #Interface_Mode_Search
    SendMessage_(Interface_Control(#Interface_Control_Search_Results), $1A0, 0, PLODHeight)
    ElseIf InterfaceMode = #Interface_Mode_Radio
    SendMessage_(Interface_Control(#Interface_Control_Radio_List), $1A0, 0, PLODHeight)
    EndIf
  
  SelectObject_(xSharedDC, hFontGFix)
  
  
  
  
; 500 / 340
  If Not hFontTTip = 0
    DeleteObject_(hFontTTip)
    hFontTTip = 0
    EndIf
  
  xType4\cbSize = SizeOf(NONCLIENTMETRICS)
  If SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS, SizeOf(NONCLIENTMETRICS), @xType4, 0)
    hFontTTip = CreateFontIndirect_(@xType4\lfStatusFont)
    EndIf
  
  SelectObject_(xSharedDC, hFontTTip)
  xChar1 = LoadResString(1100)
  CurShownToolTip_SpKeyPre = GetTextOutWidth(xSharedDC, xChar1) + #TTSpaceLeft
  GetTextExtentPoint32_(xSharedDC, #DefTxt, #LenDefTxt, xType2)
  CurShownToolTip_SpHeight = xType2\y
  
  ; 11 long, 4 logfont
  

  
  If InterfaceMode = #Interface_Mode_Search
    MainForm_TrySearch(#False)
    ElseIf InterfaceMode = #Interface_Mode_Radio
    RadioForm_DetectListWidth()
    EndIf




  SelectObject_(xSharedDC, hFontGFix)
  GetTextExtentPoint32_(xSharedDC, #DefTxt, #LenDefTxt, xType2)
  xDefHeight16 = xType2\y
  If xDefHeight16 < 16
    xDefHeight16 = 16
    EndIf
  xDefIconTopShift16 = (xDefHeight16 - 16) >> 1
  PLCurSongDisplaySpacePerc = GetTimeFmtMaxPerc()
  AnimExtraPadding = ScrollComboWidth + 32 + 8 * DPIScaleX
  SendMessage_(xListHWnd(1), $1A0, 0, xDefHeight16)

  xType3\Top = 0
  xType3\Bottom = xDefHeight16
  AdjustWindowRectEx_(xType3, $56000000, 0, $200)
  xDefCtlHeight16 = xType3\Bottom - xType3\Top
  xDefButtonHeight = xDefCtlHeight16 * 1.5
  
  If xDirListModeCur = 0
    SetWindowPos_(xListHWnd(0), 0, 0, xDefCtlHeight16, 300, 200, $215)
    SetWindowPos_(xListHWnd(2), 0, 0, xDefCtlHeight16 + eSPTopY, 300, 200, $215)
    SetWindowPos_(HWndSplitterTH, 0, 0, xDefCtlHeight16, 300, eSPTopY, $215)
    SetWindowPos_(HWndSplitterMoveTH, 0, 0, xDefCtlHeight16, 300, eSPTopY, $215)
    EndIf
  
  
  ;SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_CurSong), 0, 0, 0, 200, xDefCtlHeight16 ,$21)
  xLong1 = xDefCtlHeight16 - 1
  CurSongPosRealHeight = xDefCtlHeight16 - xDefHeight16 + 5 * DPIScaleY
  SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_CurSongPos), 0, 0, xLong1, 200, CurSongPosRealHeight, $215)
  xLong1 = xLong1 + CurSongPosRealHeight
  SpectrumTop = xLong1
  ;SpectrumHeight = 16 * DPIScaleY
  ;If SpectrumHeight < 24
    SpectrumHeight = 24
    ;endif
  SpectrumMinLeft = 244
  SpectrumWidth = 128
  SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Spectrum), 0, SpectrumMinLeft, SpectrumTop, SpectrumWidth, SpectrumHeight, $216)
 
  If xTagBoxHeight = 0
    xTagBoxHeight = xDefCtlHeight16 + xDefHeight16
    EndIf

  
  If vKioskMode
    PanelSizeDef = xLong1
    If MP3GetID3Tag
      SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Tags), 0, 0, xLong1, 200, xDefCtlHeight16 + xDefHeight16, $215)
      If xTagBoxHeight < SpectrumHeight
        xTagBoxHeight = SpectrumHeight
        PanelSizeTags = xLong1 + SpectrumHeight
        Else
        PanelSizeTags = xLong1 + xTagBoxHeight
        SpectrumTop = SpectrumTop + (xTagBoxHeight - SpectrumHeight) / 2
        EndIf
      Else
      PanelSizeTags = xLong1
      EndIf
    Else
    ;debug "Spectrum", SpectrumMinLeft, SpectrumTop, SpectrumWidth, SpectrumHeight
    PlayControlsTop = xLong1 + (SpectrumHeight - 16) / 2
    
    For xLong2 = 0 To 5
      SetWindowPos_(xStaticIconsHWnd(xLong2), 0, 8 + 24 * xLong2, PlayControlsTop, 20, 16, $215)
      Next
    SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Volume), 0, 152, PlayControlsTop, 40, 16, $214)
    SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_RepMode), 0, 196, PlayControlsTop, 20, 16, $214)
    SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_TimerInd), 0, 220, PlayControlsTop, 20, 16, $214)
  
  
    xLong1 = xLong1 + SpectrumHeight
    PanelSizeDef = xLong1
    SetWindowPos_(xStaticIconsHWnd(#xStaticIcons_Tags), 0, 0, xLong1, 200, xDefCtlHeight16 + xDefHeight16, $215)
    PanelSizeTags = xLong1 + xTagBoxHeight
    EndIf

  If Not CurMusic = #ctSSLayer_MusicTypeNone
    If (CurMusic = #ctSSLayer_MusicTypeStream And xSongIsMidi = 3)
      PLCurSongDisplaySpace = PLCurSongDisplaySpacePerc
      Else
      PLCurSongDisplaySpace = GetTimeFmtMax()
      EndIf
    If xSongIsMidi = 3
      GetTimeFmt(#True)
      Else
      GetTimeFmt(#False)
      EndIf
    EndIf
  MainForm_ReGetWidth()
  MainForm_xBuildDirs()
  EndProcedure

Procedure TimerForm_PrePreset()
  If InterfaceMode = #Interface_Mode_Timer
    If Not xTimerEditingHWnd = 0
      EndDialog_(xTimerEditingHWnd, 1)
      EndIf
    EndIf
  EndProcedure

Procedure TimerListForm_TryAccel(wParam.i)
  Define.i xLong1
  
  If wParam = 40 Or wParam = 38
    ShowWindow_(Interface_Control(#Interface_Control_Timer_List), 5)
    SetFocus_(Interface_Control(#Interface_Control_Timer_List))
    ElseIf wParam = 93 And Not TimerListForm_xLocked
    xLong1 = GetAPIPopupMenu(MainHWnd, TimerListForm_xMenu2, Interface_Control(#Interface_Control_Timer_List))
    If Not xLong1 = 0
      TimerListForm_ListProc(Interface_Control(#Interface_Control_Timer_List), $111, 0, xLong1)
      ;TimerListForm_TryAccel = (Not (InterfaceMode = #Interface_Mode_Timer))
      EndIf
    Else
    For xLong1 = 0 To #Interface_Control_Timer_Close
      If Interface_Control_Accel(xLong1) = wParam
        SetFocus_(Interface_Control(#Interface_Control_Timer_List))
        If Not xLong1 = #Interface_Control_Timer_List
          TimerListForm_TrySCommandEx(MainHWnd, xLong1)
          EndIf
        Break
        EndIf
      Next
    EndIf
  EndProcedure

Procedure RadioForm_ShowRadioEditor(*DialogID)
  ;xRadioEditing = #True
  DialogTimer(#True)
  DialogBoxParam_(hInstance, *DialogID, MainHWnd, @RadioForm_RadioEditorProc(), 0)
  DialogTimer(#False)
  xRadioEditingHWnd = 0
  EndProcedure




IncludeFile "Calaym_PlaylistFormats.pb"

;PrivateDimLong(Function LoadPList(FileName.s, InitRun As Boolean, AddOnly As Boolean, InitialDontApplySettings As Boolean) As Boolean
Procedure.i LoadPList(Filename.s, AddOnly.i, InitialDontApplySettings.i) ; , IntroResume As Boolean) As Boolean
  Define.i xResult
  Define.s xChar1
  Define.s xChar2
  Define.s xChar3
  Define.i xLong1
  Define.i xLong2
  Define.i xLong3
  Define.i CurrentDirDepth
  Define.i xLong6
  Define.i llResumeMode
  Define.i llResumePos
  Define.i llResumeTime
  Define.s llResumeURL
  Define.s llResumeURLCP
  Define.s llResumeURLHP
  Define.i llResumeNextIndex
  Define.s llResumeNextFile
  Define.i llResumeCurrentIndex
  Define.s llResumeCurrentFile
  Define.i OrgPLCount
  Define.i HasMissingSongs
  Define.i HasMissingDepth
  #NoMissingDepth = $FFFFFF
  Define.i hFile
  Define.i xIsUnicodeExt
  Define.i FormatHandler
  
  If (PLCount < PLCountMaxX Or Not AddOnly) And Not (Filename = "" Or xAutoDoing) ; Or AutoRefreshVisible)
    SetAutoDoing(#True)
    xTimerIsEnabled = #False
    AbortReading = #False
    xPStateIconRefreshing = #True
    MainForm_UpdateMainIcon()
    MainForm_LockMe(#True)
    OrgPLCount = PLCount
    HasMissingDepth = #NoMissingDepth
    
    If Left(Filename, 1) = Chr(34) And Right(Filename, 1) = Chr(34) And Not Len(Filename) = 1
      Filename = Mid(Filename, 2, Len(Filename) - 2)
      EndIf
    
    RadioForm_PrePreset()
; playlistformatsimport
    Select GetExtensionPart(Filename)
      Case "m3u8"
        hFile = TxtFileReader_FromFile(Filename, #CP_UTF8)
        xIsUnicodeExt = #True
      Case "m3u"
        hFile = TxtFileReader_FromFile(Filename)
        ;xIsUnicodeExt = #False
      Case "pls"
        hFile = TxtFileReader_FromFile(Filename, #CP_ACP)
        ;xIsUnicodeExt = #False
        FormatHandler = 1
      Case "aap"
        hFile = TxtFileReader_FromFile(Filename, #CP_ACP)
        ;xIsUnicodeExt = #False
        FormatHandler = 2
      Case "wpl"
        CompilerIf #WPL_AnsiTest
          hFile = TxtFileReader_FromFile(Filename, #CP_ACP)
          CompilerElse
          hFile = TxtFileReader_FromFile(Filename, #CP_UTF8)
          CompilerEndIf
        ;xIsUnicodeExt = #False
        FormatHandler = 3
;        Else
;        hFile = TxtFileReader_FromFile(Filename)
      Case "xspf"
        hFile = TxtFileReader_FromFile(Filename, #CP_ACP)
        ;xIsUnicodeExt = #False
        FormatHandler = 4
      Case "aimppl"
        hFile = TxtFileReader_FromFile(Filename, #CP_WINUNICODE)
        ;xIsUnicodeExt = #False
        FormatHandler = 5
      Case "plc"
        hFile = TxtFileReader_FromFile(Filename, #CP_WINUNICODE)
        ;xIsUnicodeExt = #False
        FormatHandler = 6
      EndSelect
    If hFile
      CompilerIf #UseFileLogging
        MainForm_ctConsoleA_AddLog("Loading playlist (" + Filename + ")")
        CompilerEndIf
    
      If TxtFileReader_NextLine(hFile)
        xChar1 = TxtFileReader_GetLineString(hFile)
        If Not AddOnly
          xAutoDirCount = 0
          If Not PlNextSong = ""
            SetNextSong(#False)
            EndIf
          PLCurItem = 0
          PLCount = 0
          OrgPLCount = 0
          xRadioCount = 0
          RadioForm_PrePreset()
          ClearPLEx()
          EndIf
        Select FormatHandler
          Case 1
            ; pls is utf8 without bom, so extra critical
            PLReader_Open_PlsAap(hFile, Filename, xChar1, "file")
          Case 2
            PLReader_Open_PlsAap(hFile, Filename, xChar1, "entry")
          Case 3
            PLReader_Open_Wpl(hFile, Filename, xChar1)
          Case 4
            PLReader_Open_Xspf(hFile, Filename, xChar1)
          Case 5
            PLReader_Open_AIMP(hFile, Filename, xChar1, "#track:1|")
          Case 6
            PLReader_Open_AIMP(hFile, Filename, xChar1, "1|")
          EndSelect
        If FormatHandler
          xCurPlistFilenameSuggestNew = #True
          xResult = #True
          Else
          If xChar1 = #m3uIString
            CompilerIf #UseFileLogging
              MainForm_ctConsoleA_AddLog("  (Calaym playlist)")
              CompilerEndIf
            
            
            While TxtFileReader_NextLine(hFile)
              xChar1 = TxtFileReader_GetLineString(hFile)
              If Left(xChar1, 1) = "#"
                xLong1 = FindString(xChar1, "=")
                If Not xLong1 = 0
                  xChar2 = Mid(xChar1, xLong1 + 1)
                  Select UCase(Mid(xChar1, 2, xLong1 - 2))
                    Case "DIR"
                      If PLCount = PLCountMaxX
                        Break
                        Else
                        CompilerIf #BoldDirs = 98
                          PLI(PLCount)\Filename = ""
                          CompilerElse
                          PLIFile(PLCount) = ""
                          CompilerEndIf
                        xLong2 = FindString(xChar2, ",")
  ;debug "Komma", xLong2, xChar2
                        If xLong2 = 0
                          CurrentDirDepth = 0 ; Val(xChar2)
                          xChar2 = LoadResString(27)
                          MessageBox_(MainHWnd, @"Error 200601a - please report", @"Warning", #MB_ICONEXCLAMATION)
                          Else
                          xLong3 = Val(Left(xChar2, xLong2 - 1))
  ;debug "Depth", xLong3, CurrentDirDepth
                          If xLong3 > CurrentDirDepth
                            CompilerIf #UseFileLogging
                              MainForm_ctConsoleA_AddLog("    DropInvalidDepthIncrement " + xChar2)
                              CompilerEndIf
                            Goto IgnoreThisDir
                            Else
                            CurrentDirDepth = xLong3
                            xChar2 = Mid(xChar2, xLong2 + 1)
                            If RemoveMissingOnPLLoad
                              If CurrentDirDepth > HasMissingDepth
                                CompilerIf #UseFileLogging
                                  MainForm_ctConsoleA_AddLog("    DropMissing SubDir " + xChar2)
                                  CompilerEndIf
                                Goto IgnoreThisDir
                                EndIf
    ;debug xChar2
                              xLong2 = GetFileAttributes(xChar2)
                              If xLong2 = -1 Or (xLong2 & 16) = 0
                                HasMissingDepth = CurrentDirDepth
                                HasMissingSongs = #True
                                CompilerIf #UseFileLogging
                                  MainForm_ctConsoleA_AddLog("    DropMissing FirstDir" + xChar2)
                                  CompilerEndIf
                                Goto IgnoreThisDir
                                Else
                                HasMissingDepth = #NoMissingDepth
                                EndIf
                              EndIf
                            CompilerIf #BoldDirs = 98
                              PLI(PLCount)\Filename = xChar2
                              CompilerElse
                              PLIFile(PLCount) = xChar2
                              CompilerEndIf
                            If Not CurrentDirDepth = 0
                              xChar1 = SimpleFile(xChar2)
                              If Not xChar1 = ""
                                xChar2 = xChar1
                                EndIf
                              EndIf
                            EndIf
                          EndIf
                        If xChar2 = ""
                          xChar2 = LoadResString(27)
                          MessageBox_(MainHWnd, @"Error 200601a - please report", @"Warning", #MB_ICONEXCLAMATION)
                          EndIf
                        CompilerIf #BoldDirs = 98
                          PLI(PLCount)\Caption = xChar2
                          PLI(PLCount)\DirDepthFlags = CurrentDirDepth | #PLI_IsDir
                          CompilerElse
                          PLICap(PLCount) = xChar2
                          PLIDF(PLCount) = CurrentDirDepth | #PLI_IsDir
                          CompilerEndIf
                        CurrentDirDepth = CurrentDirDepth + 1 ;CurrentDirDepth * 2 + 4
                        PLCount = PLCount + 1
                        If PLCount = PLCountMax
                          Break
                          EndIf
IgnoreThisDir:
                        EndIf
                    Case "AUTODIR"
                      If Not (xAutoDirCount = #xAutoDirCountMax Or xNoAutoRefresh)
                        xChar1 = LCase(Trim(xChar2))
                        xChar2 = xChar1 + "\"
                        xLong3 = Len(xChar2)
                        If (Mid(xChar2, 2, 1) = ":" Or Left(xChar2, 2) = "\\")
                          For xLong1 = xAutoDirCount - 1 To 0 Step -1
                            If Left(xChar1, Len(xAutoDir(xLong1)) + 1) = xAutoDir(xLong1) + "\"
                              xChar1 = ""
                              Break
                              EndIf
                            If xAutoDir(xLong1) = xChar1
                              xChar1 = ""
                              Break
                              EndIf
                            If Left(xAutoDir(xLong1), xLong3) = xChar2
                              For xLong2 = xLong1 To xAutoDirCount - 2
                                xAutoDir(xLong2) = xAutoDir(xLong2 + 1)
                                Next
                              xAutoDirCount = xAutoDirCount - 1
                              EndIf
                            Next
                          If Not xChar1 = ""
                            xLong3 = xAutoDirCount
                            For xLong1 = 0 To xAutoDirCount - 1
                              If xChar1 < xAutoDir(xLong1)
                                xLong3 = xLong1
                                Break
                                EndIf
                              Next
                            For xLong1 = xAutoDirCount To xLong3 + 1 Step -1
                              xAutoDir(xLong1) = xAutoDir(xLong1 - 1)
                              Next
                            xAutoDirCount = xAutoDirCount + 1
                            xAutoDir(xLong3) = xChar1
                            EndIf
                          EndIf
                        EndIf
                    Case "AUTOREFRESHTIMER"
                      xLong1 = Val(xChar2)
                      If Not (AddOnly Or Abs(xLong1) < #xAutoRefreshTimeMinAll Or Abs(xLong1) > #xAutoRefreshTimeMaxAll)
                        xAutoRefreshTimer(0) = Val(xChar2)
                        EndIf
                    Case "AUTOREFRESHTIMERMONITOR"
                      xLong1 = Val(xChar2)
                      If Not (AddOnly Or Abs(xLong1) < #xAutoRefreshTimeMin Or Abs(xLong1) > #xAutoRefreshTimeMax)
                        xAutoRefreshTimer(1) = Val(xChar2)
                        EndIf
                    Case "CURRENTSONG"
                      If Not AddOnly
                        xLong1 = FindString(xChar2 + ",", ",")
                        llResumeCurrentFile = Mid(xChar2, xLong1 + 1)
                        llResumeCurrentIndex = Val(Left(xChar2, xLong1 - 1))
                        If Not xLong1 = 0
                          PLCurItem = xLong1 - 1
                          EndIf
                        EndIf
                    Case "CURRENTSONGPOS"
                      If Not AddOnly
                        xLong1 = FindString(xChar2 + ",", ",")
                        If Not xLong1 = 0
                          llResumeMode = Val(Left(xChar2, xLong1 - 1)) + 1
                          xChar2 = Mid(xChar2, xLong1 + 1)
                          xLong1 = FindString(xChar2 + ",", ",")
                          If xLong1 = 0
                            llResumePos = Val(xChar2)
                            Else
                            llResumePos = Val(Left(xChar2, xLong1 - 1))
                            llResumeTime = Val(Mid(xChar2, xLong1 + 1))
                            EndIf
                          If (llResumePos < 0 Or llResumeTime < 0) Or Not (llResumeMode = 1 Or llResumeMode = 2)
                            llResumeMode = 0
                            EndIf
                          EndIf
                        EndIf
                    Case "CURRENTURL"
                      If CanIRadio And Not AddOnly
                        xLong1 = FindString(xChar2 + ",", ",")
                        If Not xLong1 = 0
                          If Val(Left(xChar2, xLong1 - 1)) > 0
                            llResumeMode = 4
                            Else
                            llResumeMode = 3
                            EndIf
                          llResumeURL = RealURL(Mid(xChar2, xLong1 + 1))
                          If Len(llResumeURL) = 0
                            llResumeMode = 0
                            EndIf
                          EndIf
                        EndIf
                    Case "CURRENTURLCAPTION"
                      llResumeURLCP = RealURL(xChar2)
                    Case "CURRENTURLHOMEPAGE"
                      llResumeURLHP = RealURL(xChar2)
                    Case "NEXTSONG"
                      ;If IntroResume
                      If InitialDontApplySettings
                        xLong1 = FindString(xChar2 + ",", ",")
                        llResumeNextFile = Mid(xChar2, xLong1 + 1)
                        llResumeNextIndex = Val(Left(xChar2, xLong1 - 1))
                        If Not xLong1 = 0
                          PLNext = xLong1 - 1
                          EndIf
                        EndIf
                    Case "REMOVEMISSINGSONGS"
                      If UsePLSettings And Not (AddOnly Or InitialDontApplySettings)
                        If Val(xChar2) > 0
                          xRemoveMissingSongs = #True
                          Else
                          xRemoveMissingSongs = #False
                          EndIf
                        CheckApiMenu(320, xRemoveMissingSongs)
                        EndIf
                    Case "REMOVEPLAYEDSONGS"
                      If UsePLSettings And Not (AddOnly Or InitialDontApplySettings)
                        If Val(xChar2) > 0
                          xRemovePlayedSongs = #True
                          Else
                          xRemovePlayedSongs = #False
                          EndIf
                        CheckApiMenu(322, xRemovePlayedSongs)
                        EndIf
                    Case "REMOVESKIPPEDSONGS"
                      If UsePLSettings And Not (AddOnly Or InitialDontApplySettings)
                        If Val(xChar2) > 0
                          xRemoveSkippedSongs = #True
                          Else
                          xRemoveSkippedSongs = #False
                          EndIf
                        CheckApiMenu(321, xRemoveSkippedSongs)
                        EndIf
                    Case "REPEATMODE"
                      xLong1 = Val(xChar2)
                      If UsePLSettings And Not (AddOnly Or InitialDontApplySettings Or xLong1 < 0 Or xLong1 > 2 Or xLong1 = xRep)
                        xRep = xLong1
                        MainForm_ApplyRepMode()
                        EndIf
                    Case "RADIO"
                      If TxtFileReader_NextLine(hFile)
                        xChar1 = TxtFileReader_GetLineString(hFile)
                        If Left(xChar1, 1) = "#"
                          If LCase(Left(xChar1, 15)) = "#radiohomepage="
                            If TxtFileReader_NextLine(hFile)
                              xChar3 = TxtFileReader_GetLineString(hFile)
                              xChar1 = Trim(Mid(xChar1, 16))
                              RadioForm_AddRadioEx(xChar2, xChar3, xChar1, #False)
                              EndIf
                            EndIf
                          Else
                          xChar3 = xChar1
                          xChar1 = ""
                          RadioForm_AddRadioEx(xChar2, xChar3, xChar1, #False)
                          EndIf
                        EndIf
                    EndSelect
                  EndIf
                ElseIf Not Len(xChar1) = 0
                If RemoveMissingOnPLLoad
                  If HasMissingDepth = #NoMissingDepth
                    If Not (AllowedItem(xChar1, #True) = 1)
                      CompilerIf #UseFileLogging
                        MainForm_ctConsoleA_AddLog("    DropMissing File    " + xChar1)
                        CompilerEndIf
                      HasMissingSongs = #True
                      Goto IgnoreThisFile
                      EndIf
                    Else
                    CompilerIf #UseFileLogging
                      MainForm_ctConsoleA_AddLog("    DropMissing SubFile " + xChar1)
                      CompilerEndIf
                    Goto IgnoreThisFile
                    EndIf
                  Else
                  If Not AllowedItemSongFast(xChar1, #True)
                    HasMissingSongs = #True
                    Goto IgnoreThisFile
                    EndIf
                  EndIf
                CompilerIf #BoldDirs = 98
                  PLI(PLCount)\Filename = xChar1
                  PLI(PLCount)\Caption = SimpleFile(xChar1)
                  PLI(PLCount)\DirDepthFlags = CurrentDirDepth
                  CompilerElse
                  PLIFile(PLCount) = xChar1
                  PLICap(PLCount) = SimpleFile(xChar1)
                  PLIDF(PLCount) = CurrentDirDepth
                  CompilerEndIf
                PLCount = PLCount + 1
                If PLCount = PLCountMax
                  Break
                  EndIf
IgnoreThisFile:
                xLong6 = (xLong6 + 1) & $3f
                If xLong6 = 0
                  DoEventsEx_SleepPeriodicalLW(0)
                  If AbortReading
                    Break
                    EndIf
                  EndIf
                EndIf
              Wend
            If HasMissingSongs
              CheckEmptyNodes(#True, -1)
              EndIf
            Else
            PLReader_Open_M3uGeneric(hFile, Filename, xChar1)
            EndIf
CompilerIf #PB_Compiler_Unicode
          If xIsUnicodeExt And Not AddOnly
CompilerElse
          If Not (xIsUnicodeExt Or AddOnly)
CompilerEndIf
            xCurPlistFilename = Filename
            xCurPlistFilenameSuggestNew = #False
            Else
            xCurPlistFilenameSuggestNew = #True
            EndIf
          xResult = #True
          EndIf
        EndIf
      If hFile
CompilerIf #UseFileLogging
    MainForm_ctConsoleA_AddLog("Closing....: " + Str(hFile))
CompilerEndIf
        TxtFileReader_Close(hFile)
        EndIf
CompilerIf #UseFileLogging
      Else
    MainForm_ctConsoleA_AddLog("Error loading playlist (" + Filename + ")")
CompilerEndIf
      EndIf
     

    
    
    
    
    If Not xNoAutoRefreshByUser
      MainForm_EnableApiMenu(411, xAutoDirCount)
      MainForm_EnableApiMenu(412, xAutoDirCount)
      MainForm_EnableApiMenu(413, xAutoDirCount)
      MainForm_EnableApiMenu(414, xAutoDirCount)
      If Not AbortReading
        MainForm_xAutoRefreshNow(#True, #True, #True, #True, #True)
        EndIf
      MainForm_LockMe(#True)
      EndIf
    
    If Not PLCount = OrgPLCount
      InitResearchClear()
      RealPLAdd(OrgPLCount)
      If xAutoDoing
        SetAutoDoing(#False)
        EndIf
;debug xAutoDoing, PlayerIsLocked
      InitResearch(#True)
      EndIf
    
    If InitialDontApplySettings And Not llResumeNextFile = ""
      If Not GetRealIndex(@llResumeNextIndex, llResumeNextFile)
        llResumeNextIndex = 0
        EndIf
      EndIf
    If Len(llResumeCurrentFile) = 0
      Goto NoRes
      ElseIf GetRealIndex(@llResumeCurrentIndex, llResumeCurrentFile)
FoundNoRes:
      PLCurItem = llResumeCurrentIndex
      xMarkSong(PLCurItem, #False, #False)
      xFollowCurSongLast = GetTickTimeMS()
      xFollowCurSongLastDiff = #xFollowCurSongLastDiffDef
      Else
NoRes:
      llResumePos = 0
      llResumeTime = 0
      If Not Len(llResumeNextFile) = 0
        If GetRealIndex(@llResumeNextIndex, llResumeNextFile)
          llResumeCurrentIndex = llResumeNextIndex
          llResumeCurrentFile = llResumeNextFile
          llResumeNextIndex = 0
          llResumeNextFile = ""
          Goto FoundNoRes
          EndIf
        EndIf
      If Len(llResumeURL) = 0
        llResumeMode = 0
        EndIf
      EndIf
      
    If InitialDontApplySettings And llResumeMode
      xPStateIconPlaying = #True
      If xAutoPlayback Or FindString(CommandX, "/PLAY")
        If llResumeMode = 1
          llResumeMode = 2
          ElseIf llResumeMode = 3
          llResumeMode = 4
          EndIf
        EndIf
      ;debug llResumeMode, llResumeURL
      If llResumeMode > 2
        If Not Len(llResumeURLCP) = 0
          llResumeURL = llResumeURL + #CR$ + llResumeURLCP
          If Not Len(llResumeURLHP) = 0
            llResumeURL = llResumeURL + #CR$ + llResumeURLHP
            EndIf
          EndIf
;        debug "ResumeURL:", llResumeURL
        If llResumeMode = 4
          xLong1 = #True
          Else
          xLong1 = #False
          EndIf
        If llResumeMode = 3
          xLong2 = #True
          Else
          xLong2 = #False
          EndIf
        If xPlayItem(#False, xLong1, #False, #True, xLong2, llResumeURL)
          If Not CurMusic = #ctSSLayer_MusicTypeNone
            llResumeMode = llResumeMode - 2
            If (llResumeMode = 1)
              xPStateIconPaused = #True
              Else
              xPStateIconPaused = #False
              EndIf
            MainForm_UpdateMainIcon()
            Goto HackIt
            EndIf
          EndIf
        EndIf
      If llResumeMode = 2
        xLong1 = #True
        Else
        xLong1 = #False
        EndIf
      If llResumeMode = 1
        xLong2 = #True
        Else
        xLong2 = #False
        EndIf
      If Len(llResumeCurrentFile) = 0
        xPStateIconPlaying = #False
        If Not llResumeNextIndex = 0
ReSetNext:
          PLNext = llResumeNextIndex
          PlNextSong = llResumeNextFile
          PlNextSongCap = SimpleFile(PlNextSong)
          SetNextSong(#True)
          EndIf
        ElseIf xPlayItem(#False, xLong1, #False, #True, xLong2, "")
        If Not CurMusic = #ctSSLayer_MusicTypeNone
          If (llResumeMode = 1)
            xPStateIconPaused = #True
            Else
            xPStateIconPaused = #False
            EndIf
          MainForm_UpdateMainIcon()
          If llResumePos < PLCurSongLength
            ctSSLayer_SeekSong(SongPointer(CurrentSongID), llResumePos)
            EndIf
          If xEndSongTimerEventTime > 0
            xEndSongTimerEventTime = (xEndSongTimerEventTime - (llResumeTime & TickTimeMSAndMask()) + TickTimeMSMod()) & TickTimeMSAndMask()
            EndIf
HackIt:
          If llResumeMode = 2
            If (xGenFading And Tear_StepT(CurrentSongID) = 0) And Not xPStateIconPaused
              Tear_Volume(CurrentSongID) = 0
              Tear_StartDropping(CurrentSongID, xSongIsMidi, 0, 0, #LongFadingTotalTimeStrt, 1)
              ElseIf Tear_StepT(CurrentSongID) = 0 And Not xPStateIconPaused
              Tear_Volume(CurrentSongID) = 0
              Tear_StartDropping(CurrentSongID, xSongIsMidi, 0, 0, #LongFadingTotalTimeStrtF, 1)
              Else
              Tear_Volume(CurrentSongID) = 1
              ctSSLayer_SetVolume(SongPointer(CurrentSongID), #SimpleFadingTotalTime)
              EndIf
            EndIf
          If Not llResumeNextIndex = 0
            Goto ReSetNext
            EndIf
          ElseIf Not llResumeNextIndex = 0
          Goto xx7
          Else
          xPStateIconPlaying = #False
          EndIf
        ElseIf Not llResumeNextIndex = 0
xx7:
        PLCurItem = llResumeNextIndex
        If Not xPlayItem(xGenFading, #False, #False, #True, #False, "")
          PLCurItem = llResumeCurrentIndex
          xPStateIconPlaying = #False
          EndIf
        Else
        xPStateIconPlaying = #False
        EndIf
      EndIf
    
    If InterfaceMode = #Interface_Mode_Radio
      RadioForm_ReListRadios(#False)
      EndIf
    
    xTimerIsEnabled = #True
    MainForm_LockMe(#False)
    
    If xAutoDoing
      SetAutoDoing(#False)
      EndIf
    CheckReplay()
    xPStateIconRefreshing = #False
    MainForm_UpdateMainIcon()
    ElseIf xAutoDoing
    SetAutoDoing(#False)
    EndIf
  
  If Not InitialDontApplySettings
    AutoSwitchIRadioCheck(#False)
    EndIf
  
  ProcedureReturn xResult
  EndProcedure

XIncludeFile("Calaym_SetupDialog.pb")
XIncludeFile("Calaym_InfoDialog.pb")
XIncludeFile("Calaym_AutoRefresh.pb")
XIncludeFile("Calaym_TimerEditor.pb")

Commons_Init()
TaskBarProgress_Init(@*TasBarPrg)

Main()
If *TasBarPrg
  TaskBarProgress_Release(*TasBarPrg)
  EndIf
If *xTimerIconBMP
  LocalFree_(*xTimerIconBMP)
  EndIf
If *DynButtonsResXDefBMP
  LocalFree_(*DynButtonsResXDefBMP)
  EndIf
If *DynButtonsResXRepBMP
  LocalFree_(*DynButtonsResXRepBMP)
  EndIf
Define.i xLong1
For xLong1 = 0 To 4
  If *FormatIconBmp(xLong1)
    LocalFree_(*FormatIconBmp(xLong1))
    EndIf
  Next

Commons_Close()
Commons_Done()


; IDE Options = PureBasic 5.21 LTS (Windows - x64)
; CursorPosition = 316
; FirstLine = 309
; Folding = -----------------------------------------------------------------------------------------------------------------------------------------------------
; EnableUnicode
; Executable = Calaym64a001.exe
; CommandLine = /PORTABLE
; CompileSourceDirectory
; AddResource = res\64bit_exe.rc