#!/usr/bin/env python3 # -*- coding: utf-8 -*- """OscMacroDefinitions.py: Hog 4 comment macros in OSC for Python3.""" __author__ = "Kevin Matz" __copyright__ = "Copyright 2018, Company 235, LLC" __credits__ = ["Kevin Matz"] __license__ = "MIT" __version__ = "3.9" __maintainer__ = "Kevin Matz" __email__ = "kevin@company235.com" __status__ = "Prototype" import logging from pythonosc import udp_client from pythonosc import osc_message_builder from pythonosc import osc_bundle_builder from time import sleep logger = logging.getLogger("CommentMacro") class HogDevice(): # button state constants buttonDOWN = 1 buttonUP = 0 def __init__(self, servers): self.servers = servers def button_press(self, device, path, delay=0.05): self.send_message(device, path, HogDevice.buttonDOWN) # button down sleep(delay) self.send_message(device, path, HogDevice.buttonUP) # button up # utility function to send simple messages with one argument def send_message(self, device, path, arg): msg = osc_message_builder.OscMessageBuilder(address=path) msg.add_arg(arg) self.send(device, msg.build()) # send python-osc messages def send(self, device, msg): if device is None: osc = list(self.servers.values())[0] else: if (device.type != 'h'): logger.error("ERROR: Only Hog type devices are supported.") return else: try: osc = self.servers[device.number.value] except KeyError: logger.error("ERROR: Net# " + str(device.number.value) + " not found.") return try: osc.send(msg) except Exception as e: logger.error(e) def _master_go(self, ctx): if ctx.number is not None: logger.warn("GO MASTER doesn't support goto. " + "Cue number "+str(ctx.number.value)+" is ignored.") if (len(ctx.master.targets) == 0): logger.info("Main GO") self.osc.button_press(ctx.device, "/hog/hardware/maingo") return else: for i in ctx.master.targets: if isinstance(i, int) is not True: logger.warn("GO MASTER macro targets must be intigers. " + str(i) + " is not an intigers.") continue if (i < 0): logger.warn("Master "+str(i)+" is not greater than 0.") continue master = str(i) logger.info("GO on master " + master) self.osc.button_press(ctx.device, "/hog/hardware/go/" + master) def _master_halt(self, ctx): if (len(ctx.master.targets) == 0): logger.info("Main HALT") self.osc.button_press(ctx.device, "/hog/hardware/mainhalt") return else: for i in ctx.master.targets: if isinstance(i, int) is not True: logger.warn("GO MASTER macro targets must be intigers. " + str(i) + " is not an intigers.") continue if (i < 0): logger.warn("Master "+str(i)+" is not greater than 0.") continue master = str(i) logger.info("HALT on master " + master) self.osc.button_press(ctx.device, "/hog/hardware/pause/" + master) def _master_assert(self, ctx): if (len(ctx.master.targets) != 0): logger.error("ERROR: limited to asserting current master only.") return logger.info("ASSERT on current master.") self.osc.button_press(ctx.device, "/hog/hardware/assert") def _master_release(self, ctx): if (len(ctx.master.targets) != 0): logger.error("ERROR: limited to releasing current master only.") return logger.info("RELEASE on current master.") self.osc.button_press(ctx.device, "/hog/hardware/release") def _master_fade(self, ctx): if (ctx.number) is None: logger.error("ERROR: Missing required argument for LEVEL") return else: level = ctx.number.value if (level < 0 or level > 100): logger.error("Level must be between 0 and 100.") return if (len(ctx.master.targets) == 0): logger.error("MASTER FADE doesn't support * current master.") return else: for i in ctx.master.targets: if isinstance(i, int) is not True: logger.warn("FADE MASTER macro targets must be intigers. " + str(i) + " is not an intigers.") continue if (i < 0): logger.warn("Master "+str(i)+" is not greater than 0.") continue master = str(i) logger.info("Fade Master "+master+" to "+str(level)+"%") level *= 255 / 100 # percent in Macro, 0>255 in OSC self.osc.send_message(ctx.device, "/hog/hardware/fader/" + master, level) def _master_fade_grand(self, ctx): level = ctx.number.value if (level < 0 or level > 100): logger.error("Level must be between 0 and 100.") return logger.info("Fading Grand Master to " + str(level) + "%") level *= 255 / 100 # percent in Macro, 0>255 in OSC self.osc.send_message(ctx.device, "/hog/hardware/fader/0", level) def _master_choose(self, ctx): if (ctx.number.value < 0): logger.error("Master must be greater than 0.") return master = str(ctx.number.value) logger.info("Choose Master " + master) self.osc.button_press(ctx.device, "/hog/hardware/choose/" + master) def _release_all(self, ctx): logger.info("Release All") self.osc.send_message(ctx.device, "/hog/hardware/pig", HogDevice.buttonDOWN) self.osc.button_press(ctx.device, "/hog/hardware/release") self.osc.send_message(ctx.device, "/hog/hardware/pig", HogDevice.buttonUP) def _list_go(self, ctx): for i in ctx.targets: if ctx.number is not None: list = str(i) + "." + str(ctx.number.value) else: list = i logger.info("Go on List " + str(list)) self.osc.send_message(ctx.device, "/hog/playback/go/0", list) def _list_halt(self, ctx): for i in ctx.targets: logger.info("Halting List " + str(i)) self.osc.send_message(ctx.device, "/hog/playback/halt/0", i) def _list_release(self, ctx): for i in ctx.targets: logger.info("Releasing List " + str(i)) self.osc.send_message(ctx.device, "/hog/playback/release/0", i) def _scene_go(self, ctx): for i in ctx.targets: logger.info("Go on Scene " + str(i)) self.osc.send_message(ctx.device, "/hog/playback/go/1", i) def _scene_halt(self, ctx): for i in ctx.targets: logger.info("Halt Scene " + str(i)) self.osc.send_message(ctx.device, "/hog/playback/halt/1", i) def _scene_release(self, ctx): for i in ctx.targets: logger.info("Release Scene " + str(i)) self.osc.send_message(ctx.device, "/hog/playback/release/1", i) def _macro_go(self, ctx): for i in ctx.targets: logger.info("Go on Macro " + str(i)) self.osc.send_message(ctx.device, "/hog/playback/go/2", i) def _macro_halt(self, ctx): for i in ctx.targets: logger.info("Pause Macro " + str(i)) self.osc.send_message(ctx.device, "/hog/playback/halt/2", i) def _macro_release(self, ctx): for i in ctx.targets: logger.info("Stop Macro " + str(i)) self.osc.send_message(ctx.device, "/hog/playback/release/2", i) def _page_change(self, ctx): if ctx.number is not None: logger.error("ERROR: changing page by number is unsupported.") return dir = ctx.children[1].getText() if dir == '+': logger.info("Next Page") self.osc.button_press(ctx.device, "/hog/hardware/nextpage") elif dir == '-': logger.info("Previous Page") self.osc.button_press(ctx.device, "/hog/hardware/backpage") command = {"GM": _master_go, "HM": _master_halt, "AM": _master_assert, "RM": _master_release, "FM": _master_fade, "FGM": _master_fade_grand, "CM": _master_choose, "RA": _release_all, "GL": _list_go, "HL": _list_halt, "RL": _list_release, "GS": _scene_go, "HS": _scene_halt, "RS": _scene_release, "GK": _macro_go, "HK": _macro_halt, "RK": _macro_release, "CP": _page_change }