Skip to content

Commit

Permalink
merge branch 'experimental'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jugran committed Mar 23, 2020
2 parents 2a85573 + a0239eb commit ca5b132
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 174 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include lyrics/lyrics.cfg
77 changes: 77 additions & 0 deletions lyrics/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from configparser import ConfigParser

import curses
import os

KEYS={
'arrow_up': curses.KEY_UP,
'arrow_down': curses.KEY_DOWN,
'arrow_left': curses.KEY_LEFT,
'arrow_right': curses.KEY_RIGHT
}

CONFIG_PATH = os.path.abspath(os.path.dirname(__file__))

class Config:
def __init__(self, section):
self.dict = {}

self.filepath = os.path.join(CONFIG_PATH, 'lyrics.cfg')
self.section = section

self.load()
self.set_constants()

def __setitem__(self, key, value):
self.dict[key] = value

def __getitem__(self, key):
return self.dict[key]

def __contains__(self, key):
return key in self.dict

def __repr__(self):
return self.dict.__repr__()

def items(self):
return [(k, v) for k,v in self.dict.items()]

def load(self):
try:
config = ConfigParser()
config.read(self.filepath)
except Exception as e:
pass
# use default config

conf = dict(config.items(self.section))
assert isinstance(conf, dict)

self.dict = conf

def set_constants(self):
for key, value in self.dict.items():
if value in KEYS.keys():
self.dict[key] = KEYS[value]
else:
try:
value = int(value)
self.dict[key] = value
except ValueError:
# not integer
# change to ascii
if len(value) == 1:
self.dict[key] = ord(value)
'''
def save(self):
config = ConfigParser()
config.read(self.filepath)
config[self.section] = self.dict
with open(self.filepath, 'w') as file:
config.write(file)
'''
30 changes: 30 additions & 0 deletions lyrics/lyrics.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# config structure

[OPTIONS]
alignment=left
source=google
interval=1500
player=spotify
#colors
#offset=1

[BINDINGS]
up=arrow_up
down=arrow_down

step-up=arrow_left
step-down=arrow_right
step-size=5

google=R
azLyrics=r

left=j
center=k
right=l

delete=d

quit=q


178 changes: 23 additions & 155 deletions lyrics/lyrics_in_terminal.py
Original file line number Diff line number Diff line change
@@ -1,174 +1,42 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-


from .config import Config
from .player import Player
from .window import Window

import curses
import sys
import curses

# BUG: when change alignment the text does not wrap to window
# -> re wrap when re align

class Window:
def __init__(self, stdscr, player, timeout=1500):
self.stdscr = stdscr
self.height, self.width = stdscr.getmaxyx()
self.player = player
self.scroll_pad = curses.newpad(self.player.track.length + 2, self.player.track.width + 2)
self.current_pos = 0
self.pad_offset = 1
self.text_padding = 5

curses.use_default_colors()
self.stdscr.timeout(timeout)
self.set_up()
def main(stdscr):
defaults=Config('OPTIONS')

def set_up(self):
self.stdscr.clear()
curses.curs_set(0)
self.current_pos = 0
if len(sys.argv) >= 2:
player_name=sys.argv[1].strip()
else:
player_name=defaults['player'].strip()

if self.player.running:
self.update_track()
self.set_titlebar()
self.stdscr.refresh()
self.scroll_pad.refresh(self.current_pos, 0, 4, self.pad_offset, self.height - 2, self.width - 1)
else:
self.stdscr.addstr(0, 1, f'{self.player.player_name} is not running!')
self.stdscr.refresh()
align = defaults['alignment']

def set_titlebar(self):
track_info = self.player.track.track_info(self.width - 1)
# track_info -> ['title', 'artist', 'album'] - all algined
self.stdscr.addstr(0, 1, track_info[0], curses.A_REVERSE)
self.stdscr.addstr(1, 1, track_info[1], curses.A_REVERSE | curses.A_BOLD | curses.A_DIM)
self.stdscr.addstr(2, 1, track_info[2], curses.A_REVERSE)

def set_offset(self):
if self.player.track.alignment == 0:
# center align
self.pad_offset = (self.width - self.player.track.width) // 2
elif self.player.track.alignment == 1:
self.pad_offset = 2
else:
self.pad_offset = (self.width - self.player.track.width) - 2
if align == 'center':
align = 0
elif align == 'right':
align = 2
else:
align = 1

def scroll_down(self, step=1):
if self.current_pos < self.player.track.length - (self.height * 0.5):
self.current_pos += step
else:
self.stdscr.addstr(self.height - 1, 1, 'END', curses.A_REVERSE)

def scroll_up(self, step=1):
if self.current_pos > 0:
if self.current_pos >= self.player.track.length - (self.height * 0.5):
self.stdscr.move(self.height - 1, 0)
self.stdscr.clrtoeol()
self.current_pos -= step

def update_track(self):
self.stdscr.clear()
self.scroll_pad.clear()

if self.player.track.width > self.width - self.text_padding:
text = self.player.track.get_text(wrap=True, width=self.width - self.text_padding)
else:
text = self.player.track.get_text()

pad_height = max(self.height, self.player.track.length) + 2
pad_width = max(self.width, self.player.track.width) + 2

