def initDMX(self): # configure Tinkerforge DMX try: self.ipcon.connect(HOST, PORT) # Register Enumerate Callback self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.cb_enumerate) # Trigger Enumerate self.ipcon.enumerate() # Likely wait for the tinkerforge brickd to finish doing its thing sleep(0.7) if DEBUG: print("Tinkerforge enumerated IDs", self.tfIDs) dmxcount = 0 for tf in self.tfIDs: if len( tf[0] ) <= 3: # if the device UID is 3 characters it is a bricklet if tf[1] in self.deviceIDs: if VERBOSE: print(tf[0], tf[1], self.getIdentifier(tf)) if tf[1] == 285: # DMX Bricklet if dmxcount == 0: print( "Registering %s as slave DMX device for playing DMX frames" % tf[0]) self.dmx = BrickletDMX(tf[0], self.ipcon) self.dmx.set_dmx_mode(self.dmx.DMX_MODE_MASTER) self.dmx.set_frame_duration(DMX_FRAME_DURATION) dmxcount += 1 if dmxcount < 1: if LIGHTING_MSGS: print("No DMX devices found.") except Exception as e: print( "Could not create connection to Tinkerforge DMX. DMX lighting is now disabled" ) print("Why: ", e) self.PLAY_DMX = False
def main(): global SRT_FILENAME, AUDIO_FILENAME, MAX_BRIGHTNESS, TICK_TIME, DEBUG, VERBOSE parser = argparse.ArgumentParser(description="LushRoom sound and light command-line player") # group = parser.add_mutually_exclusive_group() # group.add_argument("-v", "--verbose", action="store_true") # group.add_argument("-q", "--quiet", action="store_true") parser.add_argument("-s","--srt", default=SRT_FILENAME, help=".srt file name for lighting events") parser.add_argument("-a","--audio", default=AUDIO_FILENAME, help="audio file for sound stream") parser.add_argument("-b","--brightness", default=MAX_BRIGHTNESS, help="maximum brightness") parser.add_argument("-t","--time", default=TICK_TIME, help="time between events") args = parser.parse_args() print('args: ', args) print('args.srt: ', args.srt) SRT_FILENAME = args.srt # global ipcon ipcon.connect(HOST, PORT) # Register Enumerate Callback ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, cb_enumerate) # Trigger Enumerate ipcon.enumerate() sleep(2) if VERBOSE: print("tfIds: ", tfIDs) dmxcount = 0 for tf in tfIDs: # try: if True: # print(len(tf[0])) if len(tf[0])<=3: # if the device UID is 3 characters it is a bricklet if tf[1] in deviceIDs: print('printed tfIds: ', tf[0],tf[1], getIdentifier(tf)) if tf[1] == 285: # DMX Bricklet if dmxcount == 0: print("Registering %s as slave DMX device for capturing DMX frames" % tf[0]) dmx = BrickletDMX(tf[0], ipcon) dmx.set_dmx_mode(BrickletDMX.DMX_MODE_SLAVE) dmx.register_callback(BrickletDMX.CALLBACK_FRAME, dmxread_callback) dmx.set_frame_callback_config(False, False, True, False) signal.signal(signal.SIGINT, signal_handler) dmxcount += 1 while True: pass
for tf in tfIDs: # try: if True: # print(len(tf[0])) if len( tf[0] ) <= 3: # if the device UID is 3 characters it is a bricklet if tf[1] in deviceIDs: print(tf[0], tf[1], getIdentifier(tf)) if tf[1] == 285: # DMX Bricklet if dmxcount == 0: print( "Registering %s as slave DMX device for capturing DMX frames" % tf[0]) dmx = BrickletDMX(tf[0], ipcon) # dmx.set_dmx_mode(BrickletDMX.DMX_MODE_SLAVE) dmx.set_dmx_mode(dmx.DMX_MODE_MASTER) # dmx.register_callback(BrickletDMX.CALLBACK_FRAME, dmxread_callback) # dmx.set_frame_callback_config(False, False, True, False) signal.signal(signal.SIGINT, signal_handler) dmxcount += 1 # print(dir(dmx)) print("Time before running scheduler", time(), perf_counter()) for sub in subs: # print(dir(sub)) # print(sub.index, dir(sub.shift), sub.position, sub.split_timestamps) hours, minutes, seconds, milliseconds = time_convert(sub.start)
def main(): global subs, player, bridge, scheduler, ipcon, dmx global SRT_FILENAME, AUDIO_FILENAME, MAX_BRIGHTNESS, TICK_TIME, HUE_IP_ADDRESS, DEBUG, VERBOSE parser = argparse.ArgumentParser(description="LushRoom sound and light command-line player. \ Press Esc to exit, P to pause and R to resume.") group = parser.add_mutually_exclusive_group() group.add_argument("-v", "--verbose", action="store_true") group.add_argument("-q", "--quiet", action="store_true") parser.add_argument("-d", "--debug", action="store_true") parser.add_argument("-s","--srt", default=SRT_FILENAME, help=".srt file name for lighting events") parser.add_argument("-a","--audio", default=AUDIO_FILENAME, help="audio file for sound stream") parser.add_argument("-b","--brightness", default=MAX_BRIGHTNESS, help="maximum brightness") parser.add_argument("-t","--time", default=TICK_TIME, help="time between events") parser.add_argument("--hue", default=HUE_IP_ADDRESS, help="Philips Hue bridge IP address") args = parser.parse_args() MAX_BRIGHTNESS = int(args.brightness) SRT_FILENAME = args.srt AUDIO_FILENAME = args.audio TICK_TIME = float(args.time) HUE_IP_ADDRESS = args.hue VERBOSE = args.verbose DEBUG = args.debug if DEBUG: print(args) ipcon.connect(HOST, PORT) # Register Enumerate Callback ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, cb_enumerate) # Trigger Enumerate ipcon.enumerate() sleep(2) if DEBUG: print(tfIDs) dmxcount = 0 for tf in tfIDs: # try: if True: # print(len(tf[0])) if len(tf[0])<=3: # if the device UID is 3 characters it is a bricklet if tf[1] in deviceIDs: if VERBOSE: print(tf[0],tf[1], getIdentifier(tf)) if tf[1] == 285: # DMX Bricklet if dmxcount == 0: print("Registering %s as slave DMX device for capturing DMX frames" % tf[0]) dmx = BrickletDMX(tf[0], ipcon) dmx.set_dmx_mode(dmx.DMX_MODE_MASTER) # channels = int((int(MAX_BRIGHTNESS)/255.0)*ones(512,)*255) # dmx.write_frame([255,255]) sleep(1) # channels = int((int(MAX_BRIGHTNESS)/255.0)*zeros(512,)*255) # dmx.write_frame(channels) dmxcount += 1 if PLAY_AUDIO: player = vlc.MediaPlayer(AUDIO_FILENAME) event_manager = player.event_manager() event_manager.event_attach(vlc.EventType.MediaPlayerEndReached, end_callback) if PLAY_HUE: # b = Bridge('lushroom-hue.local') bridge = Bridge(HUE_IP_ADDRESS) # If the app is not registered and the button is not pressed, press the button and call connect() (this only needs to be run a single time) bridge.connect() # Get the bridge state (This returns the full dictionary that you can explore) bridge.get_api() lights = bridge.lights # Print light names for l in lights: print(l.name) #print(dir(l)) for l in lights: # print(dir(l)) l.on = False sleep(1) for l in lights: l.on = True l.brightness = MAX_BRIGHTNESS # Get a dictionary with the light name as the key light_names = bridge.get_light_objects('name') print("Light names:", light_names) subs = srtopen(SRT_FILENAME) print("Number of lighting events",len(subs)) # print("PLAY_HUE", PLAY_HUE) scheduler = BackgroundScheduler() scheduler.add_job(tick, 'interval', seconds=TICK_TIME, misfire_grace_time=10, max_instances=4096, coalesce=True) if PLAY_AUDIO: player.play() scheduler.start(paused=False) with keyboard.Listener( # on_press=on_press, on_release=on_release, suppress=False) as listener: try: listener.join() except ExitException as e: print("Exiting ...")
#!/usr/bin/env python # -*- coding: utf-8 -*- HOST = "localhost" PORT = 4223 UID = "XYZ" # Change XYZ to the UID of your DMX Bricklet from tinkerforge.ip_connection import IPConnection from tinkerforge.bricklet_dmx import BrickletDMX if __name__ == "__main__": ipcon = IPConnection() # Create IP connection dmx = BrickletDMX(UID, ipcon) # Create device object ipcon.connect(HOST, PORT) # Connect to brickd # Don't use device before ipcon is connected # Configure Bricklet as DMX master dmx.set_dmx_mode(dmx.DMX_MODE_MASTER) # Write DMX frame with 3 channels dmx.write_frame([255, 128, 0]) input("Press key to exit\n") # Use raw_input() in Python 2 ipcon.disconnect()
def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) self.setWindowTitle('DMX Test Tool by LauerSystems') # create and setup ipcon self.ipcon = IPConnection() self.ipcon.connect(HOST, PORT) self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_ipcon_enumerate.emit) self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_ipcon_connected.emit) self.dmx = BrickletDMX(UID_DMX, self.ipcon) self.label_image.setText("Started!") #Configs self.wait_for_first_read = True self.qtcb_frame_started.connect(self.cb_frame_started) self.qtcb_frame.connect(self.cb_frame) self.dmx.set_dmx_mode(BrickletDMX.DMX_MODE_MASTER) print("DMX Mode [0=Master; 1=Slave]: " + str(self.dmx.get_dmx_mode())) self.dmx.set_frame_duration(200) print("Frame Duration [ms]: " + str(self.dmx.get_frame_duration())) self.address_spinboxes = [] self.address_slider = [] print("Config Ende") for i in range(20): spinbox = QSpinBox() spinbox.setMinimum(0) spinbox.setMaximum(255) slider = QSlider(Qt.Horizontal) slider.setMinimum(0) slider.setMaximum(255) spinbox.valueChanged.connect(slider.setValue) slider.valueChanged.connect(spinbox.setValue) def get_frame_value_changed_func(i): return lambda x: self.frame_value_changed(i, x) slider.valueChanged.connect(get_frame_value_changed_func(i)) self.address_table.setCellWidget(i, 0, spinbox) self.address_table.setCellWidget(i, 1, slider) self.address_spinboxes.append(spinbox) self.address_slider.append(slider) print("Erzeuge Set: " + str(i)) self.address_table.horizontalHeader().setStretchLastSection(True) self.address_table.show() self.current_frame = [0] * 512 print(self.current_frame) self.dmx.register_callback(self.dmx.CALLBACK_FRAME_STARTED, self.qtcb_frame_started.emit) self.dmx.register_callback(self.dmx.CALLBACK_FRAME, self.qtcb_frame.emit) self.dmx.set_frame_callback_config(True, False, True, False)
class MainWindow(QMainWindow, Ui_MainWindow): qtcb_ipcon_enumerate = pyqtSignal(str, str, 'char', type((0, )), type( (0, )), int, int) qtcb_ipcon_connected = pyqtSignal(int) qtcb_frame_started = pyqtSignal() qtcb_frame = pyqtSignal(object, int) def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) self.setWindowTitle('DMX Test Tool by LauerSystems') # create and setup ipcon self.ipcon = IPConnection() self.ipcon.connect(HOST, PORT) self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_ipcon_enumerate.emit) self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_ipcon_connected.emit) self.dmx = BrickletDMX(UID_DMX, self.ipcon) self.label_image.setText("Started!") #Configs self.wait_for_first_read = True self.qtcb_frame_started.connect(self.cb_frame_started) self.qtcb_frame.connect(self.cb_frame) self.dmx.set_dmx_mode(BrickletDMX.DMX_MODE_MASTER) print("DMX Mode [0=Master; 1=Slave]: " + str(self.dmx.get_dmx_mode())) self.dmx.set_frame_duration(200) print("Frame Duration [ms]: " + str(self.dmx.get_frame_duration())) self.address_spinboxes = [] self.address_slider = [] print("Config Ende") for i in range(20): spinbox = QSpinBox() spinbox.setMinimum(0) spinbox.setMaximum(255) slider = QSlider(Qt.Horizontal) slider.setMinimum(0) slider.setMaximum(255) spinbox.valueChanged.connect(slider.setValue) slider.valueChanged.connect(spinbox.setValue) def get_frame_value_changed_func(i): return lambda x: self.frame_value_changed(i, x) slider.valueChanged.connect(get_frame_value_changed_func(i)) self.address_table.setCellWidget(i, 0, spinbox) self.address_table.setCellWidget(i, 1, slider) self.address_spinboxes.append(spinbox) self.address_slider.append(slider) print("Erzeuge Set: " + str(i)) self.address_table.horizontalHeader().setStretchLastSection(True) self.address_table.show() self.current_frame = [0] * 512 print(self.current_frame) self.dmx.register_callback(self.dmx.CALLBACK_FRAME_STARTED, self.qtcb_frame_started.emit) self.dmx.register_callback(self.dmx.CALLBACK_FRAME, self.qtcb_frame.emit) self.dmx.set_frame_callback_config(True, False, True, False) def frame_value_changed(self, line, value): self.current_frame[line] = value print("Value Changed") print(self.current_frame) self.dmx.write_frame(self.current_frame) #self.dmx_overview.draw_line(line, value, None, True) def mode_changed(self, index, update=True): if index == 0: for spinbox in self.address_spinboxes: spinbox.setReadOnly(False) for slider in self.address_slider: slider.setEnabled(True) self.frame_duration_label.setVisible(True) self.frame_duration_unit.setVisible(True) self.frame_duration_spinbox.setVisible(True) else: for spinbox in self.address_spinboxes: spinbox.setReadOnly(True) for slider in self.address_slider: slider.setEnabled(False) self.frame_duration_label.setVisible(False) self.frame_duration_unit.setVisible(False) self.frame_duration_spinbox.setVisible(False) if update: self.dmx.set_dmx_mode(index) def frame_duration_changed(self, value): self.dmx.set_frame_duration(value) def handle_new_frame(self, frame): for i, value in enumerate(frame): self.address_spinboxes[i].setValue(value) self.frame_value_changed(i, value) self.wait_for_first_read = False def cb_get_frame_duration(self, frame_duration): self.frame_duration_spinbox.blockSignals(True) self.frame_duration_spinbox.setValue(frame_duration) self.frame_duration_spinbox.blockSignals(False) def cb_get_dmx_mode(self, mode): self.mode_combobox.blockSignals(True) self.mode_combobox.setCurrentIndex(mode) self.mode_changed(mode, False) self.mode_combobox.blockSignals(False) if mode == self.dmx.DMX_MODE_MASTER: self.dmx.read_frame, None, self.cb_read_frame, self.increase_error_count def cb_read_frame(self, frame): self.handle_new_frame(frame.frame) def cb_frame_started(self): if not self.wait_for_first_read: self.dmx.write_frame, self.current_frame, None, self.increase_error_count def cb_frame(self, frame, frame_number): if frame == None: return self.handle_new_frame(frame) def cb_ipcon_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if self.ipcon.get_connection_state( ) != IPConnection.CONNECTION_STATE_CONNECTED: # ignore enumerate callbacks that arrived after the connection got closed return def cb_ipcon_connected(self, connect_reason): try: self.ipcon.enumerate() except: pass
class LushRoomsLighting(): def __init__(self): print('Lushroom Lighting init!') self.PLAY_HUE = True self.PLAY_DMX = True self.TRANSITION_TIME = 5 # milliseconds self.hue_list = [[]] self.player = None self.scheduler = None self.dmx_interpolator = DmxInterpolator() # 'last_played' seems to be the last numbered lighting event # in the SRT file self.last_played = 0 self.subs = "" # Hue self.bridge = None # DMX self.dmx = None self.tfIDs = [] self.ipcon = IPConnection() self.deviceIDs = [i[0] for i in deviceIdentifiersList] if self.PLAY_DMX: self.initDMX() if self.PLAY_HUE: self.initHUE() def emptyDMXFrame(self): return zeros((512, ), dtype=int) # Tinkerforge sensors enumeration def cb_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): self.tfIDs.append([uid, device_identifier]) ############################### LIGHTING FUNCTION METHODS def initDMX(self): # configure Tinkerforge DMX try: self.ipcon.connect(HOST, PORT) # Register Enumerate Callback self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.cb_enumerate) # Trigger Enumerate self.ipcon.enumerate() # Likely wait for the tinkerforge brickd to finish doing its thing sleep(0.7) if DEBUG: print("Tinkerforge enumerated IDs", self.tfIDs) dmxcount = 0 for tf in self.tfIDs: if len( tf[0] ) <= 3: # if the device UID is 3 characters it is a bricklet if tf[1] in self.deviceIDs: if VERBOSE: print(tf[0], tf[1], self.getIdentifier(tf)) if tf[1] == 285: # DMX Bricklet if dmxcount == 0: print( "Registering %s as slave DMX device for playing DMX frames" % tf[0]) self.dmx = BrickletDMX(tf[0], self.ipcon) self.dmx.set_dmx_mode(self.dmx.DMX_MODE_MASTER) self.dmx.set_frame_duration(DMX_FRAME_DURATION) dmxcount += 1 if dmxcount < 1: if LIGHTING_MSGS: print("No DMX devices found.") except Exception as e: print( "Could not create connection to Tinkerforge DMX. DMX lighting is now disabled" ) print("Why: ", e) self.PLAY_DMX = False def resetDMX(self): print("Directly resetting DMX...") if self.dmx: self.dmx.write_frame([ int(0.65 * MAX_BRIGHTNESS), int(0.40 * MAX_BRIGHTNESS), int(0.40 * MAX_BRIGHTNESS), int(0.40 * MAX_BRIGHTNESS), int(0.40 * MAX_BRIGHTNESS), int(0.40 * MAX_BRIGHTNESS), int(0.40 * MAX_BRIGHTNESS), int(0.40 * MAX_BRIGHTNESS), int(0.40 * MAX_BRIGHTNESS), 0, 0, 0, int(0.40 * MAX_BRIGHTNESS) ]) else: logging.error("Could not connect to DMX daemon to reset!") def initHUE(self): try: if self.PLAY_HUE: HUE_IP_ADDRESS = find_hue.hue_ip() if HUE_IP_ADDRESS == None: print("HUE disabled in settings.json, HUE is now disabled") self.PLAY_HUE = False return self.bridge = Bridge(HUE_IP_ADDRESS, config_file_path="/media/usb/python_hue") # If the app is not registered and the button is not pressed, press the button and call connect() (this only needs to be run a single time) self.bridge.connect() # Get the bridge state (This returns the full dictionary that you can explore) self.bridge.get_api() self.resetHUE() lights = self.bridge.lights self.hue_list = self.hue_build_lookup_table(lights) if LIGHTING_MSGS: # Get a dictionary with the light name as the key light_names = self.bridge.get_light_objects('name') print("Light names:", light_names) print(self.hue_list) except Exception as e: print( "Could not create connection to Hue. Hue lighting is now disabled" ) print("Error: ", e) self.PLAY_HUE = False def resetHUE(self): if self.PLAY_HUE: for l in self.bridge.lights: # print(dir(l)) l.on = True # Print light names # Set brightness of each light to 100 for l in self.bridge.lights: if LIGHTING_MSGS: print(l.name) l.brightness = 50 ##l.colormode = 'ct' #l.colortemp_k = 2700 #l.saturation = 0 bri = 50 sat = 100 hue = 0 colortemp = 450 cmd = { 'transitiontime': int(self.TRANSITION_TIME), 'on': True, 'bri': int(bri), 'sat': int(sat), 'hue': int(hue), 'ct': colortemp } self.bridge.set_light(l.light_id, cmd) ############################### LOW LEVEL LIGHT METHODS def getIdentifier(self, ID): deviceType = "" for t in range(len(self.deviceIDs)): if ID[1] == deviceIdentifiersList[t][0]: deviceType = deviceIdentifiersList[t][1] return (deviceType) # tick() # callback that runs at every tick of the apscheduler def tick(self): # Leaving the comments below in for Francesco, they could be part of # a mysterious but useful debug strategy # try: if True: # print(subs[0]) t = perf_counter() # ts = str(timedelta(seconds=t)).replace('.',',') # tsd = str(timedelta(seconds=t+10*TICK_TIME)).replace('.',',') ts = SubRipTime(seconds=t) tsd = SubRipTime(seconds=t + (1 * TICK_TIME)) # print(dir(player)) try: pp = self.player.getPosition() except Exception as e: print( "Could not get the current position of the player, shutting down lighting gracefully..." ) logging.error(e) self.__del__() #ptms = player.get_time()/1000.0 #pt = SubRipTime(seconds=(player.get_time()/1000.0)) #ptd = SubRipTime(seconds=(player.get_time()/1000.0+1*TICK_TIME)) pt = SubRipTime(seconds=pp) ptd = SubRipTime(seconds=(pp + 1 * TICK_TIME)) if DEBUG: #print('Time: %s | %s | %s - %s | %s - %s | %s | %s' % (datetime.now(),t,ts,tsd,pt,ptd,pp,ptms)) # print('Time: %s | %s | %s | %s | %s | %s | %s ' % (datetime.now(),t,ts,tsd,pp,pt,ptd)) pass ## sub, i = self.find_subtitle(subs, ts, tsd) # sub, i = self.find_subtitle(self.subs, pt, ptd) sub, i = self.find_subtitle(self.subs, pt, ptd, lo=self.last_played) if DEBUG: print(i, "Found Subtitle for light event:", sub, i) ## hours, minutes, seconds, milliseconds = time_convert(sub.start) ## t = seconds + minutes*60 + hours*60*60 + milliseconds/1000.0 if sub != "": #and i > self.last_played: if LIGHTING_MSGS and DEBUG: print(i, "Light event:", sub) # print("Trigger light event %s" % i) self.trigger_light(sub) self.last_played = i if DEBUG: print('last_played: ', i) pod_mode = MENU_DMX_VAL != None if self.dmx_interpolator.isRunning() and pod_mode is False: if self.PLAY_DMX: if self.dmx != None: iFrame = self.dmx_interpolator.getInterpolatedFrame(pt) self.dmx.write_frame(iFrame) # except Exception as e: # print('ERROR: It is likely the connection to the audio player has been severed...') # print('Why? --> ', e) # print('Scheduler is about to end gracefully...') # self.__del__() # except: # pass def find_subtitle(self, subtitle, from_t, to_t, lo=0, backwards=False): i = lo if backwards and SEEK_EVENT_LOG: print("searching backwards!") if DEBUG and VERBOSE: pass # print("Starting from subtitle", lo, from_t, to_t, len(subtitle)) # Find where we are subLen = len(subtitle) while (i < subLen): if (subtitle[i].start >= to_t and not backwards): break if backwards and (subtitle[i].start >= from_t): previous_i = max(0, i - 1) if SEEK_EVENT_LOG: print("In subs, at:", previous_i, " found: ", subtitle[previous_i].text) return subtitle[previous_i].text, previous_i # if (from_t >= subtitle[i].start) & (fro m_t <= subtitle[i].end): if (subtitle[i].start >= from_t) & (to_t >= subtitle[i].start): # print(subtitle[i].start, from_t, to_t) if not self.dmx_interpolator.isRunning(): self.dmx_interpolator.findNextEvent(i, subtitle) return subtitle[i].text, i i += 1 return "", i def end_callback(self, event): if LIGHTING_MSGS: print('End of media stream (event %s)' % event.type) exit(0) def hue_build_lookup_table(self, lights): if DEBUG: print("hue lookup lights: ", lights) hue_l = [[]] i = 0 for j in range(1 + len(lights) + 1): for l in lights: #print(dir(l)) #lname = "lamp "+l.name+" " lname = str(l.name) #print(lname) #print("testing", str(j), lname.find(str(i)), len(hue), l.name.find(str(i)), l.light_id, l.name, l.bridge.ip, l.bridge.name, str(i+1)) if lname.find(str(j)) >= 0: #if str(i) in lname: if LIGHTING_MSGS: print(j, lname.find(str(j)), l.light_id, l.name, l.bridge.ip, l.bridge.name) if len(hue_l) <= j: hue_l.append([l.light_id]) else: hue_l[j].append(l.light_id) i += 1 if DEBUG: print("hue_l: ", hue_l) return (hue_l) def trigger_light(self, subs): global MAX_BRIGHTNESS, DEBUG if DEBUG: print("perf_count: ", perf_counter(), subs) commands = str(subs).split(";") if DEBUG: print("Trigger light", self.hue_list) for command in commands: try: # if True: # print(command) if DEBUG: print(command[0:len(command) - 1].split("(")) scope, items = command[0:len(command) - 1].split("(") if DEBUG: print("sc: ", scope, "it: ", items) if scope[0:3] == "HUE" and self.PLAY_HUE: l = int(scope[3:]) #print(l) if VERBOSE: print(self.hue_list[l]) hue, sat, bri, TRANSITION_TIME = items.split(',') # print(perf_counter(), l, items, hue, sat, bri, TRANSITION_TIME) bri = int((float(bri) / 255.0) * int(MAX_BRIGHTNESS)) # print(bri) cmd = { 'transitiontime': int(self.TRANSITION_TIME), 'on': True, 'bri': int(bri), 'sat': int(sat), 'hue': int(hue) } if LIGHTING_MSGS: print("Trigger HUE", l, cmd) if self.PLAY_HUE: #lights = bridge.lights #for light in lights: # print(light.name) # if light.name.find(str(l)): # light.brightness = bri # light.hue = hue #lights[l].brightness = bri #lights[l].saturation = sat #lights[l].hue = hue for hl in self.hue_list[l]: self.bridge.set_light(hl, cmd) if scope[0:3] == "DMX": l = int(scope[3:]) if items == "": print( "Empty DMX event found! Turning all DMX channels off..." ) channels = self.emptyDMXFrame() else: # channels = int(int(MAX_BRIGHTNESS)/255.0*(array(items.split(",")).astype(int))) channels = array(items.split(",")).astype(int) # channels = array(map(lambda i: int(MAX_BRIGHTNESS)*i, channels)) if LIGHTING_MSGS: print("Trigger DMX:", l, channels) if self.PLAY_DMX: if self.dmx != None: self.dmx.write_frame(channels) except: pass if LIGHTING_MSGS and DEBUG: print(30 * '-') ############################### PLAYER FUNCTION METHODS def time_convert(self, t): block, milliseconds = str(t).split(",") hours, minutes, seconds = block.split(":") return (int(hours), int(minutes), int(seconds), int(milliseconds)) def start(self, audioPlayer, subs): self.player = audioPlayer self.subs = subs self.dmx_interpolator.__init__() subs_length = len(self.subs) if subs is not None: if LIGHTING_MSGS: print("Lighting: Start!") print('AudioPlayer: ', self.player) print("Number of lighting events: ", subs_length) # Trigger the first lighting event before the scheduler event starts self.triggerPreviousEvent(0) self.last_played = 0 if subs_length == 1: if LIGHTING_MSGS: print( "There's only 1 lighting event, so no need to start the scheduler and unleash hell..." ) elif subs_length > 1: # start lighting scheduler self.scheduler = BackgroundScheduler({ 'apscheduler.executors.processpool': { 'type': 'processpool', 'max_workers': '10' } }) self.scheduler.add_job(self.tick, 'interval', seconds=TICK_TIME, misfire_grace_time=None, max_instances=16, coalesce=True) # This could be the cause of the _very_ first event, after a cold boot, not triggering correctly: self.scheduler.start(paused=False) if LIGHTING_MSGS: print("-------------") else: print( 'Subtitle track not found/empty subtitle track. Lighting is now disabled' ) def playPause(self, status): print('Lighting PlayPause: ', status) if status == "Paused": self.scheduler.pause() elif status == "Playing": self.scheduler.resume() if LIGHTING_MSGS: print("-------------") def fadeDown(self, status): print("Lighting: fadeDown") # self.scheduler.shutdown() self.last_played = 0 if status == "Paused": self.scheduler.pause() elif status == "Playing": self.scheduler.resume() if LIGHTING_MSGS: print("-------------") def exit(self): self.__del__() def triggerPreviousEvent(self, pos): if LIGHTING_MSGS: print("Finding last lighting command from pos: ", pos) pp = pos pt = SubRipTime(seconds=pp) ptd = SubRipTime(seconds=(pp + 1 * TICK_TIME)) if VERBOSE and DEBUG: print("Finding last light event, starting from: ") print("pt: ", ptd) print("ptd: ", ptd) sub, i = self.find_subtitle(self.subs, pt, ptd, backwards=True) if LIGHTING_MSGS: print("Seeking, found sub:", sub, " at pos: ", i) if sub != "": #and i > self.last_played: if LIGHTING_MSGS and DEBUG: print(i, "Found last lighting event!:", sub) # print("Trigger light event %s" % i) self.trigger_light(sub) self.last_played = i if DEBUG: print('last_played: ', i) def seek(self, pos): # This doesn't seem to work fully... # But may be solved by LUSHDigital/lrpi_player#116 # Get the last DMX and HUE events after a seek # Then trigger that... self.dmx_interpolator.__init__() self.triggerPreviousEvent(pos) def __del__(self): try: print("ipcon: ", self.ipcon) if self.scheduler: logging.info("Shutting down scheduler...") self.scheduler.shutdown() logging.info("Disconnecting from tinkerforge...") self.ipcon.disconnect() self.dmx = None self.ipcon = None except Exception as e: print('Lighting destructor failed: ', e) if LIGHTING_MSGS: print("Lighting died!")
def main(): global hue_list, bridge, SRT_FILENAME, HUE_IP_ADDRESS, MAX_BRIGHTNESS global DMX_INTERVAL, INTERVAL, TRANSITION_TIME, HUE_IP_ADDRESS, DEBUG, VERBOSE global subs, srtFile global ipcon, tfIDs, dmx f1 = Figlet(font='standard') print(f1.renderText('LushRoom')) f2 = Figlet(font='standard') print(f2.renderText('OSC live record')) parser = argparse.ArgumentParser() parser.add_argument("--ip", default="127.0.0.1", help="OSC ip address to listen to") parser.add_argument("--port", type=int, default=8000, help="OSC port to listen to") parser.add_argument("-s", "--srt", default=SRT_FILENAME, help=".srt file name for lighting events") parser.add_argument("-b", "--brightness", default=MAX_BRIGHTNESS, help="maximum brightness") parser.add_argument("-i", "--interval", default=INTERVAL, help="sampling interval for Philips Hue events") parser.add_argument("-d", "--dmx_interval", default=DMX_INTERVAL, help="sampling interval for DMX events") parser.add_argument("-t", "--transition_time", default=TRANSITION_TIME, help="transition time between Philips Hue events") parser.add_argument("--hue", default=HUE_IP_ADDRESS, help="Philips Hue bridge IP address") args = parser.parse_args() print(args) MAX_BRIGHTNESS = int(args.brightness) SRT_FILENAME = args.srt INTERVAL = float(args.interval) DMX_INTERVAL = float(args.dmx_interval) TRANSITION_TIME = float(args.transition_time) HUE_IP_ADDRESS = args.hue # VERBOSE = args.verbose # DEBUG = args.debug if SRT_FILENAME != "": print("Start recording the %s subtitles track for light events." % SRT_FILENAME) srtFile = SubRipFile(path=SRT_FILENAME) if PLAY_HUE: bridge = Bridge(HUE_IP_ADDRESS) bridge.connect() bridge.get_api() lights = bridge.lights for l in lights: print(l.name) for l in lights: l.on = True l.brightness = MAX_BRIGHTNESS light_names = bridge.get_light_objects('name') print("Light names:", light_names) if PLAY_HUE: hue_list = hue_build_lookup_table(lights) # else: # hue_list = [[0],['1'],[2],[3],[4],[5],[6],[7],[8],[9]] print(hue_list) if PLAY_DMX: ipcon.connect(HOST, PORT) # Register Enumerate Callback ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, cb_enumerate) # Trigger Enumerate ipcon.enumerate() sleep(2) if DEBUG: print(tfIDs) dmxcount = 0 for tf in tfIDs: # try: if True: # print(len(tf[0])) if len( tf[0] ) <= 3: # if the device UID is 3 characters it is a bricklet if tf[1] in deviceIDs: if VERBOSE: print(tf[0], tf[1], getIdentifier(tf)) if tf[1] == 285: # DMX Bricklet if dmxcount == 0: print( "Registering %s as slave DMX device for capturing DMX frames" % tf[0]) dmx = BrickletDMX(tf[0], ipcon) dmx.set_dmx_mode(dmx.DMX_MODE_MASTER) # channels = int((int(MAX_BRIGHTNESS)/255.0)*ones(512,)*255) # dmx.write_frame([255,255]) sleep(1) # channels = int((int(MAX_BRIGHTNESS)/255.0)*zeros(512,)*255) # dmx.write_frame(channels) dmxcount += 1 disp = dispatcher.Dispatcher() # print(dir(dispatcher)) for h in range(512): disp.map("/hue%s" % h, play_record_hue, "%s" % h) for h in range(512): disp.map("/dmx%s" % h, play_record_dmx, "%s" % h) server = osc_server.ThreadingOSCUDPServer((args.ip, args.port), disp) print("Serving OSC on {}".format(server.server_address)) signal.signal(signal.SIGINT, signal_handler) server.serve_forever()
dmxcount = 0 for tf in tfIDs: # try: if True: # print(len(tf[0])) if len( tf[0] ) <= 3: # if the device UID is 3 characters it is a bricklet if tf[1] in deviceIDs: print(tf[0], tf[1], getIdentifier(tf)) if tf[1] == 285: # DMX Bricklet if dmxcount == 0: print( "Registering %s as slave DMX device for capturing DMX frames" % tf[0]) dmx = BrickletDMX(tf[0], ipcon) dmx.set_dmx_mode(BrickletDMX.DMX_MODE_SLAVE) dmx.register_callback(BrickletDMX.CALLBACK_FRAME, dmxread_callback) dmx.set_frame_callback_config(True, True, True, True) dmxcount += 1 while True: pass if tfConnect: ipcon.disconnect()