From e336fc4b9d909b74c694fbe31c6c6646e1b702e5 Mon Sep 17 00:00:00 2001 From: 9and3r <9and3r@gmail.com> Date: Fri, 8 Aug 2014 11:20:31 +0200 Subject: [PATCH] First support for GPIO on Raspberry Pi --- mopidy_touchscreen/__init__.py | 1 + mopidy_touchscreen/ext.conf | 3 +- mopidy_touchscreen/gpio_inpput_manager.py | 14 ++++ mopidy_touchscreen/menu_screen.py | 30 ++++---- mopidy_touchscreen/screen_manager.py | 91 ++++++++++++++--------- mopidy_touchscreen/screen_objects.py | 31 ++++---- mopidy_touchscreen/touch_screen.py | 8 ++ 7 files changed, 112 insertions(+), 66 deletions(-) create mode 100644 mopidy_touchscreen/gpio_inpput_manager.py diff --git a/mopidy_touchscreen/__init__.py b/mopidy_touchscreen/__init__.py index 86e811a..e04d106 100644 --- a/mopidy_touchscreen/__init__.py +++ b/mopidy_touchscreen/__init__.py @@ -31,6 +31,7 @@ class Extension(ext.Extension): schema['cursor'] = config.Boolean() schema['fullscreen'] = config.Boolean() schema['cache_dir'] = config.Path() + schema['gpio'] = config.Boolean() return schema def setup(self, registry): diff --git a/mopidy_touchscreen/ext.conf b/mopidy_touchscreen/ext.conf index 7e3ebf2..3c431ba 100644 --- a/mopidy_touchscreen/ext.conf +++ b/mopidy_touchscreen/ext.conf @@ -4,4 +4,5 @@ screen_width = 320 screen_height = 240 cursor = True fullscreen = False -cache_dir = $XDG_CACHE_DIR/mopidy/touchscreen \ No newline at end of file +cache_dir = $XDG_CACHE_DIR/mopidy/touchscreen +gpio = False \ No newline at end of file diff --git a/mopidy_touchscreen/gpio_inpput_manager.py b/mopidy_touchscreen/gpio_inpput_manager.py new file mode 100644 index 0000000..6a2e3d7 --- /dev/null +++ b/mopidy_touchscreen/gpio_inpput_manager.py @@ -0,0 +1,14 @@ +import RPi.GPIO as GPIO +import logging + +logger = logging.getLogger(__name__) + + +class GPIOManager(): + + def __init__(self): + GPIO.add_event_detect(23, GPIO.RISING, callback=self.printFunction, bouncetime=300) + + + def printFunction(self): + logger.error("Sakatu da") diff --git a/mopidy_touchscreen/menu_screen.py b/mopidy_touchscreen/menu_screen.py index 86e0c81..d17dd68 100644 --- a/mopidy_touchscreen/menu_screen.py +++ b/mopidy_touchscreen/menu_screen.py @@ -4,6 +4,7 @@ import socket import mopidy from .screen_objects import ScreenObjectsManager, TouchAndTextItem +from .input_manager import InputManager class MenuScreen(): @@ -49,20 +50,21 @@ class MenuScreen(): def update(self, screen): self.screen_objects.render(screen) - def touch_event(self, touch_event): - clicked = self.screen_objects.get_touch_objects_in_pos( - touch_event.current_pos) - for key in clicked: - if key == "exit_icon" or key == "exit": - mopidy.utils.process.exit_process() - elif key == "shutdown_icon" or key == "shutdown": - if os.system("gksu -- shutdown now -h") != 0: - os.system("shutdown now -h") - elif key == "restart_icon" or key == "restart": - if os.system("gksu -- shutdown -r now") != 0: - os.system("shutdown -r now") - elif key == "ip": - self.check_connection() + def touch_event(self, event): + if event.type == InputManager.click: + clicked = self.screen_objects.get_touch_objects_in_pos( + event.current_pos) + for key in clicked: + if key == "exit_icon" or key == "exit": + mopidy.utils.process.exit_process() + elif key == "shutdown_icon" or key == "shutdown": + if os.system("gksu -- shutdown now -h") != 0: + os.system("shutdown now -h") + elif key == "restart_icon" or key == "restart": + if os.system("gksu -- shutdown -r now") != 0: + os.system("shutdown -r now") + elif key == "ip": + self.check_connection() # Will check internet connection def check_connection(self): diff --git a/mopidy_touchscreen/screen_manager.py b/mopidy_touchscreen/screen_manager.py index be4ee6d..c633e6a 100644 --- a/mopidy_touchscreen/screen_manager.py +++ b/mopidy_touchscreen/screen_manager.py @@ -41,7 +41,9 @@ class ScreenManager(): traceback.print_exc() self.track = None self.input_manager = InputManager(size) - self.screen_objects_manager = ScreenObjectsManager() + self.top_bar_objects = ScreenObjectsManager() + self.down_bar_objects = ScreenObjectsManager() + self.selected_zone = self.top_bar_objects # Top bar self.top_bar = pygame.Surface((self.size[0], self.base_size), @@ -50,38 +52,38 @@ class ScreenManager(): # Play/pause button = TouchAndTextItem(self.fonts['icon'], u"\ue615 ", (0, 0), None) - self.screen_objects_manager.set_touch_object("pause_play", button) + self.top_bar_objects.set_touch_object("pause_play", button) x = button.get_right_pos() # Random button = TouchAndTextItem(self.fonts['icon'], u"\ue629 ", (x, 0), None) - self.screen_objects_manager.set_touch_object("random", button) + self.top_bar_objects.set_touch_object("random", button) x = button.get_right_pos() # Repeat button = TouchAndTextItem(self.fonts['icon'], u"\ue626", (x, 0), None) - self.screen_objects_manager.set_touch_object("repeat", button) + self.top_bar_objects.set_touch_object("repeat", button) x = button.get_right_pos() # Single button = TouchAndTextItem(self.fonts['base'], " 1 ", (x, 0), None) - self.screen_objects_manager.set_touch_object("single", button) + self.top_bar_objects.set_touch_object("single", button) x = button.get_right_pos() # Internet button = TouchAndTextItem(self.fonts['icon'], u"\ue602 ", (x, 0), None) - self.screen_objects_manager.set_touch_object("internet", button) + self.top_bar_objects.set_touch_object("internet", button) x = button.get_right_pos() # Mute button = TouchAndTextItem(self.fonts['icon'], u"\ue61f ", (x, 0), None) - self.screen_objects_manager.set_touch_object("mute", button) + self.top_bar_objects.set_touch_object("mute", button) x = button.get_right_pos() # Volume progress = Progressbar(self.fonts['base'], "100", (x, 0), (self.size[0] - x, self.base_size), 100, True) - self.screen_objects_manager.set_touch_object("volume", progress) + self.top_bar_objects.set_touch_object("volume", progress) progress.set_value(self.core.playback.volume.get()) # Menu buttons @@ -91,31 +93,31 @@ class ScreenManager(): # Main button button = TouchAndTextItem(self.fonts['icon'], u" \ue600", (0, self.base_size * 7), button_size) - self.screen_objects_manager.set_touch_object("menu_0", button) + self.down_bar_objects.set_touch_object("menu_0", button) x = button.get_right_pos() # Tracklist button button = TouchAndTextItem(self.fonts['icon'], u" \ue60d", (x, self.base_size * 7), button_size) - self.screen_objects_manager.set_touch_object("menu_1", button) + self.down_bar_objects.set_touch_object("menu_1", button) x = button.get_right_pos() # Library button button = TouchAndTextItem(self.fonts['icon'], u" \ue604", (x, self.base_size * 7), button_size) - self.screen_objects_manager.set_touch_object("menu_2", button) + self.down_bar_objects.set_touch_object("menu_2", button) x = button.get_right_pos() # Playlist button button = TouchAndTextItem(self.fonts['icon'], u" \ue605", (x, self.base_size * 7), button_size) - self.screen_objects_manager.set_touch_object("menu_3", button) + self.down_bar_objects.set_touch_object("menu_3", button) x = button.get_right_pos() # Menu button button = TouchAndTextItem(self.fonts['icon'], u" \ue60a", (x, self.base_size * 7), None) - self.screen_objects_manager.set_touch_object("menu_4", button) + self.down_bar_objects.set_touch_object("menu_4", button) # Down bar self.down_bar = pygame.Surface( @@ -129,7 +131,7 @@ class ScreenManager(): self.screens[4].check_connection() self.change_screen(self.current_screen) - self.screen_objects_manager.set_selected("pause_play") + self.top_bar_objects.set_selected("pause_play") def update(self): surface = pygame.Surface(self.size) @@ -137,7 +139,8 @@ class ScreenManager(): self.screens[self.current_screen].update(surface) surface.blit(self.top_bar, (0, 0)) surface.blit(self.down_bar, (0, self.base_size * 7)) - self.screen_objects_manager.render(surface) + self.top_bar_objects.render(surface) + self.down_bar_objects.render(surface) return surface def track_started(self, track): @@ -152,31 +155,37 @@ class ScreenManager(): event = self.input_manager.event(event) if event is not None: if event.type == InputManager.click: - objects = self.screen_objects_manager.get_touch_objects_in_pos( + objects = self.top_bar_objects.get_touch_objects_in_pos( event.current_pos) + objects.extend(self.down_bar_objects.get_touch_objects_in_pos( + event.current_pos)) self.click_on_objects(objects, event) elif event.type == InputManager.key and event.direction == InputManager.enter: - objects = [self.screen_objects_manager.selected_key] + objects = [self.selected_zone.selected_key] self.click_on_objects(objects, event) elif event.type == InputManager.key: - self.screen_objects_manager.change_selected(event.direction) + if event.direction == InputManager.enter: + logger.error(self.selected_zone.selected_key) + self.click_on_objects([self.selected_zone.selected_key], event) + else: + self.change_selection(event, None) self.screens[self.current_screen].touch_event(event) def volume_changed(self, volume): if not self.core.playback.mute.get(): if volume > 80: - self.screen_objects_manager.get_touch_object("mute").set_text( + self.top_bar_objects.get_touch_object("mute").set_text( u"\ue61f", False) elif volume > 50: - self.screen_objects_manager.get_touch_object("mute").set_text( + self.top_bar_objects.get_touch_object("mute").set_text( u"\ue620", False) elif volume > 20: - self.screen_objects_manager.get_touch_object("mute").set_text( + self.top_bar_objects.get_touch_object("mute").set_text( u"\ue621", False) else: - self.screen_objects_manager.get_touch_object("mute").set_text( + self.top_bar_objects.get_touch_object("mute").set_text( u"\ue622", False) - self.screen_objects_manager.get_touch_object("volume").set_value( + self.top_bar_objects.get_touch_object("volume").set_value( volume) def click_on_objects(self, objects, event): @@ -210,7 +219,7 @@ class ScreenManager(): self.change_screen(int(key[-1:])) def change_volume(self,event): - manager = self.screen_objects_manager + manager = self.top_bar_objects volume = manager.get_touch_object("volume") pos = event.current_pos value = volume.get_pos_value(pos) @@ -220,17 +229,17 @@ class ScreenManager(): def playback_state_changed(self, old_state, new_state): if new_state == mopidy.core.PlaybackState.PLAYING: - self.screen_objects_manager.get_touch_object( + self.top_bar_objects.get_touch_object( "pause_play").set_text(u"\ue616", False) else: - self.screen_objects_manager.get_touch_object( + self.top_bar_objects.get_touch_object( "pause_play").set_text(u"\ue615", False) def mute_changed(self, mute): - self.screen_objects_manager.get_touch_object("mute").set_active( + self.top_bar_objects.get_touch_object("mute").set_active( not mute) if mute: - self.screen_objects_manager.get_touch_object("mute").set_text( + self.top_bar_objects.get_touch_object("mute").set_text( u"\ue623", False) else: self.volume_changed(self.core.playback.volume.get()) @@ -239,28 +248,42 @@ class ScreenManager(): self.screens[1].tracklist_changed() def options_changed(self): - self.screen_objects_manager.get_touch_object("random").set_active( + self.top_bar_objects.get_touch_object("random").set_active( self.core.tracklist.random.get()) - self.screen_objects_manager.get_touch_object("repeat").set_active( + self.top_bar_objects.get_touch_object("repeat").set_active( self.core.tracklist.repeat.get()) - self.screen_objects_manager.get_touch_object("single").set_active( + self.top_bar_objects.get_touch_object("single").set_active( self.core.tracklist.single.get()) def change_screen(self, new_screen): - self.screen_objects_manager.get_touch_object( + self.down_bar_objects.get_touch_object( "menu_" + str(self.current_screen)).set_active(False) self.current_screen = new_screen - self.screen_objects_manager.get_touch_object( + self.down_bar_objects.get_touch_object( "menu_" + str(new_screen)).set_active(True) def playlists_loaded(self): self.screens[3].playlists_loaded() def set_connection(self, connection, loading): - internet = self.screen_objects_manager.get_touch_object("internet") + internet = self.top_bar_objects.get_touch_object("internet") if loading: internet.set_text(u"\ue627", None) internet.set_active(False) else: internet.set_text(u"\ue602", None) internet.set_active(connection) + + def change_selection(self, event, pos): + if self.selected_zone == self.top_bar_objects: + if not self.top_bar_objects.change_selected(event.direction, pos) and event.direction == InputManager.down: + pos = self.top_bar_objects.selected.pos + self.selected_zone = self.down_bar_objects + self.top_bar_objects.set_selected(None) + self.change_selection(event, pos) + elif self.selected_zone == self.down_bar_objects: + if not self.down_bar_objects.change_selected(event.direction, pos) and event.direction == InputManager.up: + pos = self.down_bar_objects.selected.pos + self.selected_zone = self.top_bar_objects + self.down_bar_objects.set_selected(None) + self.change_selection(event, pos) \ No newline at end of file diff --git a/mopidy_touchscreen/screen_objects.py b/mopidy_touchscreen/screen_objects.py index fd639d4..fdadf01 100644 --- a/mopidy_touchscreen/screen_objects.py +++ b/mopidy_touchscreen/screen_objects.py @@ -61,23 +61,23 @@ class ScreenObjectsManager(): self.selected_key = key else: self.selected = None - self.selected.set_selected(False) self.selected_key = None - def change_selected(self, direction): - pos = self.selected.pos + def change_selected(self, direction, pos): + if pos is None: + pos = self.selected.pos if direction == InputManager.right: - bests = self.find_nearest_objects(self.find_in_quadrant(False, True), True) - best_key = self.find_best_object(bests, False, True) + bests = self.find_nearest_objects(self.find_in_quadrant(False, True, pos), True, pos) + best_key = self.find_best_object(bests, False, True, pos) elif direction == InputManager.left: - bests = self.find_nearest_objects(self.find_in_quadrant(False, False), True) - best_key = self.find_best_object(bests, False, False) + bests = self.find_nearest_objects(self.find_in_quadrant(False, False, pos), True, pos) + best_key = self.find_best_object(bests, False, False, pos) elif direction == InputManager.down: - bests = self.find_nearest_objects(self.find_in_quadrant(True, True), False) - best_key = self.find_best_object(bests, True, True) + bests = self.find_nearest_objects(self.find_in_quadrant(True, True, pos), False, pos) + best_key = self.find_best_object(bests, True, True, pos) elif direction == InputManager.up: - bests = self.find_nearest_objects(self.find_in_quadrant(True, False), False) - best_key = self.find_best_object(bests, True, False) + bests = self.find_nearest_objects(self.find_in_quadrant(True, False, pos), False, pos) + best_key = self.find_best_object(bests, True, False, pos) if best_key is None: return False else: @@ -88,8 +88,7 @@ class ScreenObjectsManager(): # The quadrant is the normal math one with x and y # x is positive on the bottom as pygame x # The quadrant origin (0,0) is the selected pos - def find_in_quadrant(self, vertical, positive): - pos = self.selected.pos + def find_in_quadrant(self, vertical, positive, pos): objects = {} if vertical: if positive: @@ -116,8 +115,7 @@ class ScreenObjectsManager(): return objects # Find the objects that are nearest - def find_nearest_objects(self, objects, vertical): - pos = self.selected.pos + def find_nearest_objects(self, objects, vertical, pos): best_pos = None min_value = None best_objects = {} @@ -146,8 +144,7 @@ class ScreenObjectsManager(): best_objects[key] = objects[key] return best_objects - def find_best_object(self, objects, vertical, positive): - pos = self.selected.pos + def find_best_object(self, objects, vertical, positive, pos): best_key = None best_pos = None if vertical: diff --git a/mopidy_touchscreen/touch_screen.py b/mopidy_touchscreen/touch_screen.py index a185bd9..bffe3b4 100644 --- a/mopidy_touchscreen/touch_screen.py +++ b/mopidy_touchscreen/touch_screen.py @@ -4,6 +4,7 @@ from threading import Thread import pygame import pykka +import mopidy from mopidy import core from .screen_manager import ScreenManager @@ -27,6 +28,12 @@ class TouchScreen(pykka.ThreadingActor, core.CoreListener): self.screen_manager = ScreenManager(self.screen_size, self.core, self.backend, self.cache_dir) + # Raspberry pi GPIO + self.gpio = config['touchscreen']['gpio'] + if self.gpio: + from .gpio_inpput_manager import GPIOManager + self.gpio = GPIOManager() + def start_thread(self): clock = pygame.time.Clock() if self.fullscreen: @@ -47,6 +54,7 @@ class TouchScreen(pykka.ThreadingActor, core.CoreListener): else: self.screen_manager.event(event) pygame.quit() + mopidy.utils.process.exit_process() def on_start(self): try: