first working pass at menu scrolling
This commit is contained in:
parent
d299f51c77
commit
2b832f1b0e
@ -9,7 +9,7 @@ import musicpd
|
||||
from math import floor
|
||||
|
||||
class SoundslabDisplay:
|
||||
def __init__(self, player_client):
|
||||
def __init__(self, player_client, input_handler):
|
||||
self.screen_size = 240, 240
|
||||
self.spi_speed_mhz = 80
|
||||
self.st7789 = ST7789(
|
||||
@ -30,12 +30,13 @@ class SoundslabDisplay:
|
||||
# the connection to mpd passed in
|
||||
self.player_client = player_client
|
||||
|
||||
# the connection to the input handler passed in
|
||||
self.input_handler = input_handler
|
||||
|
||||
# track battery voltage over time so we can figure out if we're charging the battery or not
|
||||
self.previous_voltage = 0.0
|
||||
# track currently playing song's art path to eliminate unnecessary reloads of the same image file
|
||||
self.current_art_path = None
|
||||
# start with menus hidden
|
||||
self.show_menu = False
|
||||
|
||||
def _displayOff(self):
|
||||
self.st7789.set_backlight(0) # turn off the backlight
|
||||
@ -70,13 +71,14 @@ class SoundslabDisplay:
|
||||
|
||||
return (voltage, capacity)
|
||||
|
||||
def updateMenu(self, menu_data=None):
|
||||
def updateMenu(self):
|
||||
menu_data = self.input_handler.getMenuOptions()
|
||||
# always start with a transparent menu overlay image
|
||||
bg_color = (200, 0, 0, 255)
|
||||
fg_color = (0, 0, 0, 255)
|
||||
im_menu_overlay = Image.new("RGBA", self.screen_size, (0, 0, 0, 0))
|
||||
menu_overlay = ImageDraw.Draw(im_menu_overlay)
|
||||
if self.show_menu and menu_data is not None:
|
||||
if self.input_handler.state == self.input_handler.MENU and menu_data is not None:
|
||||
# we have a menu to display
|
||||
#
|
||||
# menu_data is structured as a dict describing the menu to be displayed:
|
||||
@ -108,11 +110,11 @@ class SoundslabDisplay:
|
||||
font = ImageFont.truetype(font='/usr/share/fonts/truetype/hack/Hack-Bold.ttf', size=15)
|
||||
|
||||
for idx, row in enumerate(menu_data["rows"], start=0):
|
||||
if menu_data["selected"] == idx:
|
||||
if idx == 1:
|
||||
menu_overlay.rectangle([(21, offset_from_top),(self.screen_size[0] - 21, offset_from_top + 40)], fg_color) # highlight background for selected menu item
|
||||
|
||||
output_size = menu_overlay.textsize(row) # get the size of the text to draw so we can center it in our rectangle for this row
|
||||
menu_overlay.text(((self.screen_size[0] / 2) - floor(output_size[0] / 2) - 14, offset_from_top + (20 - floor(output_size[1]) + 1)), row, font=font, fill=bg_color if menu_data["selected"] == idx else fg_color) # draw output text in appropriate color
|
||||
menu_overlay.text(((self.screen_size[0] / 2) - floor(output_size[0] / 2) - 14, offset_from_top + (20 - floor(output_size[1]) + 1)), row, font=font, fill=bg_color if idx == 1 else fg_color) # draw output text in appropriate color
|
||||
offset_from_top += 40
|
||||
|
||||
# finally, set the current_menu image
|
||||
|
@ -12,7 +12,14 @@ class SoundslabInputHandler:
|
||||
self.player_client.connect()
|
||||
|
||||
# initialize connection to display
|
||||
self.display = SoundslabDisplay(self.player_client)
|
||||
self.display = SoundslabDisplay(self.player_client, self)
|
||||
|
||||
# set up some states and an initial state
|
||||
(self.NOWPLAYING, self.MENU, self.LOCKED) = [1, 2, 3]
|
||||
self.state = self.NOWPLAYING
|
||||
self.current_menu_level = 1
|
||||
self.current_menu_position = 0
|
||||
self.current_menu_items = []
|
||||
|
||||
# The buttons on Pirate Audio are connected to pins 5, 6, 16 and 24
|
||||
# Boards prior to 23 January 2020 used 5, 6, 16 and 20
|
||||
@ -48,9 +55,53 @@ class SoundslabInputHandler:
|
||||
for pin in self.BUTTONS:
|
||||
GPIO.add_event_detect(pin, GPIO.FALLING, self.handle_button, bouncetime=150)
|
||||
|
||||
# menu handler
|
||||
def getMenuOptions(self):
|
||||
if self.current_menu_level == 1:
|
||||
menu = {
|
||||
"options": [
|
||||
"Toggle repeat",
|
||||
"Toggle shuffle",
|
||||
"View queue >",
|
||||
"Browse playlists >",
|
||||
"Browse artists >",
|
||||
"Browse genres >",
|
||||
"Browse decades >",
|
||||
"Browse albums >",
|
||||
"Browse songs >",
|
||||
"Shuffle all songs",
|
||||
"Shuffle all albums",
|
||||
"Settings >",
|
||||
"Power off",
|
||||
"About"
|
||||
]
|
||||
}
|
||||
|
||||
if self.current_menu_position == 0:
|
||||
rows = ["", menu["options"][self.current_menu_position], menu["options"][self.current_menu_position + 1]]
|
||||
elif self.current_menu_position == len(menu["options"]) - 1:
|
||||
rows = [menu["options"][self.current_menu_position - 1], menu["options"][self.current_menu_position], ""]
|
||||
else:
|
||||
# one before current, current, and one after current
|
||||
rows = [ menu["options"][self.current_menu_position - 1], menu["options"][self.current_menu_position], menu["options"][self.current_menu_position + 1] ]
|
||||
|
||||
self.current_menu_items = menu["options"]
|
||||
|
||||
return {
|
||||
"has_previous": False if self.current_menu_position == 0 else True,
|
||||
"has_next": False if self.current_menu_position == len(menu["options"]) else True,
|
||||
"selected": self.current_menu_position,
|
||||
"rows": rows
|
||||
}
|
||||
else:
|
||||
return None
|
||||
|
||||
def handle_menu_option_select(self):
|
||||
pass
|
||||
|
||||
# some button handlers
|
||||
def NE(self):
|
||||
# play/pause toggle
|
||||
# this is ALWAYS play/pause toggle
|
||||
status = self.player_client.status()
|
||||
if status['state'] == "play":
|
||||
print("pausing")
|
||||
@ -63,7 +114,7 @@ class SoundslabInputHandler:
|
||||
player_client.play()
|
||||
|
||||
def SW(self):
|
||||
# previous track
|
||||
# this is ALWAYS previous track
|
||||
status = player_client.status()
|
||||
if float(status['elapsed']) > 5.0:
|
||||
# restart track
|
||||
@ -75,31 +126,59 @@ class SoundslabInputHandler:
|
||||
self.player_client.previous()
|
||||
|
||||
def NW(self):
|
||||
# open menu
|
||||
# this is ALWAYS toggle menu
|
||||
print("toggling menu")
|
||||
if self.display.show_menu is True:
|
||||
self.display.show_menu = False
|
||||
if self.state != self.MENU:
|
||||
self.last_state = self.state
|
||||
self.state = self.MENU
|
||||
else:
|
||||
self.display.show_menu = True
|
||||
self.state = self.last_state
|
||||
self.current_menu_level = 1
|
||||
self.current_menu_position = 0
|
||||
self.current_menu_items = []
|
||||
|
||||
def SE(self):
|
||||
# next track
|
||||
# this is ALWAYS next track
|
||||
print("next track")
|
||||
self.player_client.next()
|
||||
|
||||
def UP(self):
|
||||
# volume up 10%
|
||||
print("vol up")
|
||||
status = self.player_client.status()
|
||||
if int(status['volume']) < 100:
|
||||
self.player_client.setvol(int(status['volume']) + 10)
|
||||
# check current state
|
||||
if self.state == self.NOWPLAYING:
|
||||
# volume up 10%
|
||||
print("vol up")
|
||||
status = self.player_client.status()
|
||||
if int(status['volume']) < 100:
|
||||
self.player_client.setvol(int(status['volume']) + 10)
|
||||
elif self.state == self.MENU:
|
||||
# move up
|
||||
print("up one menu item")
|
||||
if self.current_menu_position != 0:
|
||||
self.current_menu_position -= 1
|
||||
else:
|
||||
print("cannot go up from here!")
|
||||
else:
|
||||
# no op when screen is locked
|
||||
pass
|
||||
|
||||
def DN(self):
|
||||
# volume down 10%
|
||||
print("vol down")
|
||||
status = self.player_client.status()
|
||||
if int(status['volume']) > 0:
|
||||
self.player_client.setvol(int(status['volume']) - 10)
|
||||
# check current state
|
||||
if self.state == self.NOWPLAYING:
|
||||
# volume down 10%
|
||||
print("vol down")
|
||||
status = self.player_client.status()
|
||||
if int(status['volume']) > 0:
|
||||
self.player_client.setvol(int(status['volume']) - 10)
|
||||
elif self.state == self.MENU:
|
||||
# move down
|
||||
print("down one menu item")
|
||||
if self.current_menu_position < len(self.current_menu_items) - 1:
|
||||
self.current_menu_position += 1;
|
||||
else:
|
||||
print("cannot go down from here!")
|
||||
else:
|
||||
# no op when screen is locked
|
||||
pass
|
||||
|
||||
def LF(self):
|
||||
# seek back 10s
|
||||
@ -129,16 +208,8 @@ class SoundslabInputHandler:
|
||||
input_handler = SoundslabInputHandler()
|
||||
|
||||
while True:
|
||||
if input_handler.display.show_menu is True:
|
||||
# test menu
|
||||
input_handler.display.updateMenu({
|
||||
"has_previous": False,
|
||||
"has_next": True,
|
||||
"selected": 0,
|
||||
"rows": ["Turn repeat on", "Turn shuffle on", "View queue >"]
|
||||
})
|
||||
else:
|
||||
input_handler.display.updateMenu()
|
||||
# test menu
|
||||
input_handler.display.updateMenu()
|
||||
# test album art
|
||||
input_handler.display.updateAlbumArt()
|
||||
# test setting up the overlay
|
||||
|
Loading…
Reference in New Issue
Block a user