Add bottom panel and improve data structure
This commit is contained in:
parent
f5ea68509e
commit
202280f760
2 changed files with 77 additions and 28 deletions
92
comp.py
92
comp.py
|
@ -3,6 +3,8 @@
|
|||
import curses
|
||||
import json
|
||||
from argparse import ArgumentParser
|
||||
from configparser import ConfigParser
|
||||
from os.path import expanduser
|
||||
|
||||
import mpv
|
||||
|
||||
|
@ -10,35 +12,46 @@ import mpv
|
|||
def mpv_wrapper(media, video=True):
|
||||
if video:
|
||||
player = mpv.MPV(ytdl=True, input_default_bindings=True,
|
||||
input_vo_keyboard=True)
|
||||
input_vo_keyboard=True, ytdl_format=ytdl_format)
|
||||
else:
|
||||
player = mpv.MPV(ytdl=True, input_default_bindings=True,
|
||||
input_vo_keyboard=True, vid=False)
|
||||
player.register_key_binding('b', player.quit_watch_later)
|
||||
input_vo_keyboard=True, vid=False,
|
||||
ytdl_format=ytdl_format)
|
||||
player.play(media)
|
||||
player.wait_for_playback()
|
||||
del player
|
||||
|
||||
|
||||
def interface(stdscr):
|
||||
def reattr(y, highlight=False):
|
||||
if DATA[start + y - 1]['selected'] and highlight:
|
||||
stdscr.chgat(y, 0, curses.color_pair(11) | curses.A_BOLD)
|
||||
elif DATA[start + y - 1]['selected']:
|
||||
stdscr.chgat(y, 0, curses.color_pair(3) | curses.A_BOLD)
|
||||
elif highlight:
|
||||
def reattr(y):
|
||||
track = DATA[start + y - 1]
|
||||
invert = 8 if track['highlight'] else 0
|
||||
if track['error']:
|
||||
stdscr.chgat(y, 0, curses.color_pair(1 + invert) | curses.A_BOLD)
|
||||
elif track['playing']:
|
||||
stdscr.chgat(y, 0, curses.color_pair(3 + invert) | curses.A_BOLD)
|
||||
elif track['selected']:
|
||||
stdscr.chgat(y, 0, curses.color_pair(5 + invert) | curses.A_BOLD)
|
||||
elif invert:
|
||||
stdscr.chgat(y, 0, curses.color_pair(12) | curses.A_BOLD)
|
||||
else:
|
||||
stdscr.chgat(y, 0, curses.color_pair(0) | curses.A_NORMAL)
|
||||
|
||||
def reprint():
|
||||
stdscr.clear()
|
||||
stdscr.addstr(0, curses.COLS-12, 'URL')
|
||||
stdscr.addstr(0, 0, 'Title')
|
||||
stdscr.chgat(0, 0, curses.color_pair(10) | curses.A_BOLD)
|
||||
for i, d in enumerate(DATA[start : start+curses.LINES-1]):
|
||||
for i, d in enumerate(DATA[start : start+curses.LINES-3]):
|
||||
stdscr.addstr(i + 1, 0, d['url'].rjust(curses.COLS - 1))
|
||||
stdscr.addstr(i + 1, 0, d['title'][:curses.COLS-12])
|
||||
reattr(i + 1)
|
||||
stdscr.addstr(
|
||||
curses.LINES - 2,
|
||||
curses.COLS - 16,
|
||||
'{:7} {:8}'.format(mode, 'selected' if selected else 'all')
|
||||
)
|
||||
stdscr.chgat(curses.LINES - 2, 0, curses.color_pair(8))
|
||||
stdscr.refresh()
|
||||
|
||||
def move(y, delta):
|
||||
|
@ -48,28 +61,34 @@ def interface(stdscr):
|
|||
start = 0
|
||||
reprint()
|
||||
stdscr.move(1, 0)
|
||||
reattr(1, True)
|
||||
DATA[0]['highlight'] = True
|
||||
reattr(1)
|
||||
DATA[0]['highlight'] = False
|
||||
return 1
|
||||
elif start + y + delta > len(DATA):
|
||||
start = len(DATA) - curses.LINES + 1
|
||||
start = len(DATA) - curses.LINES + 3
|
||||
reprint()
|
||||
y = curses.LINES - 1
|
||||
y = curses.LINES - 3
|
||||
stdscr.move(y, 0)
|
||||
reattr(y, True)
|
||||
DATA[-1]['highlight'] = True
|
||||
reattr(y)
|
||||
DATA[-1]['highlight'] = False
|
||||
return y
|
||||
|
||||
if 0 < y + delta < curses.LINES:
|
||||
if 0 < y + delta < curses.LINES - 2:
|
||||
y = y + delta
|
||||
elif y + delta < 1:
|
||||
start += y + delta - 1
|
||||
reprint()
|
||||
y = 1
|
||||
else:
|
||||
start += y + delta - curses.LINES + 1
|
||||
start += y + delta - curses.LINES + 3
|
||||
reprint()
|
||||
y = curses.LINES - 1
|
||||
y = curses.LINES - 3
|
||||
stdscr.move(y, 0)
|
||||
reattr(y, True)
|
||||
DATA[start + y - 1]['highlight'] = True
|
||||
reattr(y)
|
||||
DATA[start + y - 1]['highlight'] = False
|
||||
stdscr.refresh()
|
||||
return y
|
||||
|
||||
|
@ -92,16 +111,22 @@ def interface(stdscr):
|
|||
curses.curs_set(False)
|
||||
|
||||
# Print initial content
|
||||
stdscr.clear()
|
||||
start = 0
|
||||
reprint()
|
||||
y = 1
|
||||
stdscr.move(y, 0)
|
||||
reattr(y, True)
|
||||
DATA[0]['highlight'] = True
|
||||
stdscr.move(1, 0)
|
||||
reattr(1)
|
||||
DATA[0]['highlight'] = False
|
||||
|
||||
while True:
|
||||
c = stdscr.getch()
|
||||
if c in (ord('j'), curses.KEY_DOWN):
|
||||
if c == curses.KEY_RESIZE:
|
||||
curses.update_lines_cols()
|
||||
reprint()
|
||||
y = 1
|
||||
reattr(y)
|
||||
elif c in (ord('j'), curses.KEY_DOWN):
|
||||
y = move(y, 1)
|
||||
elif c in (ord('k'), curses.KEY_UP):
|
||||
y = move(y, -1)
|
||||
|
@ -116,10 +141,15 @@ def interface(stdscr):
|
|||
elif c == ord(' '):
|
||||
DATA[start + y - 1]['selected'] = not DATA[start + y - 1]['selected']
|
||||
y = move(y, 1)
|
||||
elif c == ord('c'): # temporally behavior
|
||||
mpv_wrapper('https://youtu.be/' + DATA[start + y - 1]['url'])
|
||||
elif c == ord('x'): # temporally behavior
|
||||
mpv_wrapper('https://youtu.be/' + DATA[start + y - 1]['url'], video)
|
||||
elif c == ord('v'):
|
||||
player.quit_watch_later()
|
||||
elif c in (ord('q'), 27): # 27 is Escape key
|
||||
break
|
||||
stdscr.addstr(curses.LINES - 1, 0, 'Quit comp? [y/N]')
|
||||
if stdscr.getch() == ord('y'):
|
||||
break
|
||||
reprint()
|
||||
stdscr.refresh()
|
||||
|
||||
|
||||
|
@ -127,9 +157,19 @@ parser = ArgumentParser(description="console/curses online media player")
|
|||
parser.add_argument('-j', '--json-playlist', required=False,
|
||||
help='path to playlist in JSON format')
|
||||
args = parser.parse_args()
|
||||
|
||||
config = ConfigParser()
|
||||
config.read(expanduser('~/.config/comp/settings.ini'))
|
||||
ytdl_format = config.get('Init', 'ytdl-format', fallback='best')
|
||||
mode = config.get('Runtime', 'play-mode', fallback='normal')
|
||||
selected = config.getboolean('Runtime', 'play-selected-only', fallback=False)
|
||||
video = config.getboolean('Runtime', 'video', fallback=True)
|
||||
|
||||
with open(args.json_playlist) as f:
|
||||
DATA = json.load(f)
|
||||
for i in DATA:
|
||||
i['error'] = False
|
||||
i['playing'] = False
|
||||
i['selected'] = False
|
||||
|
||||
i['highlight'] = False
|
||||
curses.wrapper(interface)
|
||||
|
|
13
setup.py
13
setup.py
|
@ -12,7 +12,16 @@ setup(name = 'comp',
|
|||
long_description=long_description,
|
||||
author = 'McSinyx',
|
||||
author_email = 'vn.mcsinyx@gmail.com',
|
||||
license = 'AGPLv2',
|
||||
py_modules = ['mpv'],
|
||||
scripts=['comp']
|
||||
scripts=['comp'],
|
||||
classifiers = ['Development Status :: 1 - Planning',
|
||||
'Environment :: Console :: Curses',
|
||||
'Intended Audience :: End Users/Desktop',
|
||||
'Natural Language :: English',
|
||||
'Natural Language :: Vietnamese', # planned
|
||||
'Operating System :: POSIX',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Topic :: Multimedia :: Sound/Audio :: Players',
|
||||
'Topic :: Multimedia :: Video :: Display'],
|
||||
license = 'AGPLv2'
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue