Added a new window for the playlist
Added a new config option `show_playlist` to specify if the playlist should be drawn Added a feature where when the window proportions exceed 1:3, 40% will be used for album art and time info while the remaining 60% will be used for playlist display
This commit is contained in:
229
bin/miniplayer
229
bin/miniplayer
@ -21,7 +21,8 @@ if "player" not in config.sections():
|
||||
"image_method": "pixcat",
|
||||
"album_art_only": False,
|
||||
"volume_step": 5,
|
||||
"auto_close": False
|
||||
"auto_close": False,
|
||||
"show_playlist": True,
|
||||
}
|
||||
|
||||
if "mpd" not in config.sections():
|
||||
@ -87,6 +88,12 @@ VOLUMESTEP = player_config.getint("volume_step", 5)
|
||||
# Autoclose boolean
|
||||
AUTOCLOSE = player_config.getboolean("auto_close", False)
|
||||
|
||||
# Playlist padding
|
||||
PLAYLISTMARGIN = 4
|
||||
|
||||
# Config option to display the playlist
|
||||
DISABLEPLAYLIST = not player_config.getboolean("show_playlist", True)
|
||||
|
||||
|
||||
def albumArtSize(album_space, window_width):
|
||||
"""
|
||||
@ -104,6 +111,26 @@ def albumArtSize(album_space, window_width):
|
||||
return image_width_px, image_width, image_height
|
||||
|
||||
|
||||
def drawPlaylist(height, width):
|
||||
"""
|
||||
A function that checks if the playlist display should be drawn
|
||||
based on the provided height and width
|
||||
"""
|
||||
return height / width < 1/3 and not DISABLEPLAYLIST
|
||||
|
||||
|
||||
def albumArtWinWidth(height, width):
|
||||
"""
|
||||
A function that calculates the album art window height and
|
||||
width based on the window height and width
|
||||
"""
|
||||
if drawPlaylist(height, width):
|
||||
return height, round(width * 2/5)
|
||||
else:
|
||||
return height, width
|
||||
|
||||
|
||||
|
||||
class Player:
|
||||
def __init__(self):
|
||||
# Curses initialisation
|
||||
@ -129,15 +156,39 @@ class Player:
|
||||
|
||||
self.last_song = None
|
||||
|
||||
# Curses window
|
||||
self.window_height, self.window_width = self.stdscr.getmaxyx()
|
||||
self.win = curses.newwin(self.window_height, self.window_width, 0, 0)
|
||||
# Album art only flag
|
||||
self.album_art_only = player_config.getboolean("album_art_only", False)
|
||||
|
||||
self.text_start = int(self.window_height - 5)
|
||||
# Screen size
|
||||
maxyx = self.stdscr.getmaxyx()
|
||||
self.screen_height, self.screen_width = maxyx
|
||||
|
||||
# Album art window
|
||||
self.art_window_height, self.art_window_width = albumArtWinWidth(*maxyx)
|
||||
self.art_win = curses.newwin(
|
||||
self.art_window_height, self.art_window_width,
|
||||
0, 0
|
||||
)
|
||||
|
||||
# Playlist window
|
||||
if drawPlaylist(*maxyx) and not self.album_art_only:
|
||||
self.draw_playlist = True
|
||||
self.playlist_window_width = maxyx[1] - self.art_window_width - PLAYLISTMARGIN
|
||||
self.playlist_window_height = maxyx[0]
|
||||
|
||||
self.playlist_win = curses.newwin(
|
||||
self.playlist_window_height, self.playlist_window_width,
|
||||
0, self.art_window_width + PLAYLISTMARGIN
|
||||
)
|
||||
else:
|
||||
self.draw_playlist = False
|
||||
self.playlist_win = None
|
||||
|
||||
self.text_start = int(self.art_window_height - 5)
|
||||
self.album_space = self.text_start - 2
|
||||
|
||||
# Calculate the size of the image
|
||||
self.image_width_px, self.image_width, self.image_height = albumArtSize(self.album_space, self.window_width)
|
||||
self.image_width_px, self.image_width, self.image_height = albumArtSize(self.album_space, self.art_window_width)
|
||||
self.image_y_pos = (self.album_space - self.image_height) // 2 + 1
|
||||
|
||||
# Album art location
|
||||
@ -153,9 +204,6 @@ class Player:
|
||||
# Update needed flag
|
||||
self.update_needed = False
|
||||
|
||||
# Album art only flag
|
||||
self.album_art_only = player_config.getboolean("album_art_only", False)
|
||||
|
||||
# Flag to check if any music has been played
|
||||
self.has_music_been_played = False
|
||||
|
||||
@ -169,7 +217,7 @@ class Player:
|
||||
song = self.title
|
||||
album = self.album
|
||||
artist = self.artist
|
||||
width = self.window_width
|
||||
width = self.art_window_width
|
||||
|
||||
if len(song) > width:
|
||||
song = song[:width - len(song)]
|
||||
@ -199,30 +247,66 @@ class Player:
|
||||
"""
|
||||
A function to check if the window size changed
|
||||
"""
|
||||
new_height, new_width = self.stdscr.getmaxyx()
|
||||
window_height, window_width = self.stdscr.getmaxyx()
|
||||
|
||||
if (new_height, new_width) != (self.window_height, self.window_width) or force_update:
|
||||
self.win.clear()
|
||||
if (window_height, window_width) != (self.screen_height, self.screen_width) or force_update:
|
||||
|
||||
# Curses window
|
||||
self.window_height, self.window_width = self.stdscr.getmaxyx()
|
||||
if drawPlaylist(window_height, window_width) and not self.album_art_only:
|
||||
self.draw_playlist = True
|
||||
else:
|
||||
self.draw_playlist = False
|
||||
|
||||
# Album art window
|
||||
self.art_window_height, self.art_window_width = albumArtWinWidth(window_height, window_width)
|
||||
|
||||
# Playlist window
|
||||
if self.draw_playlist:
|
||||
self.playlist_window_width = window_width - self.art_window_width - PLAYLISTMARGIN
|
||||
self.playlist_window_height = window_height
|
||||
|
||||
# Close the playlist window if it exists
|
||||
elif self.playlist_win is not None:
|
||||
del self.playlist_win
|
||||
self.playlist_win = None
|
||||
|
||||
# Check if we are drawing info
|
||||
if self.album_art_only:
|
||||
self.text_start = int(self.window_height)
|
||||
self.text_start = int(self.art_window_height)
|
||||
self.album_space = self.text_start - 1
|
||||
else:
|
||||
self.text_start = int(self.window_height - 5)
|
||||
self.text_start = int(self.art_window_height - 5)
|
||||
self.album_space = self.text_start - 2
|
||||
|
||||
# Calculate the size of the image
|
||||
self.image_width_px, self.image_width, self.image_height = albumArtSize(self.album_space, self.window_width)
|
||||
self.image_width_px, self.image_width, self.image_height = albumArtSize(self.album_space, self.art_window_width)
|
||||
self.image_y_pos = (self.album_space - self.image_height) // 2 + 1
|
||||
|
||||
# Resize the window
|
||||
self.win.resize(self.window_height, self.window_width)
|
||||
# Check if playlist window exists and if we are drawing it
|
||||
if self.playlist_win is not None and self.draw_playlist:
|
||||
self.playlist_win.clear()
|
||||
self.playlist_win.refresh()
|
||||
|
||||
self.playlist_win.resize(
|
||||
self.playlist_window_height,
|
||||
self.playlist_window_width
|
||||
)
|
||||
|
||||
self.playlist_win.mvwin(0, self.art_window_width + PLAYLISTMARGIN)
|
||||
|
||||
elif self.draw_playlist:
|
||||
self.playlist_win = curses.newwin(
|
||||
self.playlist_window_height, self.playlist_window_width,
|
||||
0, self.art_window_width + PLAYLISTMARGIN
|
||||
)
|
||||
|
||||
self.last_song = None
|
||||
|
||||
# Resize the window
|
||||
self.art_win.clear()
|
||||
self.art_win.resize(self.art_window_height, self.art_window_width)
|
||||
|
||||
self.screen_height, self.screen_width = window_height, window_width
|
||||
|
||||
|
||||
def getAlbumArt(self, song_file):
|
||||
"""
|
||||
@ -288,7 +372,7 @@ class Player:
|
||||
self.progress = self.elapsed/self.duration
|
||||
|
||||
if self.last_song != song:
|
||||
self.win.clear()
|
||||
self.art_win.clear()
|
||||
|
||||
try:
|
||||
self.album = song["album"]
|
||||
@ -326,9 +410,9 @@ class Player:
|
||||
"""
|
||||
|
||||
self.album_art_only = not self.album_art_only
|
||||
self.win.clear()
|
||||
self.art_win.clear()
|
||||
self.updateWindowSize(force_update=True)
|
||||
self.win.refresh()
|
||||
self.art_win.refresh()
|
||||
|
||||
|
||||
def handleKeypress(self):
|
||||
@ -415,41 +499,84 @@ class Player:
|
||||
|
||||
if state == 0:
|
||||
# Everything fits
|
||||
self.win.addstr(self.text_start, 0, f"{title}")
|
||||
self.win.addstr(self.text_start + 1, 0, f"{artist}{seperator}{album}")
|
||||
self.art_win.addstr(self.text_start, 0, f"{title}")
|
||||
self.art_win.addstr(self.text_start + 1, 0, f"{artist}{seperator}{album}")
|
||||
|
||||
elif state == 1:
|
||||
# Too wide
|
||||
self.win.addstr(self.text_start - 1, 0, f"{title}")
|
||||
self.win.addstr(self.text_start, 0, f"{album}")
|
||||
self.win.addstr(self.text_start + 1, 0, f"{artist}")
|
||||
self.art_win.addstr(self.text_start - 1, 0, f"{title}")
|
||||
self.art_win.addstr(self.text_start, 0, f"{album}")
|
||||
self.art_win.addstr(self.text_start + 1, 0, f"{artist}")
|
||||
|
||||
else:
|
||||
# No album
|
||||
self.win.addstr(self.text_start, 0, f"{title}")
|
||||
self.win.addstr(self.text_start + 1, 0, f"{artist}")
|
||||
self.art_win.addstr(self.text_start, 0, f"{title}")
|
||||
self.art_win.addstr(self.text_start + 1, 0, f"{artist}")
|
||||
|
||||
|
||||
# Progress bar
|
||||
song_duration = (int(self.duration / 60), round(self.duration % 60))
|
||||
song_elapsed = (int(self.elapsed / 60), round(self.elapsed % 60))
|
||||
|
||||
self.win.addstr(
|
||||
self.art_win.addstr(
|
||||
self.text_start + 2, 0,
|
||||
"-"*(int((self.window_width - 1) * self.progress)) + ">",
|
||||
"-"*(int((self.art_window_width - 1) * self.progress)) + ">",
|
||||
curses.color_pair(1)
|
||||
)
|
||||
|
||||
# Duration string
|
||||
time_string = f"{song_elapsed[0]}:{song_elapsed[1]:02d}/{song_duration[0]}:{song_duration[1]:02d}"
|
||||
|
||||
self.win.addstr(
|
||||
self.art_win.addstr(
|
||||
self.text_start + 3, 0,
|
||||
f"{time_string:>{self.window_width}}",
|
||||
f"{time_string:>{self.art_window_width}}",
|
||||
curses.color_pair(2)
|
||||
)
|
||||
|
||||
self.win.refresh()
|
||||
self.art_win.refresh()
|
||||
|
||||
# Draw playlist
|
||||
if self.draw_playlist:
|
||||
playlist = self.client.playlistinfo()
|
||||
currentsong = self.client.currentsong()
|
||||
|
||||
currentpos = int(currentsong["pos"])
|
||||
|
||||
# Determine where to start the playlist
|
||||
if currentpos > self.playlist_window_height // 2 and len(playlist) > self.playlist_window_height:
|
||||
start = currentpos - (self.playlist_window_height - 1) // 2
|
||||
else:
|
||||
start = 0
|
||||
|
||||
start = min(abs(len(playlist) - self.playlist_window_height), start)
|
||||
|
||||
line = 0
|
||||
while line < self.playlist_window_height:
|
||||
# Check if playlist is empty
|
||||
if line + start < len(playlist):
|
||||
playlist_item = playlist[start + line]
|
||||
else:
|
||||
playlist_item = None
|
||||
|
||||
# Decide color
|
||||
if playlist_item == currentsong:
|
||||
pair = curses.A_REVERSE | curses.color_pair(2)
|
||||
else:
|
||||
pair = 0
|
||||
|
||||
# Move and write text
|
||||
self.playlist_win.move(line, 0)
|
||||
|
||||
if playlist_item is not None:
|
||||
self.playlist_win.addstr(
|
||||
f"{playlist_item['artist']} - {playlist_item['title']}"[:self.playlist_window_width],
|
||||
pair
|
||||
)
|
||||
|
||||
self.playlist_win.clrtoeol()
|
||||
line += 1
|
||||
|
||||
self.playlist_win.refresh()
|
||||
|
||||
|
||||
def hideAlbumArt(self):
|
||||
@ -467,7 +594,7 @@ class Player:
|
||||
|
||||
if IMAGEMETHOD == "ueberzug":
|
||||
# Figure out new placement
|
||||
self.art_placement.x = (self.window_width - self.image_width)//2
|
||||
self.art_placement.x = (self.art_window_width - self.image_width)//2
|
||||
self.art_placement.y = self.image_y_pos
|
||||
|
||||
# Figure out height and width
|
||||
@ -484,7 +611,7 @@ class Player:
|
||||
(
|
||||
pixcat.Image(self.album_art_loc)
|
||||
.thumbnail(self.image_width_px )
|
||||
.show(x=(self.window_width - self.image_width)//2, y=self.image_y_pos)
|
||||
.show(x=(self.art_window_width - self.image_width)//2, y=self.image_y_pos)
|
||||
)
|
||||
|
||||
|
||||
@ -498,8 +625,8 @@ class Player:
|
||||
string -- The string to draw
|
||||
"""
|
||||
|
||||
x_pos = self.window_width / 2 - len(string) / 2
|
||||
self.win.addstr(y, int(x_pos), string)
|
||||
x_pos = self.art_window_width / 2 - len(string) / 2
|
||||
self.art_win.addstr(y, int(x_pos), string)
|
||||
|
||||
|
||||
def drawHelp(self):
|
||||
@ -512,18 +639,18 @@ class Player:
|
||||
|
||||
# Left and right margin pct
|
||||
lr_margin_pct = 0.1
|
||||
lr_margin = round(self.window_width * lr_margin_pct)
|
||||
lr_margin = round(self.art_window_width * lr_margin_pct)
|
||||
|
||||
# Actual space for text
|
||||
x_space = self.window_width - 2 * (lr_margin)
|
||||
x_space = self.art_window_width - 2 * (lr_margin)
|
||||
|
||||
# Check if window has been cleared
|
||||
if not self.cleared:
|
||||
self.win.clear()
|
||||
self.art_win.clear()
|
||||
self.cleared = True
|
||||
|
||||
# Figure out center, y_start and x_start
|
||||
center_y, center_x = (self.window_height // 2, self.window_width // 2)
|
||||
center_y, center_x = (self.art_window_height // 2, self.art_window_width // 2)
|
||||
y_start = top_vspace
|
||||
x_start = int(lr_margin)
|
||||
|
||||
@ -535,9 +662,9 @@ class Player:
|
||||
y_start += 1
|
||||
sep = "." * (x_space - len(key) - len(desc) - 2)
|
||||
desc = desc.replace("_", " ").capitalize()
|
||||
self.win.addstr(y_start, x_start, f"{key} {sep} {desc}")
|
||||
self.art_win.addstr(y_start, x_start, f"{key} {sep} {desc}")
|
||||
|
||||
self.win.refresh()
|
||||
self.art_win.refresh()
|
||||
|
||||
|
||||
def draw(self):
|
||||
@ -545,12 +672,12 @@ class Player:
|
||||
The function that draws the now playing window
|
||||
"""
|
||||
if not self.cleared:
|
||||
self.win.clear()
|
||||
self.art_win.clear()
|
||||
self.cleared = True
|
||||
|
||||
# Force window nings
|
||||
self.win.redrawln(0, 1)
|
||||
self.win.addstr(0, 0, " ")
|
||||
self.art_win.redrawln(0, 1)
|
||||
self.art_win.addstr(0, 0, " ")
|
||||
|
||||
# Get mpd state
|
||||
state = self.checkSongUpdate()
|
||||
@ -561,13 +688,13 @@ class Player:
|
||||
# Check if the playlist has concluded and if we should close
|
||||
raise KeyboardInterrupt
|
||||
|
||||
self.win.clear()
|
||||
self.art_win.clear()
|
||||
self.hideAlbumArt()
|
||||
|
||||
infomsg = "Put some beats on!"
|
||||
|
||||
self.win.addstr(self.window_height // 2, (self.window_width - len(infomsg)) // 2, infomsg)
|
||||
self.win.refresh()
|
||||
self.art_win.addstr(self.art_window_height // 2, (self.art_window_width - len(infomsg)) // 2, infomsg)
|
||||
self.art_win.refresh()
|
||||
|
||||
return
|
||||
|
||||
|
Reference in New Issue
Block a user