VMA Macro Interpreter

The VMA Video Analyser Package has an important new addition: a transversal macro language that can be used to automate processes in VMA Stream Reader, VMA Transport Stream Analyser, VMA Mosaic and VMA Video Analyser.

One single macro can interact with all applications!

The macro language gives access to all controls (buttons, textboxes, lists, etc.) and adds typical functions like IF-THEN-GOTO, IF-THEN-ELSE-ENDIF, FOR-NEXT, FOREACH-ENDFOREACH, GOTO-LABEL. Also included are functions to manipulate lists and strings, output to a user window or to a file and screenshot functions.

This way, any user can greatly extend the already vast functionality of the VMA Video Analyser Package.

Here is an example: how about a way to automatically scan the selected satellite: do a spectrum sweep, automatically perform a scan of all transponders and then render a list with the services of each transponder, preferably with a screenshot?

Here is the required macro:

;
; VMA Stream Reader Macro
;
; =========== CHANNEL SCAN → SATNAME.html + screenshots =========== 
OUTPUT.SHOW
OUTPUT.CLEAR
PRINT "------------------"
PRINT "Channel Scan Macro"
PRINT "------------------"

; --- Resolve satellite name and output locations ---
VMA.READER.MACRO: GET cmbSatellite AS satName
VMA.READER.MACRO: GET cmbPol AS polarity
LET satSafe "${satName}"
STR.REPLACE_REGEX "${satSafe}" "[\\/:*?'<>|]" "_" AS satSafe

; HTML path: C:\Temp\SATNAME.html
FORMAT "C:\Temp\{0} - {1}.html" "${satSafe}" "${polarity}" AS htmlPath

; Screenshot root: C:\Temp\SATNAME
FORMAT "C:\Temp\{0}" "${satSafe}" AS shotsRoot

LET outPath "C:\Temp\ChannelScan.csv"
CLICK Button2

TAB.SELECT "Auto Scan"
PRINT "Starting AUTO SCAN SPECTRUM..."
CLICK Button4


; --- Start fresh HTML ---
FILE.WRITE "${htmlPath}" "<!DOCTYPE html>"
FILE.APPEND "${htmlPath}" "<html><head><meta charset='utf-8'><title>${satSafe}</title>"
FILE.APPEND "${htmlPath}" "<style>body{font-family:Segoe UI,Arial,sans-serif;background:#111;color:#eee;padding:12px}h1,h2{color:#9fe871}table{border-collapse:collapse;margin:8px 0;width:100%}th,td{border:1px solid #444;padding:6px 8px;font-size:12px}th{background:#222}code{color:#ccc}.pics img{max-width:320px;margin:4px;border:1px solid #333;border-radius:4px}</style></head><body>"
FILE.APPEND "${htmlPath}" "<h1>${satSafe}</h1>"

; --- Make sure we're on Auto Scan tab and have carriers ---
TAB.SELECT "Auto Scan"
LISTBOX.GET_ITEMS lstCarriers AS carriers
IF "${carriers}" = ' THEN
    FILE.APPEND "${htmlPath}" "<p>No carriers found.</p></body></html>"
    PRINT "No carriers found. Aborting."
    GOTO END
ENDIF

; --- Launch TSA and connect (so we can read the services list) ---
APP.LAUNCH "VMA TRANSPORT STREAM ANALYSER.EXE"
APP.WAIT "VMA.TSA.MACRO" 3000
RENEW.CONNECTION TSA

