Jump to content

All my products and services are free. All my costs are met by donations I receive from my users. If you enjoy using any of my products, please donate to support me. Thank you for your support. Tom Speirs

Patreon

GatorCoop

Basic Member
  • Posts

    7
  • Joined

  • Last visited

Posts posted by GatorCoop

  1. I got the create videos button it to work in game manager (even get a voice saying "please be patient this may take a few minutes") however when it records - the backglass and dmd record fine but for the table video i get another backglass vid turned 270. Is there a way to fix this? PBX recorder works fine. I would love to use this function. Any help would be greatly appreciated. I'm using ffmeg not the driver option. 

  2. On 5/2/2016 at 2:53 AM, Carny_Priest said:

    Hi, the latest OBS studio added command line support for multiple profiles, so I ported gtxjoe's version 1.4 to support capturing Future Pinball tables. It has all the features of 1.4 except that it supports only Future Pinball and uses OBS Studio as the capture engline for playfield, backglass, DMD. Ffmpeg is still required to complete the transcode to generate the final output. 

    Latest OBS Studio for Windows (portable zip):

    https://github.com/jp9000/obs-studio/releases/download/0.14.1/OBS-Studio-0.14.1.zip

    The installation contains both 32bit and 64bit executables. The script assumes 64bit and assumes that you will extract directly to your C: drive.

    Unzip the following file into the obs-studio folder, RETAIN THE FOLDER STRUCTURE WHEN YOU COPY

    https://dl.dropboxusercontent.com/u/45430846/config.zip

    Open a command prompt and navigate to obs-studio\bin\64bit

    execute obs64.exe --portable

    Agree to the license. 

    There are pre-existing profiles, scene collections, and sources for playfield, bg, and dmd. Each source captures an entire screen. You may want to confirm that each profile is capturing the correct screen. Click the settings icon for display capture in each profile and see that the preview is displaying the correct screen. You can change the screen using the pulldown menu. The script assumes that full screens are used for playfield and bg. Ffmpeg will automatically crop the DMD video based on your FutureDMD settings. I think that's it.

    The 64bit compiled executable is here:

    https://dl.dropboxusercontent.com/u/45430846/PBXrecorder_x64_1.4FP.exe

    As always, run as admin.

    This can co-exist in the same folder as PBXRecorder for VP. The log will get overwritten but it creates an ini file with a different file name.

    Output will look best and work trouble free with the LAV filters that are linked on the PinballX home page.

    Because of the length of time it takes to load some of the more elaborate tables in my cab, I've increased the wait time from 15 seconds to 60 seconds. It's simply what it takes on my system to load SlamT1lt's Nightmare on Elm Street and Robocop.

    I'm running FP at 3K using NVidea DSR on a GTX 660. Using the same capturing engine, the videos are synced up better than when I was using a mix of OBS and ffmpeg. But my hardware is three years old now and running all of these capture simultaneously causes slowdown, so this may require some beefy hardware, or you might try capturing the different screens in separate sessions.

    I'm assuming if you are capturing three screens that you are using FutureDMD. I'm not aware of another solution.

    Capture settings are read from the registry and FutureDMD.ini. No sense trying to capture anything until you are sure the tables are playing correctly.

    Works with or without BAM. Why would you not use BAM, though?

    Source:

      Hide contents

    ;PBX recorder 1.4FP (May 2, 2016) - Mod by Carny_Priest from original 1.4 by GTXJoe

    LoadTime:= 60         ;How long to allow table to load/start (in sec)


    ;*****Start log file
    FileDelete %A_ScriptDir%\PBXrecorder.log
    FileAppend, %A_MMMM% %A_DD%`,%A_YYYY% %A_Hour%:%A_Min%:%A_Sec%`n, %A_ScriptDir%\PBXrecorder.log
    FileAppend, Version 1.4betaFP`n, %A_ScriptDir%\PBXrecorder.log

    ;*******If table drag and drop use, record only that table *************************
    Loop %0% 
    {
        GivenPath := %A_Index%
        Loop %GivenPath%, 1
        {
            DragAndDropFile = %A_LoopFileLongPath%
        }
        SplitPath, DragAndDropFile, DragAndDropFileName, DragAndDropFileDir, DragAndDropFileExtOnly, DragAndDropFileNameOnly
        If ((InStr(DragAndDropFileExtOnly, "fpt")) = 1)
            DragAndDrop := 1
    ;    Else If ((InStr(DragAndDropFileExtOnly, "vpx")) = 1)
    ;        DragAndDrop := 1
        Else
        {
            Msgbox Error:       %DragAndDropFileName% is not a Future Pinball table
            ExitApp
        }
            
        FileAppend, Drag and Drop used:  %DragAndDropFile%`n, %A_ScriptDir%\PBXrecorder.log
        DragText = ---------------------------  Drag and drop mode  ---------------------------`n%DragAndDropFileName%`n------------------------------------------------------------------------------
        Break
    }

    ;***************Monitor setup details
    SysGet, MonitorCount, MonitorCount
    SysGet, MonitorPrimary, MonitorPrimary
    FileAppend, `nMonitor Count: %MonitorCount%`,  Primary Monitor: %MonitorPrimary%`n, %A_ScriptDir%\PBXrecorder.log
    Loop, %MonitorCount%
    {
        SysGet, MonitorName, MonitorName, %A_Index%
        SysGet, Monitor, Monitor, %A_Index%
        SysGet, MonitorWorkArea, MonitorWorkArea, %A_Index%
        ;MsgBox, Monitor %A_Index%: %MonitorRight%x%MonitorBottom% (%MonitorName%)
        FileAppend, Monitor %A_Index%: %MonitorRight%x%MonitorBottom% (%MonitorName%)`n, %A_ScriptDir%\PBXrecorder.log
    }

    ;************************************************************************************************
    ;************************************************************************************************
    ;Create/Load PinballX recorder settings 
    ;************************************************************************************************
    ;************************************************************************************************
    ;************************************************************************************************
    ;************************************************************************************************
    Version:=5
    NumOfSettings:=12
    LoadTimeX:=LoadTime*10
    PBXRPauseMode:=0
    BetaMode:=0           ;0=Normal mode,   1=Beta mode will store recorded media in a Beta folder
                        
    ;Load PBXrecorder settings if they exist
    IfExist, %A_ScriptDir%\PBXrecorderFP.ini
    {
        ;Load Existing settings from file
        ;*************************
        Loopcount:=0
        Loop, Read, %A_ScriptDir%\PBXrecorderFP.ini
        {
                If (Loopcount = 0)
                    VersionRead:= A_LoopReadLine    
                Else If (Loopcount=1)                
                    PinballXPath := A_LoopReadLine
                Else If (Loopcount=2)
                    OnlyRecordMissingVideos := A_LoopReadLine    
                Else If (Loopcount=3)
                    PFVideoOnly := A_LoopReadLine                
                Else If (Loopcount=4)
                    BGVideoOnly := A_LoopReadLine                
                Else If (Loopcount=5)
                    DMDVideoOnly := A_LoopReadLine                
                Else If (Loopcount=6)
                    PFImageOnly := A_LoopReadLine                
                Else If (Loopcount=7)
                    BGImageOnly := A_LoopReadLine                
                Else If (Loopcount=8)
                    DMDImageOnly := A_LoopReadLine
                Else If (Loopcount=9)
                    RecFormat := A_LoopReadLine
                Else If (Loopcount=10)
                    RecTime := A_LoopReadLine            
                Else If (Loopcount=11)
                    MediaFileNaming := A_LoopReadLine
                    
                Loopcount:=Loopcount + 1
        }

        ;Check Version of ini file
        ;*************************
        If ((Version=VersionRead) and (LoopCount=NumOfSettings))    ;If ini version matches, process, else force user to update settings
        {
            ;Display ini settings
            ;*************************
            If (OnlyRecordMissingVideos = 2)
                TempStr2 := "`nFind and record missing media files only`n(Existing media files are kept)"
            Else If (OnlyRecordMissingVideos = 1)
                TempStr2 := "`nRecord complete media set for new and incomplete tables`n(Incomplete media sets are deleted/re-recorded)"
            Else If (OnlyRecordMissingVideos = 3)
                TempStr2 := "`nRecord complete media set for new tables only`n(If any media is found, the table is skipped. Tables with no media are recorded)"
            Else
                TempStr2 := "`nStart over and record complete media sets for all tables`n(All existing media is replaced)"
            
            If RecFormat = 1
                RecExt=mp4
            Else
                RecExt=f4v
                
            TempStr1 = `nMedia to Record (%RecTime% sec %RecExt% videos):`n
            If (PFVideoOnly=1)
                TempStr1 = %TempStr1%Playfield Videos`n
            If (BGVideoOnly=1)
                TempStr1 = %TempStr1%Backglass Videos`n
            If (DMDVideoOnly=1)
                TempStr1 = %TempStr1%DMD Videos`n
            If (PFImageOnly=1)
                TempStr1 = %TempStr1%Playfield Images`n
            If (BGImageOnly=1)
                TempStr1 = %TempStr1%Backglass Images`n
            If (DMDImageOnly=1)
                TempStr1 = %TempStr1%DMD Images`n
                
            If (MediaFileNaming=0)
                TempStr1 = %TempStr1%`nMedia filename based on Description tags`n
            Else
                TempStr1 = %TempStr1%`nMedia filename based on FP table filename`n
                
            If (DragAndDrop<>1)    ; if drag and drop not used, display settings
            {
                ;Prompt user if change to settings desired
                ;*************************
                SetTimer, CurrSettingsButtonNames, 50 
                Msgbox, 4, Current Recorder Settings, %DragText%`n`nPinballX Path: %PinballXPath%`n%TempStr2%`n%TempStr1%`n`n`nPress ESC to abort script            
                IfMsgBox, NO 
                    Change := 1
            }
        }
        Else
        {
            Msgbox, New version of the video recorder detected.  Please update settings
            Change := 1
        }
        
    }
    Else    ;No PBXRecorderFP.ini found.  Need to Create the ini file
    {
        ;******* PBXR settings needed ******************
        Change := 1
        PinballXPath = C:\PinballX
    }

    ;*****Create Pinballx.net FTP login file if not exist
    IfNotExist, %A_ScriptDir%\FTPLoginInfo.txt
    {
        FileAppend, **** To enabled Wheel Image downloads - Replace USERNAME and PASSWORD with your Pinballx FTP login info (requires subscription)`n, %A_ScriptDir%\FTPLoginInfo.txt
        FileAppend, USERNAME`n, %A_ScriptDir%\FTPLoginInfo.txt
        FileAppend, PASSWORD`n, %A_ScriptDir%\FTPLoginInfo.txt
    }

    ; User needs to update PBX Recorder ini settings
    ;*************************
    If (Change = 1)        
    {
        ;Pinballx folder
        Msgbox, 4,PBXrecorder Settings, PinballX folder: %PinballXPath%`n`n Do you want to change the Pinballx path?       `n
        IfMsgBox Yes    ;display folder selection dialog
        {
            FileSelectFolder, PinballXPath,,0,Select the Pinballx Folder
            PinballXPath := RegExReplace(PinballXPath, "\\$")
        }
        
        ;Pic Record Mode
        Gui, Show, W810 H170, Record Mode
        gui, font, s10, Arial
        Gui, Add, Radio, checked vMRadioGroup1, Find and record missing media files only (Existing media files are kept. No files deleted)
        Gui, Add, Radio, vMRadioGroup4, Record complete media set for new tables only (If any media is found, the table is skipped. Only tables with no media are recorded)
        Gui, Add, Radio, vMRadioGroup2, Record complete media set for new and incomplete tables (Missing media is recorded. Incomplete media sets are deleted/re-recorded)
        Gui, Add, Radio, vMRadioGroup3, Start over and record complete media sets for all tables (All existing media is deleted and re-recorded)
        Gui, Add, Text,, `n
        Gui, Add, Button, Default gMediaMode, Next
        Gui, Show
        WinWaitClose, Record Mode        

        ;Choose what media to record
        Gui, Show, W400 H280, Choose Media to Record
        gui, font, s10, Arial
        Gui, Add, Text,,Videos
        Gui, Add, Checkbox, vPFVid, Playfield Videos
        Gui, Add, Checkbox, vBGVid, Backglass Videos
        Gui, Add, Checkbox, vDMDVid, DMD Videos (Req 3 Monitor setup/FutureDMD)
        Gui, Add, Text,,`nImages
        Gui, Add, Checkbox, vPFImage, Playfield Image
        Gui, Add, Checkbox, vBGImage, Backglass Image
        Gui, Add, Checkbox, vDMDImage, DMD Image (Req 3 Monitor setup/FutureDMD)
        Gui, Add, Text,, `n
        Gui, Add, Button, Default gConfirm, Next
        Gui, Show
        WinWaitClose, Choose Media to Record

        ;Set the video recording time
        Gui, Show, W400 H260, Video Recording Time
        gui, font, s10, Arial
        Gui, Add, Text,,Select duration of video recordings:`n
        Gui, Add, Radio, vRadioGroup1, 5 seconds
        Gui, Add, Radio, vRadioGroup2, 15 seconds
        Gui, Add, Radio, vRadioGroup3, 30 seconds
        Gui, Add, Radio, Checked vRadioGroup4, 60 seconds
        Gui, Add, Radio, vRadioGroup5, 120 seconds
        Gui, Add, Radio, vRadioGroup6, 300 seconds
        Gui, Add, Text,, `n
        Gui, Add, Button, Default gSelect, Next
        Gui, Show
        WinWaitClose, Video Recording Time
        
        ;Recording Format
        Gui, Show, W500 H170, Recording Format
        gui, font, s10, Arial
        Gui, Add, Text,,Record all videos in:`n
        Gui, Add, Radio, checked vRadioGroupRF1, .f4v format 
        Gui, Add, Radio, vRadioGroupRF2, .mp4 format
        Gui, Add, Text,, `n
        Gui, Add, Button, Default gMediaR, Next
        Gui, Show
        WinWaitClose, Recording Format
        
        ;File naming convention
        Gui, Show, W500 H170, Media Naming
        gui, font, s10, Arial
        Gui, Add, Text,,Media filenames should be based on:`n
        Gui, Add, Radio, checked vRadioGroupMF1, Description tag            Example:  Medieval Madness (Williams 1997).%RecExt% 
        Gui, Add, Radio, vRadioGroupMF2, FP table filename        Example:  Medieval Madness ZED.%RecExt%
        Gui, Add, Text,, `n
        Gui, Add, Button, Default gMediaF, Next
        Gui, Show
        WinWaitClose, Media Naming
        
        ;******Save Settings*****
        FileDelete %A_ScriptDir%\PBXrecorderFP.ini
        FileAppend,%Version%`n%PinballXPath%`n%OnlyRecordMissingVideos%`n%PFVideoOnly%`n%BGVideoOnly%`n%DMDVideoOnly%`n%PFImageOnly%`n%BGImageOnly%`n%DMDImageOnly%`n%RecFormat%`n%RecTime%`n%MediaFileNaming%`n, %A_ScriptDir%\PBXrecorderFP.ini

        ;Display ini settings
        If (OnlyRecordMissingVideos = 2)
                TempStr2 := "`nFind and record missing media files only`n(Existing media files are kept)"
            Else If (OnlyRecordMissingVideos = 1)
                TempStr2 := "`nRecord complete media set for new and incomplete tables`n(Incomplete media sets are deleted/re-recorded)"
            Else If (OnlyRecordMissingVideos = 3)
                TempStr2 := "`nRecord complete media set for new tables only`n(If any media is found, the table is skipped. Tables with no media are recorded)"
            Else
                TempStr2 := "`nStart over and record complete media sets for all tables`n(All existing media is replaced)"
                
        If RecordingFormat = 1
            RecExt=mp4
        Else
            RecExt=f4v
                
        TempStr1 = `nMedia to Record (%RecTime% sec %RecExt% videos):`n
        If (PFVideoOnly=1)
            TempStr1 = %TempStr1%Playfield Videos`n
        If (BGVideoOnly=1)
            TempStr1 = %TempStr1%Backglass Videos`n
        If (DMDVideoOnly=1)
            TempStr1 = %TempStr1%DMD Videos`n
        If (PFImageOnly=1)
            TempStr1 = %TempStr1%Playfield Images`n
        If (BGImageOnly=1)
            TempStr1 = %TempStr1%Backglass Images`n
        If (DMDImageOnly=1)
            TempStr1 = %TempStr1%DMD Images`n

        If (MediaFileNaming=0)
            TempStr1 = %TempStr1%`nMedia filename based on Description tags`n
        Else
            TempStr1 = %TempStr1%`nMedia filename based on FP table filename`n

        Msgbox, 0, Current Recorder Settings, PinballX Path: %PinballXPath%`n%TempStr2%`n%TempStr1%`n(Wheel Image download support. See FTPLoginInfo.txt)`n`n`nPress ESC to abort script

    }
    FileAppend,`nPinballx.ini`n%Version%`n%PinballXPath%`n%OnlyRecordMissingVideos%`n%PFVideoOnly%`n%BGVideoOnly%`n%DMDVideoOnly%`n%PFImageOnly%`n%BGImageOnly%`n%DMDImageOnly%`n%RecFormat%`n%RecTime%`n%MediaFileNaming%`n`nIdentify all FP XML files...`n, %A_ScriptDir%\PBXrecorder.log

    ;Set FFMpeg, OBS and MediaOut folder locations
    OBSPath = C:\obs-studio
    FFMpegPath = %A_ScriptDir%\FFMpeg\bin
    MediaOutPath = %PinballXPath%\Media

    ;************************************************************************************************
    ;************************************************************************************************
    ;2. Time to walk find all the FP xml files
    ;************************************************************************************************
    ;************************************************************************************************
    ;************************************************************************************************
    ;Arrays for finding and storing FP xml files and path information
    XMLPathArray := Object()
    XMLFileNameArray := Object()
    WorkingPathArray := Object()
    TablePathArray := Object()
    ExecutableArray := Object()
    ;Array[j] := A_LoopField
    ; Array of xml search strings
    Array := ["[FuturePinball]", "Enabled=", "WorkingPath=", "TablePath=", "Executable=", "[System_",  "Name=", "WorkingPath=", "TablePath=", "Executable=", "Enabled=", "SystemType=", "XXXX END XXXX"]
    ;                1                2           3               4             5             6           7            8            9             10              11          12                13

    FPXMLCount=1
    FPSearchIndex:=1
    FPActiveFlag=0
    FPKeepFlag = 1 ;Assume System is enabled
    FPSystemFlag = 0
    FPFirstSystemDone = 0

    If (DragAndDrop<>1)
        PauseTime:=200
    Else
        PauseTime:=0
        
    ;Open PinballX.ini file and identify FP xml files
    ;=================================================
    Loop, Read, %PinballXPath%\Config\PinballX.ini
    {
        ;****** Find 1st System ******
        If (FPFirstSystemDone=0 and FPActiveFlag=0)        ;Search for 1st System start
        {
            StringGetPos, Position, A_LoopReadLine, [FuturePinball]    
            If Position = 0 
            {
                FPActiveFlag = 1
                TempStr = %PinballXPath%\Databases\Future Pinball
                XMLPathArray[FPXMLCount] := TempStr
                XMLFileNameArray[FPXMLCount] := "Future Pinball"
                TempStr1 := XMLPathArray[FPXMLCount]
                TempStr2 := XMLFileNameArray[FPXMLCount]
                ;Msgbox, XMLPathArray[%FPXMLCount%]=%TempStr1%\%TempStr2%
            }
            else        
            {
                continue    ;Read next line
            }
        }
        else if (FPFirstSystemDone==0 and FPActiveFlag==1)    ;Collect info for 1st system
        {
            StringGetPos, Position, A_LoopReadLine, WorkingPath
            If Position = 0 
            {
                TempStr1 := SubStr(A_LoopReadLine, 13)
                WorkingPathArray[FPXMLCount] := TempStr1
                TempStr2 := WorkingPathArray[FPXMLCount]
                ;Msgbox WorkingPathArray[%FPXMLCount%]=%TempStr2%        
            }
            StringGetPos, Position, A_LoopReadLine, Tablepath
            If Position = 0 
            {
                TempStr1 := SubStr(A_LoopReadLine, 11)
                TablePathArray[FPXMLCount] := TempStr1
                TempStr2 := TablePathArray[FPXMLCount]
                ;Msgbox TablePathArray[%FPXMLCount%]=%TempStr2%        
            }
            StringGetPos, Position, A_LoopReadLine, Executable
            If Position = 0 
            {
                TempStr1 := SubStr(A_LoopReadLine, 12)
                ExecutableArray[FPXMLCount] := TempStr1
                TempStr2 := ExecutableArray[FPXMLCount]
                ;Msgbox ExecutableArray[%FPXMLCount%]=%TempStr2%
            }
            StringGetPos, Position, A_LoopReadLine, Enabled=True
            If Position = 0 
            {
                FPKeepFlag = 1
                ;MsgBox, enabled is true
            }
            StringGetPos, Position, A_LoopReadLine, Enabled=False
            If Position = 0 
            {
                FPKeepFlag = 0
                ;MsgBox, enabled is false
            }
            StringGetPos, Position, A_LoopReadLine, [     ;End of section found
            If Position = 0 
            {
                FPFirstSystemDone=1
                StringGetPos, pos, A_LoopReadLine, [
                if pos = 0
                {
                    If FPKeepFlag = 1    ;Keep System info
                    {
                        TempStr1 := XMLPathArray[FPXMLCount]
                        TempStr2 := XMLFileNameArray[FPXMLCount]
                        TempStr3 := WorkingPathArray[FPXMLCount]
                        TempStr4 := TablePathArray[FPXMLCount]
                        TempStr5 := ExecutableArray[FPXMLCount]
                        ;Msgbox, XMLPathArray[%FPXMLCount%]=%TempStr1%\%TempStr2%`n WorkingPathArray[%FPXMLCount%]=%TempStr3%`n TablePathArray[%FPXMLCount%]=%TempStr4%`n ExecutableArray[%FPXMLCount%]=%TempStr5%
                        FileAppend, FP System #%FPXMLCount%:`n%TempStr1%\%TempStr2%.xml`n%TempStr3%`n%TempStr4%`n%TempStr5%`n`n, %A_ScriptDir%\PBXrecorder.log

                        FPXMLCount++
                    }
                    Else
                    {
                        FileAppend, `nFuture Pinball System is disabled in the XML file`n`n, %A_ScriptDir%\PBXrecorder.log
                        ;Msgbox, System Disabled (%FPSystemFlag% %FPKeepFlag%)
                    }
                    FPActiveFlag = 0
                    FPKeepFlag = 1    ;Assume System is enabled        
                }
                
                ; Need to check this line if it is the start of a new system
                StringGetPos, Position, A_LoopReadLine, [System_
                If Position = 0 
                {
                    FPActiveFlag = 1
                }

            }
        }
        ;****** Find Extra Systems ******
        Else If (FPFirstSystemDone=1 and FPActiveFlag = 0)        ;Search for start extra [System...] sections
        {
            StringGetPos, Position, A_LoopReadLine, [System_
            If Position = 0 
            {
                FPActiveFlag = 1
            }
            else        
            {
                continue    ;Read next line
            }
        }
        else if (FPFirstSystemDone=1 and FPActiveFlag = 1)    ;Collect info for the additional [System... sections
        {
            StringGetPos, Position, A_LoopReadLine, Name
            If Position = 0 
            {
                TempStr1 := SubStr(A_LoopReadLine, 6)
                TempStr = %PinballXPath%\Databases\%TempStr1%
                XMLPathArray[FPXMLCount] := TempStr
                XMLFileNameArray[FPXMLCount] := TempStr1
                ;Msgbox, XMLPathArray[%FPXMLCount%]=%TempStr%\%TempStr1%
            }
            StringGetPos, Position, A_LoopReadLine, WorkingPath
            If Position = 0 
            {
                TempStr1 := SubStr(A_LoopReadLine, 13)
                WorkingPathArray[FPXMLCount] := TempStr1
                TempStr2 := WorkingPathArray[FPXMLCount]
                ;Msgbox %TempStr2%        
            }
            StringGetPos, Position, A_LoopReadLine, Tablepath
            If Position = 0 
            {
                TempStr1 := SubStr(A_LoopReadLine, 11)
                TablePathArray[FPXMLCount] := TempStr1
                TempStr2 := TablePathArray[FPXMLCount]
                ;Msgbox %TempStr2%        
            }
            StringGetPos, Position, A_LoopReadLine, Executable
            If Position = 0 
            {
                TempStr1 := SubStr(A_LoopReadLine, 12)
                ExecutableArray[FPXMLCount] := TempStr1
                TempStr2 := ExecutableArray[FPXMLCount]
                ;Msgbox %TempStr2%
            }
            StringGetPos, Position, A_LoopReadLine, SystemType=2
            If Position = 0 
            {
                FPSystemFlag = 1
                ;MsgBox, System is FP
            }
            StringGetPos, Position, A_LoopReadLine, Enabled=True
            If Position = 0 
            {
                FPKeepFlag = 1
                ;MsgBox, System Enabled
            }
            StringGetPos, Position, A_LoopReadLine, Enabled=False
            If Position = 0 
            {
                FPKeepFlag = 0
                ;MsgBox, System Disabled

            }
            StringGetPos, Position, A_LoopReadLine, [
            If Position = 0 
            {
                If (FPSystemFlag = 1 and FPKeepFlag = 1)       ;Keep System info
                {
                    TempStr1 := XMLPathArray[FPXMLCount]
                    TempStr2 := XMLFileNameArray[FPXMLCount]
                    TempStr3 := WorkingPathArray[FPXMLCount]
                    TempStr4 := TablePathArray[FPXMLCount]
                    TempStr5 := ExecutableArray[FPXMLCount]
                    ;Msgbox, XMLPathArray[%FPXMLCount%]=%TempStr1%\%TempStr2%`n WorkingPathArray[%FPXMLCount%]=%TempStr3%`n TablePathArray[%FPXMLCount%]=%TempStr4%`n ExecutableArray[%FPXMLCount%]=%TempStr5%
                    FileAppend, FP System #%FPXMLCount%:`n%TempStr1%\%TempStr2%.xml`n%TempStr3%`n%TempStr4%`n%TempStr5%`n`n, %A_ScriptDir%\PBXrecorder.log
                
                    FPXMLCount++
                }
                Else
                {
                    TempStr2 := XMLFileNameArray[FPXMLCount]
                    FileAppend, Skipping this system: %TempStr2%.xml`n`n, %A_ScriptDir%\PBXrecorder.log
                    ;Msgbox, System Disabled (%FPSystemFlag% %FPKeepFlag%)
                }                
                FPActiveFlag = 0
                FPKeepFlag = 1    ;Assume System is enabled
                FPSystemFlag = 0
                
                ; Need to check this line if it is the start of a new system
                StringGetPos, Position, A_LoopReadLine, [System_
                If Position = 0 
                {
                    FPActiveFlag = 1
                }
            }
        }
    }

    ;End of file found, process last system found
    If (FPSystemFlag = 1 and FPKeepFlag = 1)       ;Keep System info
    {
        TempStr1 := XMLPathArray[FPXMLCount]
        TempStr2 := XMLFileNameArray[FPXMLCount]
        TempStr3 := WorkingPathArray[FPXMLCount]
        TempStr4 := TablePathArray[FPXMLCount]
        TempStr5 := ExecutableArray[FPXMLCount]
        ;Msgbox, XMLPathArray[%FPXMLCount%]=%TempStr1%\%TempStr2%`n WorkingPathArray[%FPXMLCount%]=%TempStr3%`n TablePathArray[%FPXMLCount%]=%TempStr4%`n ExecutableArray[%FPXMLCount%]=%TempStr5%
        FileAppend, FP System #%FPXMLCount%:`n%TempStr1%\%TempStr2%.xml`n%TempStr3%`n%TempStr4%`n%TempStr5%`n`n, %A_ScriptDir%\PBXrecorder.log

        FPXMLCount++
    }
    Else
    {
        TempStr2 := XMLFileNameArray[FPXMLCount]
        FileAppend, Skipping this system: %TempStr2%.xml`n`n, %A_ScriptDir%\PBXrecorder.log
        ;Msgbox, System Disabled (%FPSystemFlag% %FPKeepFlag%)
    }    
    FPActiveFlag = 0
    FPKeepFlag = 0    
    FPSystemFlag = 0
    FPXMLCount--
    FileAppend, Total number of FP systems found: %FPXMLCount%`n, %A_ScriptDir%\PBXrecorder.log
    If FPXMLCount = 0
    {
        Msgbox No XML files were found.  Check PinballX path.  
    }

    ;************************************************************************************************
    ;************************************************************************************************
    ;3. If table selected via drag drop or right click, Allow user to add table to XML file
    ;************************************************************************************************
    ;************************************************************************************************
    ;************************************************************************************************
    If (DragAndDrop=1)
    {
        Loop, %FPXMLCount%        ;Search if table exists in XML files already
        {
            XMLPath:=XMLPathArray[A_Index]
            XMLFileName:=XMLFileNameArray[A_Index]
            WorkingPath:=WorkingPathArray[A_Index]
            TablePath:=TablePathArray[A_Index]
            Executable:=ExecutableArray[A_Index]
            FileAppend, `nAdding table to %XMLFileName%.xml (%A_Hour%:%A_Min%:%A_Sec%)`n`n, %A_ScriptDir%\PBXrecorder.log
                
            ;Open XML file and walk through every table
            ;==========================
            Loop, Read, %XMLPath%\%XMLFilename%.xml
            {
                IfInString, A_LoopReadLine, game name=
                {
                    TableEnabled := 1
                    StringGetPos, start, A_LoopReadLine, =
                    StringGetPos, end, A_LoopReadLine, >
                    XTable := SubStr(A_LoopReadLine, start+3, end-start-3)
                    
                    ;-----------------------------------------------------
                    ;Convert special chars in Table Name so they are used correctly
                    ;-----------------------------------------------------        
                    ;Special handling for & in the Table Name.  Change &amp; to & 
                    IfInString, XTable, &amp;
                    {
                        StringGetPos, start, XTable, &amp;
                        TestTable := SubStr(XTable, 1, start)
                        TestTable2 := SubStr(XTable, start+6)
                        XTable = %TestTable%&%TestTable2%
                    }
                    ;Special handling for italian ' in the Table Name.  Change ’ to ' 
                    IfInString, XTable, ’
                    {
                        StringGetPos, start, XTable, ’
                        TestTable := SubStr(XTable, 1, start)
                        TestTable2 := SubStr(XTable, start+4)
                        XTable = %TestTable%'%TestTable2%
                    }    
                    ;Special handling for ™ in the Table Name.  Change &#8482; to ™ 
                    IfInString, XTable, &#8482;
                    {
                        StringGetPos, start, XTable, &#8482;
                        TestTable := SubStr(XTable, 1, start)
                        TestTable2 := SubStr(XTable, start+8)
                        XTable = %TestTable%™%TestTable2%
                    }
                    
                    If inStr(XTable, DragAndDropFileNameOnly)
                    {
                        XMLTableFound := 1    ;Table found in XML files, go ahead and record media
                        break
                    }
                } ;End of Else IfInString, A_LoopReadLine, /game                
            } ;End of Loop, Read, %XMLPath%\%XMLFilename%.xml
            
            If (XMLTableFound=1) ;Table was found in XML files, go ahead and record media
            {
                break ;exit loop to record media
            }    
        } ;End of Loop, %FPXMLCount%

        If (XMLTableFound<>1)    ; XML table not found, so display XML dialog to add table to XML file
        {
            IPDBArray := Object()
            IPDBNameArray := Object()
            IPDBMfrArray := Object()
            IPDBYearArray := Object()
            IPDBTypeArray := Object()
            IPDBStart:=0
            XMLAllStart:=0
            XMLMatchFound:=0
            
            Loop, %FPXMLCount%    ;Create XML system list for the dialog
            {    
                theXMLString2:=XMLPathArray[A_Index]
                SplitPath, theXMLString2,,,, theXMLString
                            
                If (XMLAllStart = 0) ;Creating XML system list
                {
                    XMLAllFPSysString=%theXMLString%|
                    XMLAllStart := 1
                }
                Else
                {
                    XMLAllFPSysString = %XMLAllFPSysString%%theXMLString%|
                }
                
                ;Check if table path matches the current FP system path, if so mark xml system as default by adding extra |
                If (XMLMatchFound=0)
                {
                    xmltpath:=TablePathArray[A_Index]
                    If (xmltpath = DragAndDropFileDir)
                    {
                        XMLMatchFound:=1
                        XMLAllFPSysString = %XMLAllFPSysString%|
                        
                        ;also store executable for launch button
                        LaunchExecutable:=ExecutableArray[A_Index]

                        ;msgbox match%xmltpath% : %DragAndDropFileDir%
                    }
                }
            }

            IfNotExist, %A_ScriptDir%\ipdb list.txt
                Msgbox, Please re-download PBX Recorder - ipdb list.txt file is missing
                    
            Loop, Read, %A_ScriptDir%\ipdb list.txt         ; Create the ipdb pinball table list for the dialog
            {
                StringSplit, TempWordArray, A_LoopReadLine,|, 
                IPDBNameArray.Insert(TempWordArray1) ; Append this line to the array.
                IPDBMfrArray.Insert(TempWordArray4) ; Append this line to the array.
                IPDBYearArray.Insert(TempWordArray7) ; Append this line to the array.
                IPDBtypeArray.Insert(TempWordArray10) ; Append this line to the array.
                
                tempIPDB = %TempWordArray1% (%TempWordArray4% %TempWordArray7%)
                IPDBArray.Insert(tempIPDB) ; Append this line to the array.
                
                If (IPDBStart = 0)
                {
                    allIPDBString = %tempIPDB%
                    IPDBStart := 1
                }
                Else
                    allIPDBString = %allIPDBString%|%tempIPDB%
            }

            ; File drag and drop - store filename
            Loop %0% 
            {
                GivenPath := %A_Index%
                Loop %GivenPath%, 1
                    DragAndDropFile = %A_LoopFileLongPath%
                DragAndDrop := 1
                Break
            }
            SplitPath, DragAndDropFile,,,, DragAndDropFileNameOnly

            ;****** Display the XML Table entry dialog bpx ******
            Gui, Font, S11 CDefault, Verdana
            Gui, Add, Text, x42 y22 w90 h20 +right , XML List
            Gui, Add, Text, x42 y52 w90 h20 +right, Game
            Gui, Add, Text, x42 y80 w90 h20 +right, Description

            Gui, Add, DropDownList, x142 y20 w280 h25 r10 altSubmit vXMLFPSystem, %XMLAllFPSysString%  
            Gui, Add, Button, x442 y18 w100 h29 gXMLLaunch , Launch
            Gui, Add, Edit, x142 y50 w400 h25 vXMLTableFileName , %DragAndDropFileNameOnly%

            Gui, Add, Edit, x142 y80 w400 h20 vXMLDescText, 
            Gui, Add, DropDownList, x146 y102 w396 h80 r10 sort altSubmit vXMLDescSelected gGetXMLDescSelected, %allIPDBString%
    ;        IfExist, %DragAndDropFileDir%\%DragAndDropFileNameOnly%.directB2S
    ;            Gui, Add, Button, x22 y120 w70 h60 vXDB2S gXMLDB2S, DB2S Found
    ;        Else IfExist, %DragAndDropFileDir%\%DragAndDropFileNameOnly%.exe
    ;            Gui, Add, Button, x22 y120 w70 h60 vXDB2S gXMLDB2S, B2S.exe Found
    ;        Else
    ;            Gui, Add, Button, x22 y120 w70 h60 vXDB2S gXMLDB2S, DB2S Rename

            Gui, Add, Text, x142 y130 w220 h20 +center , Manufacturer
            Gui, Add, Text, x372 y130 w80 h20 +center , Year
            Gui, Add, Text, x462 y130 w80 h20 +center , Type

            Gui, Add, Edit, x142 y150 w220 h25 vXMLMfr, 
            Gui, Add, Edit, x372 y150 w80 h25 vXMLYear, 
            Gui, Add, Edit, x462 y150 w80 h25 vXMLType, 

            Gui, Add, CheckBox, x142 y180 w120 h30 Checked vXMLEnabled, Table Enabled
            Gui, Add, CheckBox, x302 y180 w100 h30 Checked vXMLHideDMD, Hide DMD
            Gui, Add, CheckBox, x412 y180 w150 h30 Checked vXMLHideBG, Hide Backglass

            Gui, Add, DropDownList, x142 y215 w120 h25 r10 +center altSubmit vXMLAltExe, No Exe Tag||AlternateExe|     Exe
            Gui, Add, Edit, x262 y216 w170 h25 vXMLAltExeName, 
            Gui, Add, DropDownList, x442 y215 w100 h25 r10 +center altSubmit vXMLRating, No Rating||1 out of 5|2 out of 5|3 out of 5|4 out of 5|5 out of 5
            
            Gui, Add, Button, x22 y280 w140 h30 gXMLCancel, Cancel
            Gui, Add, Button, x212 y280 w140 h30 gXMLSaveExit, Save && Exit
            Gui, Add, Button, x402 y280 w140 h30 gXMLSave, Save && Record

            GuiControl, Focus, XMLDescSelected
            Gui, Show, x127 y87 h327 w574,Add Table to XML - Start typing to perform Description auto-complete
            WinWaitClose, Add Table to XML - Start typing to perform Description auto-complete
            ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx        
        }
        Else
        {
            MsgBox, 4,, Table exists in XML file already.  Begin recording? (press Yes or No)
            IfMsgBox No
                ExitApp
        }
        
            
    }    
        
    ;************************************************************************************************
    ;************************************************************************************************
    ;4. Time to walk through the tables and record videos
    ;************************************************************************************************
    ;************************************************************************************************
    ;************************************************************************************************
    ; Disabling "Application has stopped Working" dialog
    ;(https://www.raymond.cc/blog/disable-program-has-stopped-working-error-dialog-in-windows-server-2008/)
    RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\Windows Error Reporting, DontShowUI, 0x00000001

    Rectime := Rectime + 10        ;Pad record time by 10 seconds
    Loopcount:=0
    Recordcount:=0
    Loop, %FPXMLCount%
    {
        XMLPath:=XMLPathArray[A_Index]
        XMLFileName:=XMLFileNameArray[A_Index]
        WorkingPath:=WorkingPathArray[A_Index]
        TablePath:=TablePathArray[A_Index]
        Executable:=ExecutableArray[A_Index]
        FileAppend, `nWorking on %XMLFileName%.xml (%A_Hour%:%A_Min%:%A_Sec%)`n`n, %A_ScriptDir%\PBXrecorder.log
        
        ;Read FP Registry and FutureDMD Settings - may need to be even number values or it may not record
        ;=======================
        RegRead, PF_width, HKCU, Software\Future Pinball\GamePlayer, Width
        RegRead, PF_height, HKCU, Software\Future Pinball\GamePlayer, Height
        RegRead, BG_width, HKCU, Software\Future Pinball\GamePlayer, SecondMonitorWidth
        RegRead, BG_height, HKCU, Software\Future Pinball\GamePlayer, SecondMonitorHeight

        IniRead, DMD_width, %WorkingPath%\FutureDMD.ini, default, SizeW
        IniRead, DMD_height, %WorkingPath%\FutureDMD.ini, default, SizeH
        IniRead, DMD_X, %WorkingPath%\FutureDMD.ini, default, PosX
        IniRead, DMD_Y, %WorkingPath%\FutureDMD.ini, default, PosY

        ;Save FP Registry and FutureDMD Settings to PBX recorder log
        FileAppend, FP Registry and FutureDMD Settings`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, %PF_width%`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, %PF_height%`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, %BG_width%`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, %BG_height%`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, %DMD_width%`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, %DMD_height%`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, %DMD_X%`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, %DMD_Y%`n, %A_ScriptDir%\PBXrecorder.log

        ;OBS file check
        IfNotExist, %OBSPath%\bin\64bit\obs64.exe
            {
                FileAppend, `nWARNING:  The file obs64.exe could not be found`n, %A_ScriptDir%\PBXrecorder.log
                FileAppend, WARNING:  The file obs64.exe could not be found`n, %A_ScriptDir%\PBXrecorder.log
                FileAppend, WARNING:  The file obs64.exe could not be found`n`n, %A_ScriptDir%\PBXrecorder.log
            }
        
        ;FFMPEG file check
        IfNotExist, %FFMpegPath%\ffmpeg.exe
        {
            FFMpegPath = %FFMpegPath%\bin
            IfNotExist, %FFMpegPath%\ffmpeg.exe
                FileAppend, `nWARNING:  The file ffmpeg.exe could not be found`n, %A_ScriptDir%\PBXrecorder.log
                FileAppend, WARNING:  The file ffmpeg.exe could not be found`n, %A_ScriptDir%\PBXrecorder.log
                FileAppend, WARNING:  The file ffmpeg.exe could not be found`n`n, %A_ScriptDir%\PBXrecorder.log
        }

        ;Create Media directories if needed
        ;==========================

        MediaSubDir:=XMLFileName
        MediaSubDirOut:=XMLFileName

        If (BetaMode=1)
        {
            MediaSubDirOut = %MediaSubDirOut% Beta
            Msgbox, 0,, Beta Mode. All new media stored in %MediaOutPath%\%MediaSubDirOut%, 20
        }
        
        FileCreateDir, %MediaOutPath%\%MediaSubDirOut%\Backglass Images
        FileCreateDir, %MediaOutPath%\%MediaSubDirOut%\Backglass Videos
        FileCreateDir, %MediaOutPath%\%MediaSubDirOut%\DMD Images
        FileCreateDir, %MediaOutPath%\%MediaSubDirOut%\DMD Videos
        FileCreateDir, %MediaOutPath%\%MediaSubDirOut%\Table Images
        FileCreateDir, %MediaOutPath%\%MediaSubDirOut%\Table Videos
        FileCreateDir, %MediaOutPath%\%MediaSubDirOut%\Wheel Images

        ;Start of new XML file
        if (DragAndDrop<>1)
        {
            Progress, x200 y200 zh0 M h200 w600 FS10, `n%WorkingPath%`n %TablePath%`n %Executable%`n`n`n(Press ESC anytime to abort script)  , `nWorking on %XMLFileName%.xml, System XML #%A_Index% of %FPXMLCount% ... , Arial
            Sleep 2000
        }
        
        ; Clean up
        ;==========================
        FileDelete, %A_ScriptDir%\playfield.mkv
        FileDelete, %A_ScriptDir%\bg.mkv
        FileDelete, %A_ScriptDir%\dmd.mkv
        Run, taskkill /T /IM obs64.exe ,,UseErrorLevel
        WinKill, Error
        Progress, Off

        ;*************** Screensize check - How good are the settings ****************
        ;==========================
        XDMD_X:=DMD_X-PF_width ;Reference to Top Left of Playfield screen
        SysGet, VirtualScreenWidth, 78
        TotalScreenWidth := DMD_X + DMD_width
        DMD_oldwidth := DMD_Width
        PFBGWidth := PF_width+BG_width
        DMDScreenWidth := VirtualScreenWidth - PFBGWidth
        DMDScreenHeight := MonitorBottom
        DMDXCrop := DMD_X - PFBGWidth
        
        ;Convert all width and height to even values for best recording success
        PF_width    := (floor(PF_width/2))*2          
        PF_height    := (floor(PF_height/2))*2          
        BG_width    := (floor(BG_width/2))*2           
        BG_height    := (floor(BG_height/2))*2          
        DMD_width    := (floor(DMD_width/2))*2          
        DMD_height    := (floor(DMD_height/2))*2
        
        FileAppend, `nValues used for media capture (height/width forced to even values)`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, VirtualScreenWidth = %VirtualScreenWidth%`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, TotalScreenWidth   = %TotalScreenWidth%  `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, PF_width           = %PF_width%          `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, PF_height          = %PF_height%         `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, BG_width           = %BG_width%          `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, BG_height          = %BG_height%         `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMD_width          = %DMD_width%      `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMD_height         = %DMD_height%        `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMD_X_offset       = %XDMD_X%            `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMD_Y_offset       = %DMD_Y%             `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, -----------------------------------------`n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMD_tot_offset     = %DMD_X%             `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMD_orig_width     = %DMD_oldwidth%         `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMDScreenWidth     = %DMDScreenWidth%    `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMDScreenHeight    = %DMDScreenHeight%   `n, %A_ScriptDir%\PBXrecorder.log
        FileAppend, DMDScreenX         = %DMDXCrop%          `n, %A_ScriptDir%\PBXrecorder.log

        ;PF width check
        If ((PF_width > VirtualScreenWidth) and (PFVideoOnly = 1 or PFImageOnly = 1))
        {
            Msgbox, 0, FP Settings: Playfield size check, Warning: FP Playfield(%PF_width%) width exceeds the actual size of the windows desktop(%VirtualScreenWidth%).  Review FP settings`n`nPlayfield recording may not work, 60 
            FileAppend, WARNING: FP Settings Playfield width exceeds the actual size of windows desktop.  Review FP settings`n, %A_ScriptDir%\PBXrecorder.log
        }
        
        ;PF and BG width check
        If ((PFBGWidth > VirtualScreenWidth) and (BGVideoOnly = 1 or BGImageOnly = 1))
        {
            Msgbox, 0, FP Settings: Backglass size check, Warning: FP Playfield(%PF_width%) plus Backglass(%BG_width%) width exceeds the actual size of windows desktop (%VirtualScreenWidth%).  Review FP settings`n`nBackglass recording may not work, 60 
            FileAppend, WARNING: FP Settings Playfield(%PF_width%) plus Backglass(%BG_width%) width exceeds the actual size of windows desktop (%VirtualScreenWidth%).  Review FP settings`n, %A_ScriptDir%\PBXrecorder.log
        }

        ;PF and BG and DMD width check
        If ((TotalScreenWidth > VirtualScreenWidth) and (DMDVideoOnly = 1 or DMDImageOnly = 1))
        {
            DMD_Width := (floor((DMD_oldwidth - (TotalScreenWidth - VirtualScreenWidth))/2))*2
            Msgbox, 0, FutureDMD: DMD size check, Warning: FutureDMD width/offset is not correct`nReducing DMD width from %DMD_oldwidth% to %DMD_width%.  Review FutureDMD.ini settings`n`nDMD recording may not work, 60
            FileAppend, WARNING: DMD window settings incorrect - auto-resizing (%DMD_oldwidth% to %DMD_width%).  Review FutureDMD settings`n, %A_ScriptDir%\PBXrecorder.log
        }
        
        
        ;Write modified settings to OBS config files
        IniWrite, %PF_width%, %OBSPath%\config\obs-studio\basic\profiles\playfield\basic.ini, Video, OutputCX 
        IniWrite, %PF_height%, %OBSPath%\config\obs-studio\basic\profiles\playfield\basic.ini, Video, OutputCY 
        IniWrite, %A_ScriptDir%, %OBSPath%\config\obs-studio\basic\profiles\playfield\basic.ini, AdvOut, RecFilePath 

        IniWrite, %BG_width%, %OBSPath%\config\obs-studio\basic\profiles\bg\basic.ini, Video, OutputCX 
        IniWrite, %BG_height%, %OBSPath%\config\obs-studio\basic\profiles\bg\basic.ini, Video, OutputCY 
        IniWrite, %A_ScriptDir%, %OBSPath%\config\obs-studio\basic\profiles\bg\basic.ini, AdvOut, RecFilePath 

        IniWrite, %DMDScreenWidth%, %OBSPath%\config\obs-studio\basic\profiles\dmd\basic.ini, Video, OutputCX 
        IniWrite, %DMDScreenHeight%, %OBSPath%\config\obs-studio\basic\profiles\dmd\basic.ini, Video, OutputCY 
        IniWrite, %A_ScriptDir%, %OBSPath%\config\obs-studio\basic\profiles\dmd\basic.ini, AdvOut, RecFilePath 
        
        ;Open XML file and walk through every table
        ;==========================
        ExecutableBackup:=Executable
        PrintFFMPEGExamples:=1
        Loop, Read, %XMLPath%\%XMLFilename%.xml
        {
            IfInString, A_LoopReadLine, game name=
            {
                TableEnabled := 1
                Executable:=ExecutableBackup
                StringGetPos, start, A_LoopReadLine, =
                StringGetPos, end, A_LoopReadLine, >
                XTable := SubStr(A_LoopReadLine, start+3, end-start-3)
                ;Msgbox, what%XTable%`n%A_LoopReadLine%`n%start%`n%end%
                
                ;-----------------------------------------------------
                ;Convert special chars in Table Name so they are used correctly
                ;-----------------------------------------------------
                ;Special handling for ® in the Table Name.  Change ® to ®
                IfInString, XTable, ®
                {
                    StringGetPos, start, XTable, ®
                    TestTable := SubStr(XTable, 1, start)
                    TestTable2 := SubStr(XTable, start+2)
                    XTable = %TestTable%%TestTable2%
                    ;msgbox %XTable%
                }            
                ;Special handling for & in the Table Name.  Change &amp; to & 
                IfInString, XTable, &amp;
                {
                    StringGetPos, start, XTable, &amp;
                    TestTable := SubStr(XTable, 1, start)
                    TestTable2 := SubStr(XTable, start+6)
                    XTable = %TestTable%&%TestTable2%
                }
                ;Special handling for Italian ® in the Table Name.  Change &#174; to ® 
                IfInString, XTable, &#174;
                {
                    StringGetPos, start, XTable, &amp;
                    TestTable := SubStr(XTable, 1, start)
                    TestTable2 := SubStr(XTable, start+7)
                    XTable = %TestTable%�%TestTable2%
                }
                ;Special handling for italian ' in the Table Name.  Change ’ to ' 
                IfInString, XTable, ’
                {
                    StringGetPos, start, XTable, ’
                    TestTable := SubStr(XTable, 1, start)
                    TestTable2 := SubStr(XTable, start+4)
                    XTable = %TestTable%'%TestTable2%
                }    
                ;Special handling for ™ in the Table Name.  Change &#8482; to ™ 
                IfInString, XTable, &#8482;
                {
                    StringGetPos, start, XTable, &#8482;
                    TestTable := SubStr(XTable, 1, start)
                    TestTable2 := SubStr(XTable, start+8)
                    XTable = %TestTable%™%TestTable2%
                }
                
                ;Identify if fpt
                IfExist, %TablePath%\%Xtable%.fpt
                {
                    Table = %XTable%.fpt
                    TableExists := 1
                }
                ;Else IfExist, %TablePath%\%Xtable%.vpx   
                ;{
                ;    Table = %XTable%.vpx 
                ;    TableExists := 1
                ;}
                Else      ;must be vpx file
                {
                    ;Table = %XTable%.vpx 
                    TableExists := 0
                }
            }
            Else IfInString, A_LoopReadLine, /description
            {                                         
                StringGetPos, start, A_LoopReadLine, <description>
                StringGetPos, end, A_LoopReadLine, </description>
                Description := SubStr(A_LoopReadLine, start+14, end-start-13)
                
                ;----------------------------------------------------
                ;Remove invalid chars from Description name like  : / \ * ? " < > |
                ;----------------------------------------------------
                IfInString, Description, :
                {
                    StringGetPos, start, Description, :
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }
                IfInString, Description, /
                {
                    StringGetPos, start, Description, /
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }
                IfInString, Description, \
                {
                    StringGetPos, start, Description, \
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }
                IfInString, Description, *
                {
                    StringGetPos, start, Description, *
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }            
                IfInString, Description, &#42;
                {
                    StringGetPos, start, Description, &#42;
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+6)
                    Description = %TestTable%%TestTable2%
                }            
                IfInString, Description, ?
                {
                    StringGetPos, start, Description, ?
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }            
                IfInString, Description, "
                {
                    StringGetPos, start, Description, "
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }            
                IfInString, Description, <
                {
                    StringGetPos, start, Description, <
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }            
                IfInString, Description, >
                {
                    StringGetPos, start, Description, >
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }            
                IfInString, Description, |
                {
                    StringGetPos, start, Description, |
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }
                
                ;-----------------------------------------------------
                ;Convert special chars in Description so they are used correctly
                ;-----------------------------------------------------
                ;Special handling for ® in the Description.  Change ® to ®
                IfInString, Description, ®
                {
                    StringGetPos, start, Description, ®
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+2)
                    Description = %TestTable%%TestTable2%
                }            
                ;Special handling for & in the Description.  Change &amp; to & 
                IfInString, Description, &amp;
                {
                    StringGetPos, start, Description, &amp;
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+6)
                    Description = %TestTable%&%TestTable2%
                }
                ;Special handling for &#174; in the Description.  Change &#174; to ®
                IfInString, Description, &#174;
                {
                    StringGetPos, start, Description, &#174;
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+7)
                    Description = %TestTable%�%TestTable2%
                }
                ;Special handling for italian ' in the Description.  Change ’ to ' 
                IfInString, Description, ’
                {
                    StringGetPos, start, Description, ’
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+4)
                    Description = %TestTable%'%TestTable2%
                }
                ;Special handling for ™ in the Description.  Change &#8482; to ™ 
                IfInString, Description, &#8482;
                {
                    StringGetPos, start, Description, &#8482;
                    TestTable := SubStr(Description, 1, start)
                    TestTable2 := SubStr(Description, start+8)
                    Description = %TestTable%™%TestTable2%
                }

                FileAppend, `n%Description%`n, %A_ScriptDir%\PBXrecorder.log                                
                If TableExists = 0
                    FileAppend,  Table file not found: %TablePath%\%XTable%.fpt`n, %A_ScriptDir%\PBXrecorder.log
            }
            Else IfInString, A_LoopReadLine, /alternateExe
            {            
                StringGetPos, start, A_LoopReadLine, <alternateExe>
                StringGetPos, end, A_LoopReadLine, </alternateExe>
                Executable := SubStr(A_LoopReadLine, start+15, end-start-14)
                ;Msgbox, %Executable%
                FileAppend, AlternateExe found in xml: %Executable%`n, %A_ScriptDir%\PBXrecorder.log
            }
            Else IfInString, A_LoopReadLine, /exe
            {            
                StringGetPos, start, A_LoopReadLine, <exe>
                StringGetPos, end, A_LoopReadLine, </exe>
                Executable := SubStr(A_LoopReadLine, start+6, end-start-5)
                ;Msgbox, %Executable%
                FileAppend, Exe found in xml: %Executable%`n, %A_ScriptDir%\PBXrecorder.log
            }
            Else IfInString, A_LoopReadLine, enabled>False
            {            
                ;Msgbox, %A_LoopReadLine%
                FileAppend, Table disabled in xml: %TablePath%\%Table%`n, %A_ScriptDir%\PBXrecorder.log
                TableEnabled := 0
            }
            Else IfInString, A_LoopReadLine, enabled>True
            {            
                ;Msgbox, %A_LoopReadLine% 
                TableEnabled := 1
            }
            Else IfInString, A_LoopReadLine, /game
            {
                If TableEnabled = 1
                {
                    If TableExists = 1
                    {
                        Loopcount:=Loopcount + 1
                        ;Msgbox, recording
                        ;Check if Media Files exist and skip if skip is enabled
                        ;===================================================
                        MediaFoundFlag:=0
                        If (MediaFileNaming=0)
                            SearchString:=Description   
                        Else
                            SearchString:=Xtable 

                        If (PrintFFMPEGExamples=1)
                        {
                            PrintFFMPEGExamples:=0
                            FileAppend, `nEXAMPLE of all ffmpeg.exe commands used`n, %A_ScriptDir%\PBXrecorder.log
    ;                        FileAppend, "%FFMpegPath%\ffmpeg" -y -t 1 -f gdigrab -framerate 1 -offset_x 0 -offset_y 0 -video_size %PF_width%x%PF_Height% -i desktop -vf "rotate=PI:bilinear=0" "%MediaOutPath%\%MediaSubDirOut%\Table Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
    ;                        FileAppend, "%FFMpegPath%\ffmpeg" -y -t 1 -f gdigrab -framerate 1 -offset_x %PF_width% -offset_y 0 -video_size %BG_width%x%BG_Height% -i desktop "%MediaOutPath%\%MediaSubDirOut%\Backglass Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
    ;                        FileAppend, "%FFMpegPath%\ffmpeg" -y -t 1 -f gdigrab -framerate 1 -offset_x %DMD_X% -offset_y %DMD_Y% -video_size %DMD_width%x%DMD_Height% -i desktop "%MediaOutPath%\%MediaSubDirOut%\DMD Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
    ;                        FileAppend, "%FFMpegPath%\ffmpeg" -y -t %RecTime% -rtbufsize 1500M -f gdigrab -framerate 30 -offset_x 0 -offset_y 0 -video_size %PF_width%x%PF_Height% -i desktop -vcodec libx264 -preset ultrafast -qp 0 -threads 8 "%A_ScriptDir%\playfield.mkv"`n, %A_ScriptDir%\PBXrecorder.log
    ;                        FileAppend, "%FFMpegPath%\ffmpeg" -y -t %RecTime% -rtbufsize 1500M -f gdigrab -framerate 30 -offset_x %PF_width% -offset_y 0 -video_size %BG_width%x%BG_Height% -i desktop -vcodec libx264 -preset ultrafast  -qp 0 -threads 8 "%A_ScriptDir%\bg.mkv"`n, %A_ScriptDir%\PBXrecorder.log
    ;                        FileAppend, "%FFMpegPath%\ffmpeg" -y -t %RecTime% -rtbufsize 1500M -f gdigrab -framerate 30 -offset_x %DMD_X% -offset_y %DMD_Y% -video_size %DMD_width%x%DMD_Height% -i desktop -vcodec libx264 -preset ultrafast  -qp 0 -threads 8 "%A_ScriptDir%\dmd.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                            FileAppend, "%FFMpegPath%\ffmpeg" -y -i "%A_ScriptDir%\playfield.mkv" -ss 10 -to 1000 -vf [in]rotate=PI:bilinear=0[middle];[middle]scale=1920:-1[out] -map 0:0 -c:v libx264 -crf 26 "%MediaOutPath%\%MediaSubDirOut%\Table Videos\%SearchString%.%RecExt%"`n, %A_ScriptDir%\PBXrecorder.log
                            FileAppend, "%FFMpegPath%\ffmpeg" -y -i "%A_ScriptDir%\bg.mkv" -ss 10 -to 1000 -map 0:0 -c:v libx264 -crf 26 "%MediaOutPath%\%MediaSubDirOut%\Backglass Videos\%SearchString%.%RecExt%"`n, %A_ScriptDir%\PBXrecorder.log
                            FileAppend, "%FFMpegPath%\ffmpeg" -y -i "%A_ScriptDir%\dmd.mkv" -ss 10 -to 1000 -vf "crop=w=%DMD_width%:h=%DMD_height%:x=%DMDXCrop%:y=%DMD_Y%" -map 0:0 -c:v libx264 -crf 26 "%MediaOutPath%\%MediaSubDirOut%\DMD Videos\%SearchString%.%RecExt%"`n`n, %A_ScriptDir%\PBXrecorder.log                        
                        }
                                            
                        If ((OnlyRecordMissingVideos = 1) or (OnlyRecordMissingVideos = 2) or (OnlyRecordMissingVideos = 3))
                        {
                            ;Perform media check for missing files
                            MediaFoundFlag:=1
                            MediaAtLeastOneFound:=0
                            
                            If (PFVideoOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\Table Videos\%SearchString%.*
                                {
                                    MediaFoundFlag:=0
                                    FileAppend, MISSING: Table Video`n, %A_ScriptDir%\PBXrecorder.log                        
                                }
                                Else
                                {
                                    MediaAtLeastOneFound:=1
                                }
                            }
                            If (BGVideoOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\BackGlass Videos\%SearchString%.*
                                {
                                    MediaFoundFlag:=0
                                    FileAppend, MISSING: BackGlass Video`n, %A_ScriptDir%\PBXrecorder.log                        
                                }
                                Else
                                {
                                    MediaAtLeastOneFound:=1
                                }
                            }
                            If (DMDVideoOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\DMD Videos\%SearchString%.*
                                {
                                    FileAppend, MISSING: DMD Video`n, %A_ScriptDir%\PBXrecorder.log                        
                                    If DMD_width > 0 
                                    {
                                        MediaFoundFlag:=0
                                    }
                                }
                                Else
                                {
                                    MediaAtLeastOneFound:=1
                                }
                            }
                            If (PFImageOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\Table Images\%SearchString%.*
                                {
                                    MediaFoundFlag:=0
                                    FileAppend, MISSING: Table Image`n, %A_ScriptDir%\PBXrecorder.log                        
                                }
                                Else
                                {
                                    MediaAtLeastOneFound:=1
                                }
                            }
                            If (BGImageOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\BackGlass Images\%SearchString%.*
                                {
                                    MediaFoundFlag:=0
                                    FileAppend, MISSING: BackGlass Image`n, %A_ScriptDir%\PBXrecorder.log                        
                                }
                                Else
                                {
                                    MediaAtLeastOneFound:=1
                                }
                            }
                            If (DMDImageOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\DMD Images\%SearchString%.*
                                {
                                    FileAppend, MISSING: DMD Image`n, %A_ScriptDir%\PBXrecorder.log                        
                                    If DMD_width > 0                 
                                    {
                                        MediaFoundFlag:=0
                                    }
                                }
                                Else
                                {
                                    MediaAtLeastOneFound:=1
                                }
                            }
                            
                        } ;end of If ((OnlyRecordMissingVideos = 1) or (OnlyRecordMissingVideos = 2) or (OnlyRecordMissingVideos = 3))
                        Else
                        {
                            FileAppend, PBXrecorder set to record complete media set`n, %A_ScriptDir%\PBXrecorder.log                        
                        }
                    
                        ;===========================================================================
                        ; Extra FP file checks - Wheel images (FTP download supported)
                        ;===========================================================================
                        ;Print out message to log file if DirectB2s file is missing
                        ;IfNotExist, %TablePath%\%XTable%.directb2s
                        ;{
                        ;    IfNotExist, %TablePath%\%XTable%.exe
                        ;    {
                        ;        FileAppend, FYI: No DirectB2S/B2S.exe File.  %TablePath%\%XTable%.directb2s`n, %A_ScriptDir%\PBXrecorder.log                        
                        ;    }
                        ;    Else
                        ;    {
                        ;        FileAppend, FYI: No DirectB2S but B2S was found.  %TablePath%\%XTable%.directb2s`n, %A_ScriptDir%\PBXrecorder.log                        
                        ;    }
                        ;}
                        ;Print out message to log file if Wheel image is missing - Perform FTP
                        IfNotExist, %MediaOutPath%\%MediaSubDir%\Wheel Images\%SearchString%.png
                        {
                            ;=============================================================
                            ; Download Wheel from PinballX FTP if user has filled in FTP login info
                            ;=============================================================
                            IfExist, %A_ScriptDir%\FTPLoginInfo.txt                            
                            {                        
                                FileReadLine, tempStr, %A_ScriptDir%\FTPLoginInfo.txt, 2
                                IfNotInString, tempStr, USERNAME
                                {
                                    Progress, x200 y200 zh0 M h200 w600 FS10, `n`Wheel Image missing... Check PinballX FTP site`n`n(Press ESC anytime to abort script)  ,`n`n%Description%, Attempting PinballX FTP download , Arial
                                    ;Strip out the {...} from the description if found
                                    StringSplit, SearchStringArray, Description, {} ;drop the 2nd part
                                    SearchStringArray1:=Trim(SearchStringArray1)
                                    SearchStringArray3:=Trim(SearchStringArray3)
                                    If (StrLen(SearchStringArray3)>0)
                                        SearchStringArray1=%SearchStringArray1% %SearchStringArray3%

                                    FileToGet = %SearchStringArray1%.png
                                    FileDelete %A_ScriptDir%\FTPtemp.bat
                                    FileAppend, open online.gameex.com`n, %A_ScriptDir%\FTPtemp.bat
                                    FileReadLine, tempStr, %A_ScriptDir%\FTPLoginInfo.txt, 2
                                    FileAppend, %tempStr%`n, %A_ScriptDir%\FTPtemp.bat
                                    FileReadLine, tempStr, %A_ScriptDir%\FTPLoginInfo.txt, 3
                                    FileAppend, %tempStr%`n, %A_ScriptDir%\FTPtemp.bat
                                    FileAppend,
                                    (
                                    binary
                                    hash
                                    cd "/-PinballX-/Media/Future Pinball/Wheel Images"
                                    get "%FileToGet%"
                                    bye
                                    ), %A_ScriptDir%\FTPtemp.bat
                                    RunWait %comspec% /c ftp.exe -s:"%A_ScriptDir%\FTPtemp.bat"
                                    FileDelete %A_ScriptDir%\FTPtemp.bat
                                    FileMove %A_ScriptDir%\%FileToGet%, %MediaOutPath%\%MediaSubDirOut%\Wheel Images\%Description%.png, 1
                                    
                                    IfNotExist, %MediaOutPath%\%MediaSubDirOut%\Wheel Images\%Description%.png
                                    {
                                        FileAppend, FYI (Wheel not found in FTP): No Wheel Image - %Description%.png`n, %A_ScriptDir%\PBXrecorder.log
                                    }
                                    Else
                                    {
                                        FileAppend, Downloaded via FTP: Wheel Image - %Description%.png`n, %A_ScriptDir%\PBXrecorder.log
                                    }
                                }
                                Else
                                {
                                    FileAppend, FYI (FTP not enabled): No Wheel Image - %Description%.png`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }
                            Else
                            {
                                FileAppend, FYI (FTP not enabled): No Wheel Image - %SearchString%.png`n, %A_ScriptDir%\PBXrecorder.log
                            }                            
                            
                        }
                        ; END OF Extra FP file checks - Wheel images (FTP download supported)
                        ;===========================================================================
                        
                        
                        ; Media checked - Decide whether to record or skip table
                        ;===========================================================================
                        IfEqual MediaFoundFlag, 1    ;If all media exists then skip table
                        {
                            If PauseTime>=10
                                PauseTime:=PauseTime-5
                            TempLongPath = %TablePath%\%Table%
                            if (DragAndDrop<>1)
                            {
                                Progress, x200 y200 zh0 M h200 w600 FS10, `nMedia already exists.  Skipping...`n`n(Press ESC anytime to abort script)  ,`n`n%Description%, Capturing Videos... #%Loopcount% , Arial                                
                                Sleep %PauseTime%
                                FileAppend, Skipping table... %TablePath%\%Table%`n, %A_ScriptDir%\PBXrecorder.log
                            }
                            Else If inStr(TempLongPath, DragAndDropFile)  ;Check if drag and drop table already has media
                            {
                                DragAndDropTableFound := -1
                                Progress, x200 y200 zh0 M h200 w600 FS10, `nDrag and Drop table media already exists.  Skipping...`n`n(Press ESC anytime to abort script)  ,`n`n%Description%, Drag and Drop... #%Loopcount% , Arial                                
                                Sleep 3000    
                                FileAppend, Drag and drop table already has Media.  Skipping... %TablePath%\%Table%`n, %A_ScriptDir%\PBXrecorder.log                            
                            }
                            continue ;Skipping table!!!
                        }
                        Else If (DragAndDrop=1) ;and MediaFoundFlag = 0     ;Handle Drag and drop table recording
                        {
                            ;Check if current table matches the drag and drop table
                            TempLongPath = %TablePath%\%Table%
                            If inStr(TempLongPath, DragAndDropFile)    ;Match - go ahead and record
                            {
                                DragAndDropTableFound := 1
                                Progress, x200 y200 M h240 w600 FS10 CB0000FF, `n`nLoading "%Table%"`n`nDrag and Drop recording will start in %LoadTime% seconds...`n(Press PAUSE if you need to edit/setup table)`n(Press ESC anytime to abort script) ,`n`n%Description%`n, Capturing Videos... #%Loopcount% , Arial
                                FileAppend, Launching table: %Executable% /STAYINRAM /open %TablePath%\%Table% /play /exit`n, %A_ScriptDir%\PBXrecorder.log
                            }
                            Else    ;No match - skip this table
                            {
                                FileAppend, Skipping table due to Drag and Drop mode... %TablePath%\%Table%`n, %A_ScriptDir%\PBXrecorder.log
                                continue ;Skipping table
                            }
                        }
                        Else If ((OnlyRecordMissingVideos=3) and (MediaAtLeastOneFound=1)) ;check if Mode = Record ONLY new tables(Ignore partial media set) AND any if media was found
                        {
                                FileAppend, Skipping table - Recording only new tables. Partial media set exists... %TablePath%\%Table%`n, %A_ScriptDir%\PBXrecorder.log
                                continue ;Skipping table
                        }
                        Else ;MediaFoundFlag = 0    ;Launch table to record
                        {
                            Progress, x200 y200 M h240 w600 FS10 CB0000FF, `n`nLoading "%Table%"`n`nRecording will start in %LoadTime% seconds...`n(Press PAUSE if you need to edit/setup table)`n(Press ESC anytime to abort script) ,`n`n%Description%`n, Capturing Videos... #%Loopcount% , Arial
                            FileAppend, Launching table: %Executable% /STAYINRAM /open %TablePath%\%Table% /play /exit`n, %A_ScriptDir%\PBXrecorder.log
                        }        

                        ;=================================================
                        ;Start Table
                        ;=================================================
                        Recordcount:=Recordcount + 1
                        WinHide, ahk_class Button
                        WinHide, ahk_class Shell_TrayWnd
                        Run, "%WorkingPath%\%Executable%" /STAYINRAM /open "%TablePath%\%Table%" /play /exit
                                            LoadingTable:=1
                        Process, wait, Future Pinball.exe
                        If DMD_width > 0
                            Run, %WorkingPath%\FutureDMD.exe table="%Table%" close=1

                        WinWaitActive, ahk_class FuturePinballOpenGL
                        If (TestMode=1) ;debug speed up of recording
                        {
                            Loop, 50 ;DEBUG
                            {            
                                j := A_Index/1.0
                                Progress,%j%
                                Sleep 100    
                                If (PBXRPauseMode=1)
                                {
                                    Goto, PBRXPaused
                                }
                            }        ; Allow time for table score display to get well beyond loading and boot images
                        }
                        Else
                        {
                            Loop, % LoadTimeX ; 
                            {            
                                j := A_Index/LoadTimeX*100
                                Progress,%j%
                                Sleep 100    
                                If (PBXRPauseMode=1)
                                {
                                    Goto, PBRXPaused
                                }
                            }        ; Allow time for table score display to get well beyond loading and boot images
                        }                    
                        Progress, Off
                        LoadingTable:=0
                        
    PBRXPaused:
                        If (LoadingTable=1)    ;User has paused PBX Recorder
                        {
                            Progress, Off
                            WindowX:=PF_width/2 -200
                            Progress, x%WindowX% y0 h25 w400 FS10 CB0000FF, Paused.  Press Pause key to start recording  , Paused.  Press Pause key to start recording, Press Pause to Resume , Arial
                            WinWaitClose, Press Pause to Resume
                        }
                        LoadingTable:=0
                        PBXRPauseMode:=0
                            
                        ; Record Video as .mkv - Fast Capture and take screenshots
                        ;============================================================
                        FileAppend, Video and screenshot capture (%A_Hour%:%A_Min%:%A_Sec%)`n, %A_ScriptDir%\PBXrecorder.log
                        If (OnlyRecordMissingVideos = 2)    ;Mode = RECORD MISSING MEDIA ONLY
                        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                        {
                            If (PFImageOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\Table Images\%SearchString%.*
                                {
                                    RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection playfield --profile playfield --scene playfield --startrecording && exit,, Hide
                                    FileAppend, Screenshot "%MediaOutPath%\%MediaSubDirOut%\Table Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }
                            If (BGImageOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\BackGlass Images\%SearchString%.*
                                {
                                    RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection bg --profile bg --scene bg --startrecording && exit,, Hide
                                    FileAppend, Screenshot "%MediaOutPath%\%MediaSubDirOut%\Backglass Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }
                            If (DMDImageOnly=1)
                            {
                                If DMD_width > 0
                                {
                                    IfNotExist, %MediaOutPath%\%MediaSubDir%\DMD Images\%SearchString%.*
                                    {
                                        RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection dmd --profile dmd --scene dmd --startrecording && exit,, Hide
                                        FileAppend, Screenshot "%MediaOutPath%\%MediaSubDirOut%\DMD Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
                                    }
                                }
                                Else
                                {
                                    FileAppend, Screenshot skipped (Bad DMD size) "%MediaOutPath%\%MediaSubDirOut%\DMD Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }

    ;                        Sleep,3000

                            If (PFVideoOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\Table Videos\%SearchString%.*
                                {
                                    RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection playfield --profile playfield --scene playfield --startrecording && exit,, Hide
                                    FileAppend, Recording "%A_ScriptDir%\playfield\playfield.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }
                            If (BGVideoOnly=1)
                            {
                                IfNotExist, %MediaOutPath%\%MediaSubDir%\BackGlass Videos\%SearchString%.*
                                {
                                    RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection bg --profile bg --scene bg --startrecording && exit,, Hide
                                    FileAppend, Recording "%A_ScriptDir%\bg.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }
                            If (DMDVideoOnly=1)
                            {
                                If DMD_width > 0 
                                {
                                    IfNotExist, %MediaOutPath%\%MediaSubDir%\DMD Videos\%SearchString%.*
                                    {
                                        RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection dmd --profile dmd --scene dmd --startrecording && exit,, Hide
                                        FileAppend, Recording "%A_ScriptDir%\dmd.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                                    }
                                }
                                Else
                                {
                                    FileAppend, Recording skipped (Bad DMD size) "%A_ScriptDir%\dmd.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }
                        }
                        Else If ((OnlyRecordMissingVideos=3) and (MediaAtLeastOneFound=1))
                        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                        {
                            ;Safety check for Mode = Record only new tables (Ignore partial media set).
                            FileAppend, Skipping table - XXX Recording only new tables. Partial media set exists... %TablePath%\%Table%`n, %A_ScriptDir%\PBXrecorder.log
                        }
                        Else     ;Record everything for this table (Mode = Re-record all, Record if incomplete table, Record if new table)
                        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                        {                    
                            If (PFImageOnly=1)
                            {
                                RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection playfield --profile playfield --scene playfield --startrecording && exit,, Hide
                                FileAppend, Screenshot "%MediaOutPath%\%MediaSubDirOut%\Table Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
                            }
                            If (BGImageOnly=1)
                            {
                                RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection bg --profile bg --scene bg --startrecording && exit,, Hide
                                FileAppend, Screenshot "%MediaOutPath%\%MediaSubDirOut%\Backglass Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
                            }
                            If (DMDImageOnly=1)
                            {
                                If DMD_width > 0 
                                {
                                    RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection dmd --profile dmd --scene dmd --startrecording && exit,, Hide
                                    FileAppend, Screenshot "%MediaOutPath%\%MediaSubDirOut%\DMD Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                                Else
                                {
                                    FileAppend, Screenshot skipped (Bad DMD size) "%MediaOutPath%\%MediaSubDirOut%\DMD Images\%SearchString%.png"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }
    ;                        Sleep,3000

                            If (PFVideoOnly=1)
                            {
                                RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection playfield --profile playfield --scene playfield --startrecording && exit,, Hide
                                FileAppend, Recording "%A_ScriptDir%\playfield\playfield.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                            }
                            If (BGVideoOnly=1)
                            {
                                RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection bg --profile bg --scene bg --startrecording && exit,, Hide
                                FileAppend, Recording "%A_ScriptDir%\bg.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                            }
                            If (DMDVideoOnly=1)
                            {
                                If DMD_width > 0 
                                {
                                    RunWait, %comspec% /k  cd "%OBSPath%\bin\64bit" && start obs64.exe --portable --collection dmd --profile dmd --scene dmd --startrecording && exit,, Hide
                                    FileAppend, Recording "%A_ScriptDir%\dmd.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                                Else
                                {
                                    FileAppend, Recording skipped (Bad DMD size) "%A_ScriptDir%\dmd.mkv"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                            }
                        }
                                     
                        WinHide, ahk_class FuturePinball
                        WinMinimize, ahk_class FuturePinball
                        WinActivate, ahk_class FuturePinballOpenGL
                        WinWaitActive, ahk_class FuturePinballOpenGL

                        
                        ;Timer if capturing any videos
                        If (PFVideoOnly=1 OR BGVideoOnly=1 OR DMDVideoOnly=1)
                            {
                                OBSRecTime:=RecTime * 1000
                                Sleep,%OBSRecTime%
                            }
                        Else
                            Sleep,3000

                        ; Clean up
                        ;==========================
                        Send ^{U down}^{U up}
                        WinClose, ahk_class Qt5QWindowIcon
                        Send {Enter}
                        WinClose, ahk_class Qt5QWindowIcon
                        Send {Enter}
                        WinClose, ahk_class Qt5QWindowIcon
                        Send {Enter}
                        Run, taskkill /T /IM obs64.exe ,,UseErrorLevel
                        WinHide, ahk_class FuturePinball
                        WinMinimize, ahk_class FuturePinball
                        WinActivate, ahk_class FuturePinballOpenGL
                        WinWaitActive, ahk_class FuturePinballOpenGL
                        Send {Esc}
                        WinWaitClose, ahk_class FuturePinballOpenGL
                        Process, close, FutureDMD.exe
                        WinClose, ahk_class FuturePinball
                        Run, taskkill /T /IM "Future Pinball.exe" ,,UseErrorLevel
                        Run, taskkill /T /IM "FutureDMD.exe" ,,UseErrorLevel
                        Run, taskkill /IM obs64.exe /F,,UseErrorLevel                
                        Sleep,5000
                        Run, taskkill /F /IM "Future Pinball.exe",,UseErrorLevel
                        WinKill, Error

                        WinShow, ahk_class Button
                        WinShow, ahk_class Shell_TrayWnd

                        
                        ;PIN2DMD related - Not ready for primetime yet
                        ;==========================
                        ;IfExist, %A_ScriptDir%\pin2dmd\pin2dmd.exe
                        ;{
                        ;    Run, %A_ScriptDir%\pin2dmd\Pin2DMD.exe /r,,UseErrorLevel
                        ;}
                        ;IfExist, %A_ScriptDir%\pin2dmd\blank.ppm
                        ;{
                        ;    Run, %A_ScriptDir%\pin2dmd\Pin2DMD.exe /i %A_ScriptDir%\pin2dmd\blank.ppm,,UseErrorLevel
                        ;}

                        ;Convert Videos to .f4v/.mp4 if any mkv exist  - Post Capture Trim and Transcode
                        ;============================================================================
                        Progress, x200 y200 zh0 M h200 w600 FS10, `n`nConvert Videos to %RecExt% if video was captured`n`n(Press ESC anytime to abort script) ,`n`n%Description%, Capturing Videos... #%Loopcount% , Arial
                        
                        ConvertStatusStr= (
                        If (PFVideoOnly=1)
                            ConvertStatusStr= %ConvertStatusStr% PF 
                        If (BGVideoOnly=1)
                            ConvertStatusStr= %ConvertStatusStr% BG     
                        If (DMDVideoOnly=1)
                            ConvertStatusStr= %ConvertStatusStr% DMD
                        ConvertStatusStr= %ConvertStatusStr%  )
                        
                        FileAppend, Convert Videos to %RecExt% if video was captured (%A_Hour%:%A_Min%:%A_Sec%)`n, %A_ScriptDir%\PBXrecorder.log
                        IfExist, %A_ScriptDir%\playfield.mkv ;If (PFVideoOnly=1) OR (PFImageOnly=1);
                        {
                            If (PFImageOnly=1)
                                Run, "%FFMpegPath%\ffmpeg" -y -ss 1 -i "%A_ScriptDir%\playfield.mkv" -vframes 1 -vf "rotate=PI:bilinear=0" "%MediaOutPath%\%MediaSubDirOut%\Table Images\%SearchString%.png"
                            Else
                                {
                                    Run, "%FFMpegPath%\ffmpeg" -y -i "%A_ScriptDir%\playfield.mkv" -ss 10 -to 1000 -vf [in]rotate=PI:bilinear=0[middle];[middle]scale=1920:-1[out] -map 0:0 -c:v libx264 -crf 26 "%MediaOutPath%\%MediaSubDirOut%\Table Videos\%SearchString%.%RecExt%"
                                    FileAppend, Converting to "%MediaOutPath%\%MediaSubDirOut%\Table Videos\%SearchString%.%RecExt%"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                        }
                        IfExist, %A_ScriptDir%\bg.mkv ;If (BGVideoOnly=1) OR (BGImageOnly=1);
                        {
                            If (BGImageOnly=1)
                                Run, "%FFMpegPath%\ffmpeg" -y -ss 1 -i "%A_ScriptDir%\bg.mkv" -vframes 1 "%MediaOutPath%\%MediaSubDirOut%\Backglass Images\%SearchString%.png"
                            Else
                                {
                                    Run, "%FFMpegPath%\ffmpeg" -y -i "%A_ScriptDir%\bg.mkv" -ss 10 -to 1000 -map 0:0 -c:v libx264 -crf 26 "%MediaOutPath%\%MediaSubDirOut%\Backglass Videos\%SearchString%.%RecExt%"
                                    FileAppend, Converting to "%MediaOutPath%\%MediaSubDirOut%\Backglass Videos\%SearchString%.%RecExt%"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                        }
                        IfExist, %A_ScriptDir%\dmd.mkv ;If (DMDVideoOnly=1)  OR (DMDImageOnly=1);
                        {        
                            If (DMDImageOnly=1)
                                Run, "%FFMpegPath%\ffmpeg" -y -ss 1 -i "%A_ScriptDir%\dmd.mkv" -vframes 1 -vf "crop=w=%DMD_width%:h=%DMD_height%:x=%DMDXCrop%:y=%DMD_Y%" "%MediaOutPath%\%MediaSubDirOut%\DMD Images\%SearchString%.png"
                            Else
                                {
                                    Run, "%FFMpegPath%\ffmpeg" -y -i "%A_ScriptDir%\dmd.mkv" -ss 10 -to 1000 -vf "crop=w=%DMD_width%:h=%DMD_height%:x=%DMDXCrop%:y=%DMD_Y%" -map 0:0 -c:v libx264 -crf 26 "%MediaOutPath%\%MediaSubDirOut%\DMD Videos\%SearchString%.%RecExt%"
                                    FileAppend, Converting to "%MediaOutPath%\%MediaSubDirOut%\DMD Videos\%SearchString%.%RecExt%"`n, %A_ScriptDir%\PBXrecorder.log
                                }
                        }
                        ; Clean up
                        ;==========================
                        Process, WaitClose, ffmpeg.exe, 500
                        Run, taskkill /IM ffmpeg.exe /F
                        Run, taskkill /IM ffmpeg.exe /F
                        Run, taskkill /IM ffmpeg.exe /F
                        Progress, Off
                        Sleep,3000
                        ;SoundBeep, 400, 200 
                        FileDelete, %A_ScriptDir%\playfield.mkv
                        FileDelete, %A_ScriptDir%\bg.mkv
                        FileDelete, %A_ScriptDir%\dmd.mkv        
                        FileAppend, Table done (%A_Hour%:%A_Min%:%A_Sec%)`n, %A_ScriptDir%\PBXrecorder.log
                        
                    } ;End of If TableExists = 1
                } ;End of If TableEnabled = 1
            } ;End of Else IfInString, A_LoopReadLine, /game
        } ;End of Loop, Read, %XMLPath%\%XMLFilename%.xml
    }

    ; All done!
    ;===============
    Progress, Off
    If (DragAndDrop<>1)
    {
        FileAppend, `n%Recordcount% new recordings out of %Loopcount% tables. Finished (%A_Hour%:%A_Min%:%A_Sec%)`n, %A_ScriptDir%\PBXrecorder.log
        Msgbox,0, Recording Finished,Recording is complete.  %Recordcount% new recordings out of %Loopcount% tables
    }
    Else ;Drag and drop done
    {
        If (DragAndDropTableFound=1)
        {
            FileAppend, `nDrag and Drop recording finished (%DragAndDropFile%). Finished (%A_Hour%:%A_Min%:%A_Sec%)`n, %A_ScriptDir%\PBXrecorder.log
            Msgbox,0, Drag and Drop, Recording is complete`n`n(%DragAndDropFile%).
        }
        Else If (DragAndDropTableFound=-1)
        {
            FileAppend, `nDrag and Drop skipped.  Media already exists (%DragAndDropFile%). Finished (%A_Hour%:%A_Min%:%A_Sec%)`n, %A_ScriptDir%\PBXrecorder.log
            Msgbox,0, Drag and Drop, No Recording. Media already exists`n`n(%DragAndDropFile%).
        }
        Else
        {
            FileAppend, `nDrag and Drop table was not found in the FP XML files (%DragAndDropFile%). Finished (%A_Hour%:%A_Min%:%A_Sec%)`n, %A_ScriptDir%\PBXrecorder.log
            Msgbox,0, Drag and Drop, Table was not found in the FP XML files.  No recording performed`n`n(%DragAndDropFile%).
        }
    }
    ExitApp


    ;*******************************************
    ;*******************************************
    ; Misc Subroutines for Msgbox and Gui windows and Exit
    ;*******************************************
    ;*******************************************
    RecordModeButtonNames: 
    IfWinNotExist, Record Mode
        return  ; Keep waiting.
    SetTimer, RecordModeButtonNames, off 
    WinActivate 
    ControlSetText, Button1, &Videos Only
    ControlSetText, Button2, &Both 
    return    

    MissingVideosButtonNames: 
    IfWinNotExist, Record Mode
        return  ; Keep waiting.
    SetTimer, MissingVideosButtonNames, off 
    WinActivate 
    ControlSetText, Button1, &Missing Only
    ControlSetText, Button2, &All Tables
    return    

    CurrSettingsButtonNames: 
    IfWinNotExist, Current Recorder Settings
        return  ; Keep waiting.
    SetTimer, CurrSettingsButtonNames, off 
    WinActivate 
    ControlSetText, Button1, &Continue
    ControlSetText, Button2, &Change
    return    


    StoreMediaButtonNames: 
    IfWinNotExist, Storing Media
        return  ; Keep waiting.
    SetTimer, StoreMediaButtonNames, off 
    WinActivate 
    ControlSetText, Button1, &Combined
    ControlSetText, Button2, &Separate
    return    

    GuiClose:
    ExitApp

    ;Pressing the ESC key will abort the script
    Esc::
    IfWinNotExist,Add Table to XML    
        IfWinNotExist,Press Pause to Resume
            {
                WinShow, ahk_class Button
                WinShow, ahk_class Shell_TrayWnd
                ExitApp
            }    
    Else
        Return   ; XML dialog present, do not exit

    Pause::
        If (LoadingTable=1)
        {
            If (PBXRPauseMode=0)
            {
                PBXRPauseMode:=1
            }
            Else
            {
                Progress, Off
            }
        }
        Return
        
        
    Confirm:
        Gui, Submit
        PFVideoOnly=0
        BGVideoOnly=0
        DMDVideoOnly=0
        PFImageOnly=0
        BGImageOnly=0
        DMDImageOnly=0

        if (PFVid = 1) 
            PFVideoOnly=1
        if (BGVid = 1) 
            BGVideoOnly=1
        if (DMDVid = 1) 
            DMDVideoOnly=1
        if (PFImage = 1) 
            PFImageOnly=1
        if (BGImage = 1) 
            BGImageOnly=1
        if (DMDImage = 1) 
            DMDImageOnly=1    

        Gui, Destroy
    return
            
    Select:
        Gui, Submit
        if (RadioGroup1) 
            RecTime:=5
        else if (RadioGroup2) 
            RecTime:=15
        else if (RadioGroup3) 
            RecTime:=30
        else if (RadioGroup4) 
            RecTime:=60
        else if (RadioGroup5) 
            RecTime:=120
        else if (RadioGroup6) 
            RecTime:=300    
            
        Gui, Destroy
    Return

    MediaMode:
        Gui, Submit
        if (MRadioGroup1) 
            OnlyRecordMissingVideos:=2
        else if (MRadioGroup2) 
            OnlyRecordMissingVideos:=1
        else if (MRadioGroup3) 
            OnlyRecordMissingVideos:=0
        else if (MRadioGroup4) 
            OnlyRecordMissingVideos:=3
        Gui, Destroy
    Return

    MediaF:
        Gui, Submit
        if (RadioGroupMF1) 
            MediaFileNaming:=0
        else if (RadioGroupMF2) 
            MediaFileNaming:=1

        Gui, Destroy
    Return

    MediaR:
        Gui, Submit
        if (RadioGroupRF1) 
        {
            RecFormat:=0
            RecExt=f4v
        }
        else if (RadioGroupRF2) 
        {
            RecFormat:=1
            RecExt=mp4
        }
        Gui, Destroy
    Return

    ; Subroutines for Add Table to XML files
    GetXMLDescSelected:
    GuiControlGet, XMLDescSelected 
    x:=IPDBArray[XMLDescSelected]
    GuiControl,, XMLDescText,%x%
    x:=IPDBMfrArray[XMLDescSelected]
    GuiControl,, XMLMfr,%x%
    x:=IPDBYearArray[XMLDescSelected]
    GuiControl,, XMLYear,%x%
    x:=IPDBTypeArray[XMLDescSelected]
    GuiControl,, XMLType,%x%
    Return

    XMLLaunch:
    GuiControlGet, XMLAltExe
    GuiControlGet, XMLAltExeName
    If (XMLAltExe = 1)
        IfExist, %WorkingPath%\%LaunchExecutable%
        {
            Run, "%WorkingPath%\%LaunchExecutable%" /STAYINRAM /open "%DragAndDropFile%" /play /exit
        }
        Else
        {
            Msgbox, %WorkingPath%\%LaunchExecutable% could not be found
            Return
        }
    Else
        IfExist, %WorkingPath%\%XMLAltExeName%
            Run, "%WorkingPath%\%XMLAltExeName%" /STAYINRAM /open "%DragAndDropFile%" /play /exit
        Else
        {
            Msgbox, %WorkingPath%\%XMLAltExeName% could not be found
            Return
        }
    Return

    XMLCancel:
    Gui, Destroy
    ExitApp

    XMLSaveExit:
    gosub XMLSave
    ;Msgbox XML Saved
    ExitApp

    XMLSave:
    ;Figure out which XML file to update
    GuiControlGet, XMLFPSystem
    tempXMLString1:=XMLPathArray[XMLFPSystem]
    tempXMLString2:=XMLFileNameArray[XMLFPSystem]
    tempXMLStringOrig=%tempXMLString1%\%tempXMLString2%.xml
    tempXMLStringBak=%tempXMLString1%\%tempXMLString2%.bak
    ;FileAppend, `t TEST %tempXMLStringOrig%`n, %A_ScriptDir%\XMLtest.txt

    FileCopy, %tempXMLStringOrig%, %tempXMLStringBak%, 1
    FileRead, tempXMLfilestring, %tempXMLStringOrig%
    StringReplace, tempXMLfilestring, tempXMLfilestring, `r`n</menu>
    StringReplace, tempXMLfilestring, tempXMLfilestring, `n</menu>
    FileDelete, %tempXMLStringOrig%
    FileAppend, %tempXMLfilestring%, %tempXMLStringOrig%

    GuiControlGet, XMLTableFileName
    FileAppend, `t<game name="%XMLTableFileName%">`n, %tempXMLStringOrig%

    GuiControlGet, XMLDescText 
    FileAppend, `t`t<description>%XMLDescText%</description>`n, %tempXMLStringOrig%
    FileAppend, `t`t<rom></rom>`n, %tempXMLStringOrig%

    GuiControlGet, XMLMfr
    FileAppend, `t`t<manufacturer>%XMLMfr%</manufacturer>`n, %tempXMLStringOrig%

    GuiControlGet, XMLYear
    FileAppend, `t`t<year>%XMLYear%</year>`n, %tempXMLStringOrig%

    GuiControlGet, XMLType
    FileAppend, `t`t<type>%XMLType%</type>`n, %tempXMLStringOrig%

    GuiControlGet, XMLHideDMD
    If (XMLHideDMD=1)
        FileAppend, `t`t<hidedmd>True</hidedmd>`n, %tempXMLStringOrig%
    Else
        FileAppend, `t`t<hidedmd>False</hidedmd>`n, %tempXMLStringOrig%

    GuiControlGet, XMLHideBG
    If (XMLHideBG=1)
        FileAppend, `t`t<hidebackglass>True</hidebackglass>`n, %tempXMLStringOrig%
    Else
        FileAppend, `t`t<hidebackglass>False</hidebackglass>`n, %tempXMLStringOrig%

    GuiControlGet, XMLEnabled
    If (XMLEnabled=1)
        FileAppend, `t`t<enabled>True</enabled>`n, %tempXMLStringOrig%
    Else
        FileAppend, `t`t<enabled>False</enabled>`n, %tempXMLStringOrig%

    GuiControlGet, XMLRating
    XMLRating := XMLRating-1    
    FileAppend, `t`t<rating>%XMLRating%</rating>`n, %tempXMLStringOrig%

    GuiControlGet, XMLAltExe
    GuiControlGet, XMLAltExeName
    If (XMLAltExe = 2)
        FileAppend, `t`t<alternateExe>%XMLAltExeName%</alternateExe>`n, %tempXMLStringOrig%
    Else If (XMLAltExe = 3)
        FileAppend, `t`t<Exe>%XMLAltExeName%</alternateExe>`n, %tempXMLStringOrig%

    FileAppend, `t</game>`n, %tempXMLStringOrig%
    FileAppend, </menu>`n, %tempXMLStringOrig%
    Gui, Destroy
    Return

    XMLDB2S:
    IfExist, %DragAndDropFileDir%\%DragAndDropFileNameOnly%.directB2S
        Return
    Else IfExist, %DragAndDropFileDir%\%DragAndDropFileNameOnly%.exe
        Return
    Else ;Let user select DirectB2S file to rename
        FileSelectFile, XMLFilePicked,,%DragAndDropFileDir%,,*.directb2s

    IfExist, %XMLFilePicked%
    {
        SetTimer, DB2SButtonNames, 50 
        Msgbox, 3, DirectB2S File Rename, Create a copy of the DirectB2S file and rename it?            
        IfMsgBox, Yes ; Copy and rename the file
        {
            GuiControl ,, XDB2S, DB2S Found
            FileCopy, %XMLFilePicked%, %DragAndDropFileDir%\%DragAndDropFileNameOnly%.directB2S, 1
        }
        Else IfMsgBox, No ; Just rename the file
        {
            FileMove, %XMLFilePicked%, %DragAndDropFileDir%\%DragAndDropFileNameOnly%.directB2S, 1
            GuiControl ,, XDB2S, DB2S Found
        }
    }
    Return

    DB2SButtonNames: 
    IfWinNotExist, DirectB2S File Rename
        return  ; Keep waiting.
    SetTimer, DB2SButtonNames, off 
    WinActivate 
    ControlSetText, Button1, &Copy&&Rename
    ControlSetText, Button2, &Just Rename 
    return        
            
    ; Release 1.0    Initial release Nov 11, 2015
    ;                 Create playfield, backglass, dmd videos and/or images automatically based on PinballX setup
    ; Release 1.1    Fix bug if VisualPinball system is disabled  (Dec 2015)
    ; Release 1.2    Skip table if table is disabled in Game Manager/XML (Jan 9, 2016)
    ;                Add <AlternateExe> and <exe> xml tag support
    ;                Add support for & and ® and ' in Table and Description names
    ;               Check if vpt or vpx file exists, skip if not found
    ;                Detects if Wheel Images or DirectB2S/B2S.exe are missing
    ;                PinballX FTP users can enable automatic Wheel download support
    ;                If PIN2DMD.exe found, it will reset PIN2DMD between tables
    ; 1.3 changes   Feb 7, 2016            
    ;                 New recording mode added:  "Record complete media set for new tables only"  If any media is found, the table is skipped. Only tables with no media are recorded.   This might eliminate the need for the drag and drop feature, since this leaves your existing Pinballx Media set unchanged, i.e if you do not have DMD images for some existing tables, PBX Recorder will not try to create them
    ;                 Drag and drop .vpt/.vpx file onto PBXrecorder to record only one table (Table must be exist in the PinballX xml files)
    ;                 New option to record video in .mp4 or existing .f4v.  Now checks for existing .f4v or .mp4 or any file.
    ;                 New option to save Media filenames based on description name or table name
    ;                 Speed up the scanning of tables for people with larger libraries
    ;                 Improve DMD recording success by forcing dvd dimensions to an even pixel value
    ;                 Bug fix: Enable recordings for VP xml systems missing the enabled xml tag        
    ; 1.4 changes   Apr 7, 2016
    ;                New dialog to add table to Pinballx XML file
    ;                PAUSE and RESUME support to allow table script changes before recording.  Double tap PAUSE to record immediately
    ; 1.4FP         May 2, 2016
    ;                Future Pinball support with playfield capture via OBS Studio
    ;                Add support for ™ and recognition of &#42; (i.e, *) in Table and Description names
    ;                Some minor clean up for unused ErrorLevel parameters
                    

    ;                Add right click support (Play with VP, Record with PBXRecorder)
    ;todo: create reg entries
    ;todo: detect xml file to default to
    ;todo list duplicates xmls entries. 
    ;todo support [xxx] for wheel download.
    ;todo list tables not in the xml file
    ;todo switch ini parsing to use split string function
    ; possible bug.  recext not correct after modifying ini 

    Changes from 1.4

    ; 1.4FP         Future Pinball support with playfield capture via OBS Studio
    ;                Add support for ™ and recognition of &#42; (i.e, *) in Table and Description names
    ;               Some minor clean up for unused ErrorLevel parameters

    Again thanks to gtxjoe for allowing mods to his source code. 

    The links to download the config file is broken, can someone repost. I would like to use pbx to record future pinball tables.

×
×
  • Create New...