#!/bin/python import argparse import socket import mido from enum import Enum MIXER_PORT = 51325 class Mixer: def __init__(self, ip, port): self.sock = socket.create_connection((ip, port)) A_H_ID = [0x00, 0x00, 0x1A] QU_MIXER = [0x50, 0x11] MAJOR_MINOR = [0x01, 0x00] ALL_CALL_MIDI_CHANNEL = [0x7F] sysex_allcall = A_H_ID + QU_MIXER + MAJOR_MINOR + ALL_CALL_MIDI_CHANNEL def recv(self): p = mido.Parser() while True: data = self.sock.recv(1024) if not data: break p.feed(data) if p.pending(): msg = p.get_message() print(msg) print("Hex: ", " ".join(f"{b:02X}" for b in msg.data)) return msg def get_system_state(self): id = 0x10 i_pad_flag = 0x01 data = self.sysex_allcall + [id, i_pad_flag] msg = mido.Message('sysex', data=data) msg_bytes = bytes(msg.bytes()) self.sock.sendall(msg_bytes) print("Sent:", " ".join(f"{b:02X}" for b in msg_bytes)) response = self.recv() class QuModel(Enum): QU16 = 1 QU24 = 2 QU32 = 3 QUPAC = 4 QUSB = 5 def __str__(self): labels = { 1: "Qu-16", 2: "Qu-24", 3: "Qu-32", 4: "Qu-Pac", 5: "Qu-SB", } return labels[self.value] sysex_header = response.data[:8] midi_channel = int(response.data[7]) id = int(response.data[8]) i_pad_flag = int(response.data[9]) major_ver = int(response.data[10]) minor_ver = int(response.data[11]) print(f"sysex_header: {sysex_header}") print(f"MIDI channel: {midi_channel}") print(f"ID: 0x{id:02X}") print(f"Model: {QuModel(i_pad_flag)}") print(f"Firmware Version: {major_ver}.{minor_ver}") def main(): parser = argparse.ArgumentParser(description="Allen & Heath Qu Remote Control") parser.add_argument("ip", help="IP of the mixer") parser.add_argument("command", help="Command to execute") args = parser.parse_args() if not args.ip: print("ip is missing!") return 1 print(f"IP: {args.ip}") if args.command: print(f"Command: {args.command}") if args.command == 'get_system_state': mixer = Mixer(args.ip, MIXER_PORT) mixer.get_system_state() if __name__ == '__main__': main()