I like to run multiple instances of VLC, each with its own playlist, and be able to control them using the web interface and telnet. I then have some python scripts to simplify sending commands. # Powershell ```powershell # create a shortcut function CreateVlcShortcut { param ( [String]$shortcutName = "VLC Media Player", [Int]$portOffset = 0 ) $HPORT = 8000 + $portOffset $TPORT = 7000 + $portOffset $shortcutPath = "C:\Program Files\VideoLAN\VLC\vlc.exe" $shortcutArguments = "--http-port $HPORT --telnet-port $TPORT --telnet-password tree --http-password tree" $WshShell = New-Object -COMObject WScript.Shell $Shortcut = $WshShell.CreateShortcut("VLC $portOffset.lnk") $Shortcut.TargetPath = $shortcutPath $Shortcut.Arguments = $shortcutArguments $Shortcut.Save() } # Example usage #CreateVlcShortcut -portOffset 0 #CreateVlcShortcut -portOffset 20 # Create Multiple # iterate over a range of numbers function IterateOverRange { param ( [Int]$start = 0, [Int]$end = 30 ) for ($i = $start; $i -lt $end; $i++) { CreateVlcShortcut -portOffset $i } } IterateOverRange -start 0 -end 5 IterateOverRange -start 10 -end 15 IterateOverRange -start 20 -end 25 IterateOverRange -start 30 -end 35 ``` # CLI tools At present I have no idea how to replace these on Windows without using cygwin and expect. I can, of course, run the Linux versions in WSL. ## tvlc This is a wrapper around `expect`. ```bash #!/bin/bash H="$1" P="$2" if [ -z "$H" -o -z "$P" ]; then echo "tvlc host port cmd ..." exit 1 fi [ "$H" = "s" ] && H="snarf" # use this to create shortcuts tvlc_expect "$H" "$P" ``` and `tvlc_expect` is ``` #!/usr/bin/expect set timeout 5 set host "[lindex $argv 0]" set tport "[lindex $argv 1]" puts "tport '$tport'" if { $tport == "" } { set tport 0 } set port "[expr 7000 + $tport]" set password "tree" spawn telnet $host $port expect "Password:" send "$password\r" expect "Welcome, Master" interact ``` ## tvlcmd This uses python's `socket` module rather than using `expect`. ```py #!/usr/bin/env python3 import socket from time import sleep import sys from threading import Thread # shorthands d = { "s": "snarf" } def get_ports(ps): xs = [ int(x) for x in ps.split(",") ] for x in xs: if x < 0 or x > 200: raise ValueError(f"Port {x} out of range") return set(xs) def get_hosts(hs): ys = [ (d[x] if x in d else x) for x in hs.split(",") ] return set(ys) args = sys.argv[1:] try: host, port, *cmds = args ports = get_ports(port) hosts = get_hosts(host) except ValueError as e: print(f"ValueError {e}") print(f"{sys.argv[0]} [...]",file=sys.stderr) exit(1) cs = [] cmdi = iter(cmds) for cmd in cmdi: if cmd == "-f": try: fn = next(cmdi) except StopIteration: print(f"Missing filename for -f",file=sys.stderr) exit(1) with open(fn) as f: lines = f.read().rstrip().splitlines() cs.extend(lines) else: cs.append(cmd) cmds = cs def doit(s,host,port,cmds): try: s.connect((host,port)) except Exception: print(f"# fail doit connect {host}:{port}",file=sys.stderr) return n = 0 while True: n += 1 if n > 100: print("doom",file=sys.stderr) exit(1) a = s.recv(1024) if b"Password:" in a: s.sendall(b"tree\n") sleep(0.1) b = s.recv(1024) if b"aster" in b: while not b">" in b: b = s.recv(1024) return docmds(s,cmds) sleep(0.1) def docmds(s,cmds): for cmd in cmds: cmd = cmd.replace("_"," ") cmd += "\n" s.sendall(cmd.encode()) oldtimeout = s.gettimeout() s.settimeout(0.5) sleep(0.1) n = 0 while True: try: a = s.recv(1024) except TimeoutError: break if a == b"": break try: b = a.decode() except Exception: b = "".join( x for x in a if ord(x) < 128 and ord(x) >= 32 ) sys.stdout.write(b) if "\n>" in b or b.startswith(">"): break print() s.settimeout(oldtimeout) sleep(0.1) def doit1(host,port,cmds): try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: doit(s,host,port,cmds) except Exception as e: print(f"Exception {e} sending to {host}:{port}") def main(): for host in hosts: for port in ports: port += 7000 print(f"{host}:{port}") Thread(target=doit1,args=(host,port,cmds)).start() if __name__ == "__main__": main() ```