self.scroll_pad.resize(pad_height, pad_width)
self.scroll_pad.addstr(text)
self.set_offset()

def input_key(self, key):
if key == curses.KEY_RESIZE:
self.update_track()
elif key == curses.KEY_DOWN:
self.scroll_down()
elif key == curses.KEY_RIGHT:
self.scroll_down(5)
self.stdscr.erase()
elif key == curses.KEY_UP:
self.scroll_up()
elif key == curses.KEY_LEFT:
self.scroll_up(5)
self.stdscr.erase()
interval = defaults['interval']
source = defaults['source']

elif key == ord('r'):
self.player.refresh('az')
self.current_pos = 0
self.update_track()
elif key == ord('R'):
self.player.refresh('google')
self.current_pos = 0
self.update_track()

# keys to change alignment
# j = left | k = center | l = right
elif key == ord('j'):
self.player.track.alignment=1
self.player.track.reset_width()
self.update_track()
elif key == ord('k'):
self.player.track.alignment=0
self.player.track.reset_width()
self.update_track()
elif key == ord('l'):
self.player.track.alignment=2
self.player.track.reset_width()
self.update_track()

elif key == ord('d'):
if self.player.track.delete_lyrics():
self.stdscr.addstr(self.height - 1, self.width - 10, ' Deleted ', curses.A_REVERSE)

def main(self):
key = ''

while key != ord('q') and key != ord('Q'):
key = self.stdscr.getch()

self.height, self.width = self.stdscr.getmaxyx()

if key == -1:
if self.player.update():
self.current_pos = 0
self.update_track()

if self.player.running:
self.input_key(key)

self.set_titlebar()
self.stdscr.refresh()
self.scroll_pad.refresh(self.current_pos, 0, 4, self.pad_offset, self.height - 2, self.width - 1)
else:
self.stdscr.clear()
self.stdscr.addstr(0, 1, f'{self.player.player_name} is not running!')
self.stdscr.refresh()


def main(stdscr, player_name, **kwargs):
player = Player(player_name, **kwargs)

win = Window(stdscr, player, timeout=1500)
#curses.cbreak()
# win.stdscr.timeout(1500)
player = Player(player_name, source, align=align)
win = Window(stdscr, player, timeout=interval)

win.main()


def start(player_name=None):
if player_name is None:
if len(sys.argv) >= 2:
player_name=sys.argv[1].strip()
else:
player_name='spotify'
else:
player_name = player_name.strip()

curses.wrapper(main, player_name, align=1)
def start():
curses.wrapper(main)


if __name__ == '__main__':
Expand Down
9 changes: 6 additions & 3 deletions lyrics/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@


class Player:
def __init__(self, name, **kwargs):
def __init__(self, name, source, **kwargs):
self.player_name = name
self.default_source = source

self.running = False
self.metadata = None
self.track = Track(**kwargs)
Expand Down Expand Up @@ -54,12 +56,13 @@ def update(self):
elif self.track.trackid != trackid or self.track.title != title:
#update
self.track.update(artist, title, album, trackid)
self.refresh(self.default_source)
return True

return False

def refresh(self, source='az'):
self.track.get_lyrics(cache=False, source=source)
def refresh(self, source):
self.track.get_lyrics(source, cache=False)

def next(self):
pass
Expand Down
11 changes: 4 additions & 7 deletions lyrics/track.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
from . import util


Expand All @@ -20,7 +18,6 @@ def __init__(self,
self.lyrics = None
self.album = None
self.trackid = None
# self.art_url = None

def __str__(self):
return self.artist + ' - ' + self.title
Expand All @@ -47,16 +44,16 @@ def update(self, artist, title, album, trackid):
self.album = album
self.trackid = trackid
# self.art_url = art_url
self.get_lyrics()
# self.get_lyrics()

def get_lyrics(self, cache=True, source='google'):
self.lyrics = util.get_lyrics(self.track_name, cache=cache, source=source)
def get_lyrics(self, source, cache=True):
self.lyrics = util.get_lyrics(self.track_name, source, cache=cache)
self.width = len(max(self.lyrics, key=len))
self.length = len(self.lyrics)

def get_text(self, wrap=False, width=0):
if wrap:
lyrics=util.wrapText(self.lyrics, width)
lyrics=util.wrap_text(self.lyrics, width)
else:
lyrics=self.lyrics

Expand Down
6 changes: 3 additions & 3 deletions lyrics/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def fetch_lyrics(url):
return lyrics_lines


def get_lyrics(track_name, cache=True, source='google'):
def get_lyrics(track_name, source, cache=True):
filename = track_name.strip()
filename = re.sub(r'\s|\/|\\|\.', '', filename)
filepath = os.path.join(CACHE_PATH, filename)
Expand Down Expand Up @@ -152,10 +152,10 @@ def align(lines, width, alignment=1):
elif alignment == 0:
return [line.center(width) for line in lines]
else:
return [line.rjust(width) for line in lines]
return [line.rjust(width - 1) for line in lines]


def wrapText(text, width):
def wrap_text(text, width):
lines = []
for line in text:
if len(line) > width:
Expand Down
Loading

0 comments on commit ca5b132

Please sign in to comment.