#!/usr/bin/env python3 """ Demo: Accelerometer-based Page Flipping This example demonstrates how to use the accelerometer for hands-free page turning by tilting the device forward or backward. Features: - Tilt device forward to advance to next page - Tilt device backward to go to previous page - Touch gestures still work normally - Configurable tilt threshold and debounce time Prerequisites: 1. Run calibration first: python examples/calibrate_accelerometer.py 2. This creates accelerometer_config.json with calibration data Usage: python examples/demo_accelerometer_page_flip.py """ import asyncio import sys from pathlib import Path # Add parent directory to path for imports sys.path.insert(0, str(Path(__file__).parent.parent)) from dreader.hal_hardware import HardwareDisplayHAL from dreader.application import EbookReader from dreader.gesture import GestureType class AccelerometerPageFlipDemo: """Demo application with accelerometer-based page flipping""" def __init__(self, epub_path: str): self.epub_path = epub_path # Create HAL with accelerometer enabled print("Initializing hardware HAL...") self.hal = HardwareDisplayHAL( width=1872, height=1404, enable_orientation=True, enable_rtc=False, enable_power_monitor=False, virtual_display=False # Set to True for testing without hardware ) # Create reader print("Creating ebook reader...") self.reader = EbookReader( page_size=(self.hal.width, self.hal.height), margin=60 ) self.running = False async def run(self): """Run the demo application""" print("\n" + "="*60) print("Accelerometer Page Flip Demo") print("="*60) # Initialize HAL await self.hal.initialize() # Load accelerometer calibration print("\nLoading accelerometer calibration...") calibrated = self.hal.load_accelerometer_calibration("accelerometer_config.json") if not calibrated: print("\nWARNING: Accelerometer not calibrated!") print("Please run: python examples/calibrate_accelerometer.py") print("\nProceeding with touch gestures only...\n") else: print("Accelerometer calibration loaded successfully!") print(f" Up vector: {self.hal.accel_up_vector}") print(f" Tilt threshold: {self.hal.accel_tilt_threshold:.2f} rad") print(f" Debounce time: {self.hal.accel_debounce_time:.2f}s") # Load EPUB print(f"\nLoading EPUB: {self.epub_path}") success = self.reader.load_epub(self.epub_path) if not success: print(f"ERROR: Failed to load {self.epub_path}") await self.hal.cleanup() return print(f"Loaded: {self.reader.book_title}") print(f"Author: {self.reader.book_author}") # Display first page print("\nDisplaying first page...") img = self.reader.get_current_page() await self.hal.show_image(img) # Instructions print("\n" + "="*60) print("Controls:") print(" - Tilt FORWARD to go to next page") print(" - Tilt BACKWARD to go to previous page") print(" - Swipe LEFT for next page (touch)") print(" - Swipe RIGHT for previous page (touch)") print(" - Long press to exit") print("="*60 + "\n") # Main event loop self.running = True try: await self.event_loop() finally: await self.hal.cleanup() print("\nDemo finished!") async def event_loop(self): """Main event loop - poll for touch and accelerometer events""" accel_poll_interval = 0.05 # Check accelerometer every 50ms while self.running: # Check for touch events touch_event = await self.hal.get_touch_event() if touch_event: await self.handle_event(touch_event) # Check for accelerometer tilt events (if calibrated) if hasattr(self.hal, 'accel_up_vector'): tilt_event = await self.hal.get_tilt_gesture() if tilt_event: await self.handle_event(tilt_event) # Small delay to avoid busy-waiting await asyncio.sleep(accel_poll_interval) async def handle_event(self, event): """Handle a gesture event (touch or accelerometer)""" gesture = event.gesture print(f"Gesture: {gesture.value}") # Navigation gestures if gesture in [GestureType.SWIPE_LEFT, GestureType.TILT_FORWARD]: await self.next_page() elif gesture in [GestureType.SWIPE_RIGHT, GestureType.TILT_BACKWARD]: await self.previous_page() # Exit on long press elif gesture == GestureType.LONG_PRESS: print("\nLong press detected - exiting...") self.running = False # Word tap elif gesture == GestureType.TAP: # You could implement word selection here print(f" Tap at ({event.x}, {event.y})") async def next_page(self): """Go to next page""" img = self.reader.next_page() if img: progress = self.reader.get_reading_progress() chapter = self.reader.get_current_chapter_info() print(f" -> Next page ({progress['percent']:.1f}% - {chapter['title']})") await self.hal.show_image(img) else: print(" -> At end of book") async def previous_page(self): """Go to previous page""" img = self.reader.previous_page() if img: progress = self.reader.get_reading_progress() chapter = self.reader.get_current_chapter_info() print(f" -> Previous page ({progress['percent']:.1f}% - {chapter['title']})") await self.hal.show_image(img) else: print(" -> At start of book") async def main(): """Main entry point""" if len(sys.argv) < 2: print("Usage: python demo_accelerometer_page_flip.py ") print("\nExample:") print(" python demo_accelerometer_page_flip.py ~/Books/mybook.epub") sys.exit(1) epub_path = sys.argv[1] # Check if file exists if not Path(epub_path).exists(): print(f"ERROR: File not found: {epub_path}") sys.exit(1) # Run demo demo = AccelerometerPageFlipDemo(epub_path) await demo.run() if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: print("\nDemo interrupted by user") sys.exit(0) except Exception as e: print(f"\nError: {e}") import traceback traceback.print_exc() sys.exit(1)