#!/usr/bin/env python3 # Sequence matrix: which load order crashes? # usage: repro_seq.py e.g. "sfz,vst3" "sf2,vst3" "vst3,sfz" "sf2,sfz,vst3" import ctypes, os, struct, subprocess, sys, time BRIDGE = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "build", "Release", "daw_vst_bridge.exe")) SF2 = r"C:\Users\locpham\SonicForgeStudio\app\storage\soundfonts\518e850f-a5d3-4790-b1f9-0c90c203c524.sf2" SFZ = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "sfizz-src", "tests", "TestFiles", "g2_test.sfz")) VST3 = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "build", "VST3", "Release", "mda-vst3.vst3")) SHM_NAME = "SonicForge_DAW_IPC" SIZE = 11160 CTRL_Q, CTRL_Q_COUNT = 2836, 11156 kern = ctypes.windll.kernel32 PAGE_READWRITE, FILE_MAP_ALL_ACCESS = 0x04, 0xF001F kern.CreateFileMappingW.restype = ctypes.c_void_p kern.CreateFileMappingW.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_wchar_p] kern.MapViewOfFile.restype = ctypes.c_void_p kern.MapViewOfFile.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_size_t] kern.UnmapViewOfFile.restype = ctypes.c_int kern.UnmapViewOfFile.argtypes = [ctypes.c_void_p] kern.CloseHandle.restype = ctypes.c_int kern.CloseHandle.argtypes = [ctypes.c_void_p] h = kern.CreateFileMappingW(None, None, PAGE_READWRITE, 0, SIZE, SHM_NAME) if not h: sys.exit("CreateFileMappingW failed") v = kern.MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0) if not v: sys.exit("MapViewOfFile failed") buf = (ctypes.c_ubyte * SIZE).from_address(v) def w32(o, x): struct.pack_into(" 1 else "sfz,vst3" env = dict(os.environ, SF_PARENT_PID=str(os.getpid()), SF_SAMPLE_RATE="44100") logpath = os.path.join(os.path.dirname(BRIDGE), "seq_%s.txt" % seq.replace(",", "_")) logf = open(logpath, "w", encoding="utf-8") proc = subprocess.Popen([BRIDGE], env=env, cwd=os.path.dirname(BRIDGE), stdout=logf, stderr=subprocess.STDOUT, text=True) try: for i, name in enumerate(seq.split(",")): if name == "sf2": load_instrument(2, SF2, ch=0) elif name == "sfz": load_instrument(3, SFZ, ch=1) elif name == "vst3": load_instrument(0, VST3, ch=2) time.sleep(0.6) if proc.poll() is not None: print("DIED after %s rc=%s" % (name, proc.poll())) break else: time.sleep(2) print("ALIVE after %s rc=%s" % (seq, proc.poll())) logf.flush() print("log:") print(open(logpath, encoding="utf-8").read()[:1500]) finally: if proc.poll() is None: proc.terminate() try: proc.wait(timeout=3) except subprocess.TimeoutExpired: proc.kill() logf.close() kern.UnmapViewOfFile(v) kern.CloseHandle(h)