; ======================= Iterate carriers =======================
FOREACH c IN "${carriers}"
    PRINT "Processing carrier: ${c}"
    TAB.SELECT "Auto Scan"

    ; Activate the carrier
    LISTBOX.DBLCLICK lstCarriers "${c}"
    SLEEP 1500

    ; Start streaming (this may auto-launch/connect TSA)
    CLICK Button1
    APP.WAIT "VMA.TSA.MACRO" 10000
    RENEW.CONNECTION TSA

    ; Start/refresh TSA measurement
    VMA.TSA.MACRO: CLICK btnStart
    SLEEP 5000

    ; Fetch services table from TSA
    VMA.TSA.MACRO: LISTVIEW.GET_ROWS lvDetails ALL AS svc

    ; Section header in HTML
    FILE.APPEND "${htmlPath}" "<h2>Transponder: ${c}</h2>"

	IF "${svc}" = "" THEN
		FILE.APPEND "${htmlPath}" "<p>No Service</p>"
		GOTO _skipMosaic
	ENDIF

	; Build services table
	FILE.APPEND "${htmlPath}" "<table>"
	FILE.APPEND "${htmlPath}" "<tr><th>Type</th><th>CA</th><th>Name</th><th>Prog ID</th><th>VPID</th><th>APID</th><th>Bitrate</th></tr>"

	STR.SPLIT "${svc}" SEP "{CRLF}" AS svcLines
	FOREACH row IN "${svcLines}"
		IF "${row}" = "" THEN GOTO _skipRow

		; split into cells
		STR.SPLIT "${row}" SEP "{TAB}" AS cells
		
		; skip header rows like "svc" or "Type"
		VAR first ""
		FOREACH c0 IN "${cells}"
			IF "${first}" = "" THEN LET first "${c0}"
		ENDFOREACH
		IF "${first}" = "svc" THEN GOTO _skipRow
		IF "${first}" = "Type" THEN GOTO _skipRow

		; write row
		FILE.APPEND "${htmlPath}" "<tr>"
		FOREACH cell IN "${cells}"
			FILE.APPEND "${htmlPath}" "<td>${cell}</td>"
		ENDFOREACH
		FILE.APPEND "${htmlPath}" "</tr>"

		LABEL _skipRow
	ENDFOREACH
	FILE.APPEND "${htmlPath}" "</table>"
    ; ======================= Mosaic screenshots =======================
    ; Open Mosaic from TSA
    VMA.TSA.MACRO: CLICK btnMosaic
    APP.WAIT "VMA.MOSAIC.MACRO" 15000
    RENEW.CONNECTION MOSAIC

    ; Determine freq-only folder name (first token of c)
    LET c_short "${c}"
    STR.REPLACE_REGEX "${c_short}" "^([^ ]+).*" "$1" AS c_short

    ; Folder: C:\Temp\SATNAME\<freq>
    VAR shotDir '
    FORMAT "{0}\{1}" "${shotsRoot}" "${c_short}" AS shotDir


    VMA.MOSAIC.MACRO: CATALOG PANEL AS _pans
    FILE.APPEND "${htmlPath}" "<div class='pics'>"

    FOREACH p IN "${_pans}"
        ; Safe filename for panel
        LET p_safe "${p}"
        STR.REPLACE_REGEX "${p_safe}" "[\\/:*?'<>|]" "_" AS p_safe
        STR.REPLACE_REGEX "${p_safe}" "^\s+|\s+$" ' AS p_safe

        ; Absolute image path: C:\Temp\SATNAME\<freq>\<panel>.png
        VAR shotPath '
        FORMAT "{0}\{1}.png" "${shotDir}" "${p_safe}" AS shotPath

        ; Relative path from C:\Temp\SATNAME.html to the file: SATNAME\<freq>\<panel>.png
        VAR relImg '
        FORMAT "{0}\{1}\{2}.png" "${satSafe}" "${c_short}" "${p_safe}" AS relImg

        VMA.MOSAIC.MACRO: SCREENSHOT.PANEL "${p}" "${shotPath}"
        FILE.APPEND "${htmlPath}" "<img src='${relImg}' alt='${p_safe}'>"
    ENDFOREACH

    FILE.APPEND "${htmlPath}" "</div>"

    APP.STOP MOSAIC

LABEL _skipMosaic

    ; Optional: stop TSA measurement for this TP
    VMA.TSA.MACRO: CLICK btnStart
ENDFOREACH

APP.STOP TSA

; ======================= Finish HTML =======================
FILE.APPEND "${htmlPath}" "</body></html>"
PRINT "HTML written: ${htmlPath}"

LABEL END
; ======================================================

The result of executing the macro can be seen here:

The VMA Macro Interpreter acts as an editor and debugger. Commands can be send individually, macros can be executed to the connected application and, most importantly, a catalog of the available controls can be downloaded, showing a tree view of all controls and the respective supported commands.

Once a macro is completed and error-free, it can be simply executed inside the respective app by pressing the F2 key.

Linear macros can be recorded using the F9 key. These can then be played back or edited in the VMA Macro Interpreter to include further commands, conditions, etc.

The F5 key (in case of VMA Mosaic it is the F6 key) shows little tags that help identify the name of the respective control:

Showcase of what can be done with the Macro Engine

Here is an example of an Automatic Transponder and Channel Scan on all configured satellites, producing a webpages and screenshots without user intervention. It uses the same macro as above, but wraps it inside two further FOREACH loops: one for each configured satellite, the other for Horizontal and Vertical polarities.

The result can be seen here:

CLICK HERE