funkwlmpv/src/mpv_control.py

221 lines
7.6 KiB
Python
Raw Normal View History

2022-11-08 19:23:19 +00:00
import src.fw_api
2023-06-10 21:54:26 +00:00
from src.utils import download_track, print_there, track_info_output
from src.settings import get_config
2022-11-01 10:15:28 +00:00
from loguru import logger
2022-11-08 18:02:07 +00:00
from pyfzf.pyfzf import FzfPrompt
from shutil import get_terminal_size
2023-06-04 10:52:50 +00:00
from shlex import quote
import mpv
import time
2023-01-26 17:03:04 +00:00
import re
import requests
2022-11-08 18:02:07 +00:00
fzf = FzfPrompt()
2023-03-02 17:58:22 +00:00
if get_config('enable_persistent_cache'):
player = mpv.MPV(cache=True,
scripts='src/mpv_scripts/mpv_cache.lua:src/mpv_scripts/streamsave.lua',
script_opts='streamsave-save_directory=cache,streamsave-dump_mode=continuous,streansave-force_extension=.mkv,streamsave-autostart=no,output_label=overwrite')
2023-03-04 00:25:09 +00:00
player.command('script-message', 'streamsave-path', 'cache')
2023-03-02 17:58:22 +00:00
else:
player = mpv.MPV(cache=True, demuxer_max_bytes=25*1024*1024)
2022-12-18 01:02:53 +00:00
player.ytdl = False # Prevent attempts load track with yt-dlp
player.volume = get_config('mpv_volume')
player.prefetch_playlist = get_config('prefetch_playlist')
2022-11-13 02:16:46 +00:00
show_like_button = get_config('show_like_button')
track_activity_history = get_config('track_activity_history')
share_to_fediverse_token = get_config('share_to_fediverse_token')
share_to_fediverse_instance = get_config('share_to_fediverse_instance')
shuffle = False
2022-11-08 18:02:07 +00:00
class player_fw_storage:
storage = {}
@logger.catch
2022-11-18 10:22:55 +00:00
def track_url_to_uuid(listen_url=None):
'''Attempt get uuid from track listen url or current playing url'''
2023-01-26 17:03:04 +00:00
hex = '[0-9a-fA-F]+'
find_uuid = f'{hex}-{hex}-{hex}-{hex}-{hex}'
2022-11-18 10:22:55 +00:00
if listen_url:
2023-01-26 17:03:04 +00:00
uuid = re.findall(find_uuid, listen_url)
2022-11-18 10:22:55 +00:00
else:
2023-01-26 17:03:04 +00:00
uuid = re.findall(find_uuid, player.stream_open_filename)
return uuid[0]
2022-11-18 10:22:55 +00:00
def send_listen_activity():
try:
track = player_fw_storage.storage.get(track_url_to_uuid())
except:
return
if src.fw_api.current_instance.token is not None:
track_id = track.get('id')
if track_id:
src.fw_api.record_track_in_history(track_id)
else:
logger.error("Can't write track to history: No track id")
if share_to_fediverse_token != '':
fid = track.get('fid')
artist = track['artist'].get('name')
album = track['album'].get('title')
title = track.get('title')
tags = track.get('tags')
if tags:
tags = [f'#{tag}' for tag in tags]
tags = ' '.join(tags)
if tags == []:
tags = ''
status_obj = {'spoiler_text': 'funkwhale-cli music share',
'visibility': 'unlisted',
'status': f'🎧 {artist} - {album} - {title}\n{fid}\n#NowPlaying {tags}'}
requests.post(f'https://{share_to_fediverse_instance}/api/v1/statuses',
json=status_obj,
headers={'Authorization': f'Bearer {share_to_fediverse_token}'})
2023-06-10 23:06:44 +00:00
def osd_observer(value):
'''Sumulate osd playing message in console'''
if value:
osd_message = []
for i in value.items():
if i[0] in ('Artist', 'Album', 'Title'):
osd_message.append(i[1])
2023-06-10 23:06:44 +00:00
osd_string = ' - '.join(osd_message)
term_len = get_terminal_size().columns
2023-06-10 23:06:44 +00:00
print_there(0, 0, '\r'+' '*term_len)
2022-12-22 11:37:27 +00:00
print_there(0, 0, '\r'+osd_string[:term_len])
2023-06-10 23:06:44 +00:00
else:
print_there(0, 0, '\rNo metadata...')
2022-12-21 20:08:46 +00:00
@player.event_callback('start-file')
@logger.catch
def starting_file_handler(value):
'''just show loading state'''
print_there(0, 0, '\rLoading track...')
2022-12-21 20:08:46 +00:00
@player.property_observer('percent-pos')
@logger.catch
def universal_observer(_name, value):
if value:
percent = int(value)
2022-12-21 20:08:46 +00:00
if player.audio_bitrate:
kbps = int(player.audio_bitrate/1024)
2022-12-21 20:08:46 +00:00
else:
kbps = '?'
if player.file_size:
track_size = round(player.file_size/1024/1024, 1)
else:
track_size = '?'
if player.cache_speed:
2022-12-29 23:23:26 +00:00
speed_load = player.cache_speed
if speed_load >= 3*1024*1024:
cache_speed = '| <<<'
elif speed_load >= 1*1024*1024:
cache_speed = '| <<*'
else:
cache_speed = '| <=>'
else:
cache_speed = ''
if player.playlist_count > -1:
2022-12-29 22:54:36 +00:00
player_pos = f'{player.playlist_pos_1}/{player.playlist_count}'
else:
player_pos = '-/-'
2023-06-10 23:06:44 +00:00
osd_observer(player.filtered_metadata)
print_there(2, 2, f'\r'+' '*get_terminal_size().columns)
print_there(2, 2, f'\r{player_pos} | {kbps} kbps | {percent}% | {track_size}MB {cache_speed}')
2022-12-21 20:08:46 +00:00
time.sleep(1)
def soft_volume_reduce():
while player.volume > 10:
player.volume = player.volume - 1
time.sleep(0.050)
@logger.catch
def player_menu(header='', storage={}):
player_fw_storage.storage.update(storage)
2022-11-14 23:02:22 +00:00
player.volume = get_config("mpv_volume")
global shuffle
2022-11-08 18:02:07 +00:00
while True:
try:
2022-11-13 02:16:46 +00:00
player_items_menu = ['Next', 'Prev', 'Pause',
'Shuffle', 'Download', 'Info', 'Share']
if player.pause:
player_items_menu[2] = 'Play'
else:
player_items_menu[2] = 'Pause'
if shuffle:
player_items_menu[3] = 'Unshuffle'
else:
player_items_menu[3] = 'Shuffle'
2022-11-13 02:16:46 +00:00
if show_like_button:
player_items_menu.append('Like')
player_items_menu.extend(['Hide artist', 'Exit'])
select = fzf.prompt(player_items_menu, quote(f"--header=\'{header}\'"))
if select == []:
break
else:
select = select[0]
2022-11-08 18:02:07 +00:00
if select == 'Next':
2022-12-20 01:33:29 +00:00
try:
player.playlist_next()
except:
print('No more next tracks')
2022-11-08 18:02:07 +00:00
elif select == 'Prev':
player.playlist_prev()
elif select in ('Pause', 'Play'):
player.cycle('pause')
elif select in ('Shuffle', 'Unshuffle'):
if shuffle:
shuffle = False
player.playlist_unshuffle()
2022-11-08 18:02:07 +00:00
else:
shuffle = True
player.playlist_shuffle()
player.playlist_play_index(0)
2022-11-08 18:02:07 +00:00
elif select == 'Download':
name_downloaded = download_track(player.stream_open_filename)
2022-11-08 18:02:07 +00:00
elif select == 'Info':
track = player_fw_storage.storage.get(track_url_to_uuid())
2023-06-14 14:37:36 +00:00
track['direct_url'] = player.stream_open_filename
2023-06-10 21:54:26 +00:00
track_info_output(track)
elif select == 'Share':
send_listen_activity()
2022-11-13 02:16:46 +00:00
elif select == 'Like':
2022-12-18 01:02:53 +00:00
src.fw_api.favorite_track(
player_fw_storage.storage.get(track_url_to_uuid())['id'])
2022-11-08 19:23:19 +00:00
elif select == 'Hide artist':
track = player_fw_storage.storage.get(track_url_to_uuid())
2022-12-18 01:02:53 +00:00
src.fw_api.hide_content(
{'target': {'id': track.get('artist').get('id'), 'type': 'artist'}})
2022-11-08 18:02:07 +00:00
elif select == 'Exit':
shuffle = False
soft_volume_reduce()
2022-11-08 18:02:07 +00:00
player.playlist_clear()
player.stop()
player_fw_storage.storage = {}
2022-11-08 18:02:07 +00:00
break
except KeyboardInterrupt:
break
2022-12-17 01:16:36 +00:00
def play_track(track, multi=False):
listen_url = src.fw_api.get_audio_file(track['listen_url'], True)
player_fw_storage.storage[track_url_to_uuid(listen_url)] = track
if multi:
player.loadfile(listen_url, 'append-play')
else:
player.loadfile(listen_url, 'append-play')
track_name = track.get('title')
player_menu(f"{track_name} playing...", player_fw_storage.storage)