diff --git a/arrive_vidplybck.py b/arrive_vidplybck.py deleted file mode 100644 index 6503ad9..0000000 --- a/arrive_vidplybck.py +++ /dev/null @@ -1,154 +0,0 @@ -import gi -import struct -import os - -gi.require_version('Gst', '1.0') -from gi.repository import Gst, GLib - -class BrightnessManager: - def __init__(self): - self.backlight_path = "/sys/class/backlight/main_backlight/brightness" - self.led_multi_path = "/sys/class/leds/display-indicator/multi_intensity" - self.led_trig_path = "/sys/class/leds/display-indicator/trigger" - self.led_br_path = "/sys/class/leds/display-indicator/brightness" - - # Backlight state - self.bl_current = 10 - self.bl_direction = 1 # 1 for increasing, -1 for decreasing - - # Hex to RGB Tuples: 5F016F, FF33BB, FF80D4, FFADE4 - self.colors = [ - (95, 1, 111), # #5F016F - (255, 51, 187), # #FF33BB - (255, 128, 212),# #FF80D4 - (255, 173, 228) # #FFADE4 - ] - - self.color_index = 0 - - self.setup_led() - - def setup_led(self): - try: - with open(self.led_trig_path, 'w') as f: f.write("none") - with open(self.led_br_path, 'w') as f: f.write("255") - self.change_led_colour() - except Exception as e: - print(f"LED Setup Error: {e}") - - def change_led_colour(self): - r, g, b = self.colors[self.color_index] - - try: - with open(self.led_multi_path, 'w') as f: - f.write(f"{r} {g} {b}") - print(f"LED changed to color index {self.color_index}: {r} {g} {b}") - except Exception as e: - print(f"Failed to write LED color: {e}") - - # Increment index for next time - self.color_index = (self.color_index + 1) % len(self.colors) - return True # Keep GLib timer alive - - def cycle_backlight(self): - """Standard backlight cycle on touch""" - self.bl_current += self.bl_direction - if self.bl_current >= 20: - self.bl_current = 20 - self.bl_direction = -1 - elif self.bl_current <= 0: - self.bl_current = 0 - self.bl_direction = 1 - try: - with open(self.backlight_path, 'w') as f: - f.write(str(self.bl_current)) - print(f"Touch! Backlight: {self.bl_current}") - - except Exception as e: - print(f"Backlight Error: {e}") - -def handle_touch(source, condition, manager): - # Linux input_event struct: long, long, unsigned short, unsigned short, unsigned int - # We read 24 bytes (standard for 64-bit systems like i.MX8M) - EVENT_SIZE = 24 - data = source.read(EVENT_SIZE) - if len(data) < EVENT_SIZE: - return True - - # Unpack the binary data - # type (H), code (H), value (I) are the last 3 fields - _, _, ev_type, ev_code, ev_value = struct.unpack('qqHHI', data) - - # EV_KEY (1) and BTN_TOUCH (330). ev_value 1 is press, 0 is release. - # We trigger the change only on the 'press' (1) - if ev_type == 1 and ev_code == 330 and ev_value == 1: - manager.cycle_backlight() - - return True - -def play_kiosk_video(): - Gst.init(None) - - brightness_manager = BrightnessManager() - - VIDEO_PATH = "file:///root/python/vid.mp4" - - SINK_STR = ( - "videoconvert ! " - "video/x-raw,format=BGRx ! " - "kmssink driver-name=mxsfb-drm connector-id=37 plane-id=31 can-scale=false" ) - - # Create the playbin element - pipeline = Gst.ElementFactory.make("playbin", "player") - pipeline.set_property("uri", VIDEO_PATH) - - # Set the custom video sink - video_sink = Gst.parse_bin_from_description(SINK_STR, True) - pipeline.set_property("video-sink", video_sink) - - # Set audio to fakesink (prevents errors if no audio hardware is found) - audio_sink = Gst.ElementFactory.make("fakesink", "audio-fake") - pipeline.set_property("audio-sink", audio_sink) - - # --- INPUT MONITORING --- - try: - # Open the touch device in binary read mode - touch_fd = open("/dev/input/event2", "rb") - # Add to GLib loop so it doesn't block the video - GLib.io_add_watch(touch_fd, GLib.IO_IN, handle_touch, brightness_manager) - except FileNotFoundError: - print("Warning: /dev/input/event2 not found. Brightness control disabled.") - - GLib.timeout_add(30000, brightness_manager.change_led_colour) - - # --- LOOPING LOGIC --- - bus = pipeline.get_bus() - bus.add_signal_watch() - - def on_message(bus, msg): - t = msg.type - if t == Gst.MessageType.EOS: - print("End of video. Looping...") - pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0) - elif t == Gst.MessageType.ERROR: - err, debug = msg.parse_error() - print(f"Error: {err}") - loop.quit() - return True - - bus.connect("message", on_message) - - # Start playback - print(f"Starting playback: {VIDEO_PATH}") - pipeline.set_state(Gst.State.PLAYING) - - loop = GLib.MainLoop() - try: - loop.run() - except KeyboardInterrupt: - print("\nStopping player...") - finally: - pipeline.set_state(Gst.State.NULL) - -if __name__ == "__main__": - play_kiosk_video() diff --git a/display_test_nexio.py b/display_test_nexio.py new file mode 100644 index 0000000..562746a --- /dev/null +++ b/display_test_nexio.py @@ -0,0 +1,162 @@ +import gi +import struct +import os + +gi.require_version('Gst', '1.0') +from gi.repository import Gst, GLib + +class KioskManager: + def __init__(self, pipeline): + self.pipeline = pipeline + self.videos = [ + "file:///root/python/vid.mp4", + "file:///root/python/vid2.mp4" + ] + self.current_video_index = 0 + + # Hardware Paths + self.backlight_path = "/sys/class/backlight/main_backlight/brightness" + self.led_multi_path = "/sys/class/leds/display-indicator/multi_intensity" + self.led_trig_path = "/sys/class/leds/display-indicator/trigger" + self.led_br_path = "/sys/class/leds/display-indicator/brightness" + + # Backlight State + self.bl_current = 10 + self.bl_direction = 1 # 1 for increasing, -1 for decreasing + + # LED State + self.colors = [(95, 1, 111), (255, 51, 187), (255, 128, 212), (255, 173, 228)] + self.color_index = 0 + + self.setup_led() + + def setup_led(self): + try: + if os.path.exists(self.led_trig_path): + with open(self.led_trig_path, 'w') as f: f.write("none") + with open(self.led_br_path, 'w') as f: f.write("255") + self.change_led_colour() + except Exception as e: + print(f"LED Setup Error: {e}") + + def change_led_colour(self): + """Cycles the LED color""" + r, g, b = self.colors[self.color_index] + try: + if os.path.exists(self.led_multi_path): + with open(self.led_multi_path, 'w') as f: + f.write(f"{r} {g} {b}") + self.color_index = (self.color_index + 1) % len(self.colors) + except Exception as e: + print(f"Failed to write LED colour: {e}") + + def cycle_backlight(self): + """Touch Logic: Adjusts screen brightness and cycles LED""" + self.bl_current += self.bl_direction + if self.bl_current >= 20: + self.bl_current = 20 + self.bl_direction = -1 + elif self.bl_current <= 0: + self.bl_current = 0 + self.bl_direction = 1 + + try: + if os.path.exists(self.backlight_path): + with open(self.backlight_path, 'w') as f: + f.write(str(self.bl_current)) + print(f"Touch Event: Brightness now {self.bl_current}") + self.change_led_colour() # Visual feedback for touch + except Exception as e: + print(f"Backlight Error: {e}") + + def switch_video(self): + """Button Logic: Swaps between vid.mp4 and vid2.mp4""" + self.pipeline.set_state(Gst.State.READY) + self.current_video_index = (self.current_video_index + 1) % len(self.videos) + new_uri = self.videos[self.current_video_index] + + print(f"Physical Button: Swapping to {new_uri}") + self.pipeline.set_property("uri", new_uri) + self.pipeline.set_state(Gst.State.PLAYING) + +def handle_touch(source, condition, manager): + """Listens to /dev/input/event2""" + EVENT_SIZE = 24 + data = source.read(EVENT_SIZE) + if not data or len(data) < EVENT_SIZE: + return True + + _, _, ev_type, ev_code, ev_value = struct.unpack('qqHHI', data) + + # EV_KEY (1) and BTN_TOUCH (330), value 1 is Press + if ev_type == 1 and ev_code == 330 and ev_value == 1: + manager.cycle_backlight() + return True + +def handle_button(source, condition, manager): + """Listens to /dev/input/event1""" + EVENT_SIZE = 24 + data = source.read(EVENT_SIZE) + if not data or len(data) < EVENT_SIZE: + return True + + _, _, ev_type, ev_code, ev_value = struct.unpack('qqHHI', data) + + # EV_KEY (1), value 1 is Press + # Note: We don't check ev_code 330 here, as it's a physical button + if ev_type == 1 and ev_value == 1: + manager.switch_video() + return True + +def play_kiosk(): + Gst.init(None) + pipeline = Gst.ElementFactory.make("playbin", "player") + + SINK_STR = ("videoconvert ! video/x-raw,format=BGRx ! " + "kmssink driver-name=mxsfb-drm connector-id=37 plane-id=31 can-scale=false") + video_sink = Gst.parse_bin_from_description(SINK_STR, True) + pipeline.set_property("video-sink", video_sink) + pipeline.set_property("audio-sink", Gst.ElementFactory.make("fakesink")) + + manager = KioskManager(pipeline) + pipeline.set_property("uri", manager.videos[0]) + + # --- INPUT ASSIGNMENT --- + try: + # Physical Button assigned to event1 + btn_fd = open("/dev/input/event1", "rb") + GLib.io_add_watch(btn_fd, GLib.IO_IN, handle_button, manager) + except Exception as e: print(f"Button Node Error: {e}") + + try: + # Touchscreen assigned to event2 + tch_fd = open("/dev/input/event2", "rb") + GLib.io_add_watch(tch_fd, GLib.IO_IN, handle_touch, manager) + except Exception as e: print(f"Touch Node Error: {e}") + + # --- LOOPING LOGIC --- + bus = pipeline.get_bus() + bus.add_signal_watch() + + def on_message(bus, msg, manager_instance): + if msg.type == Gst.MessageType.EOS: + # Video ended, cycle LED and loop back to start + manager_instance.change_led_colour() + pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0) + elif msg.type == Gst.MessageType.ERROR: + err, debug = msg.parse_error() + print(f"GStreamer Error: {err}") + loop.quit() + return True + + bus.connect("message", on_message, manager) + + pipeline.set_state(Gst.State.PLAYING) + loop = GLib.MainLoop() + try: + loop.run() + except KeyboardInterrupt: + pipeline.set_state(Gst.State.NULL) + +if __name__ == "__main__": + play_kiosk() \ No newline at end of file