2023-06-03 22:24:44 +00:00
|
|
|
from src.fw_api import current_instance, get_radios, post_radio_session, get_track_radio, list_libraries, favorite_track, get_audio_file, hide_content
|
2022-11-08 22:34:33 +00:00
|
|
|
from src.fw_libraries import libraries
|
2022-11-30 00:33:14 +00:00
|
|
|
from src.fw_tags import list_tags
|
2023-06-10 21:54:26 +00:00
|
|
|
from src.utils import download_track, track_info_output
|
2023-06-11 12:10:24 +00:00
|
|
|
from src.mpv_control import player, track_url_to_uuid, player_fw_storage, soft_volume_reduce
|
2022-11-13 23:26:47 +00:00
|
|
|
from src.settings import get_config
|
2022-11-01 10:15:28 +00:00
|
|
|
from pyfzf.pyfzf import FzfPrompt
|
2022-11-06 00:45:56 +00:00
|
|
|
from loguru import logger
|
2023-06-04 10:52:50 +00:00
|
|
|
from shlex import quote
|
2022-11-02 00:05:08 +00:00
|
|
|
import threading
|
|
|
|
import time
|
2022-12-21 20:08:46 +00:00
|
|
|
import sys
|
2022-11-02 00:05:08 +00:00
|
|
|
|
2022-11-01 10:15:28 +00:00
|
|
|
fzf = FzfPrompt()
|
|
|
|
|
|
|
|
|
2022-11-08 20:39:01 +00:00
|
|
|
@logger.catch
|
2023-06-14 20:05:14 +00:00
|
|
|
def list_radios(error_given=None):
|
2022-11-01 10:15:28 +00:00
|
|
|
radios = get_radios()
|
|
|
|
count = radios.get('count')
|
|
|
|
|
|
|
|
results = radios.get('results')
|
|
|
|
view = []
|
2022-12-18 01:02:53 +00:00
|
|
|
for i in results:
|
2022-11-01 10:15:28 +00:00
|
|
|
index = results.index(i)
|
|
|
|
id_radio = i.get('id')
|
|
|
|
name = i.get('name')
|
2022-11-23 22:48:59 +00:00
|
|
|
descr = i.get('description')
|
|
|
|
radio_option = name
|
|
|
|
if descr and descr != "":
|
|
|
|
radio_option += f' | {descr}'
|
|
|
|
view.append(f'{index}.{radio_option}')
|
2022-12-18 01:02:53 +00:00
|
|
|
# Radios avalaible only for auth user
|
|
|
|
if current_instance.s.headers.get('Authorization'):
|
2022-11-06 01:26:50 +00:00
|
|
|
view.append('Favourites')
|
|
|
|
view.append('Less listened')
|
2022-11-30 00:33:14 +00:00
|
|
|
view.extend(['Tag', 'Random', 'Libraries', 'Users', 'Recently Added'])
|
2023-06-14 20:05:14 +00:00
|
|
|
header = f'Found {count} radios'
|
|
|
|
if error_given:
|
|
|
|
header += f'\n{error_given}'
|
|
|
|
header = quote(header)
|
2022-12-18 01:02:53 +00:00
|
|
|
selected = fzf.prompt(
|
2023-06-14 21:52:34 +00:00
|
|
|
view, f'--header {header} --read0', delimiter="\0")
|
|
|
|
if selected == []:
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
selected = selected[0].split('.', 1)
|
|
|
|
|
2022-11-02 23:58:55 +00:00
|
|
|
if 'Favourites' in selected:
|
2022-11-23 22:58:17 +00:00
|
|
|
radio_load(id_radio, 'favorites', name='your favorites tracks')
|
2022-11-30 00:33:14 +00:00
|
|
|
elif 'Tag' in selected:
|
|
|
|
tag = list_tags()
|
2022-11-30 00:41:14 +00:00
|
|
|
radio_load(type_radio='tag', name=f'by tag: {tag}', related_object=tag)
|
2022-11-06 01:26:50 +00:00
|
|
|
elif 'Random' in selected:
|
2022-11-23 22:58:17 +00:00
|
|
|
radio_load(id_radio, 'random', name='totally random')
|
2022-11-08 20:39:01 +00:00
|
|
|
elif 'Libraries' in selected:
|
2022-12-29 20:14:28 +00:00
|
|
|
id_radio, type_radio, name_radio, related_obj = libraries(radio=True)
|
2022-11-08 22:34:33 +00:00
|
|
|
radio_load(id_radio, type_radio, name_radio, related_obj)
|
2022-11-08 20:39:01 +00:00
|
|
|
elif 'Users' in selected:
|
2022-11-08 00:29:44 +00:00
|
|
|
libs = list_libraries()['results']
|
|
|
|
libraries_listing = []
|
|
|
|
for lib_i in libs:
|
|
|
|
lib_name = lib_i.get('actor').get('full_username')
|
|
|
|
if lib_name not in libraries_listing:
|
|
|
|
libraries_listing.append(lib_name)
|
|
|
|
libraries_listing.append('Custom')
|
|
|
|
lib_addr = fzf.prompt(libraries_listing)[0]
|
|
|
|
if lib_addr == 'Custom':
|
|
|
|
print('Input remote user library (ex. nick@funkwhale.domain.example: ')
|
|
|
|
lib_addr = input()
|
2022-11-07 23:40:26 +00:00
|
|
|
radio_load(None, 'actor-content', lib_addr, lib_addr)
|
2022-11-06 01:26:50 +00:00
|
|
|
elif 'Recently Added' in selected:
|
2022-12-18 01:02:53 +00:00
|
|
|
radio_load(id_radio, 'recently-added',
|
|
|
|
name='Newest content on the network')
|
2022-11-06 01:26:50 +00:00
|
|
|
elif 'Less listened' in selected:
|
2022-11-23 22:58:17 +00:00
|
|
|
radio_load(id_radio, 'less-listened', name="Less listened tracks")
|
2022-11-02 23:58:55 +00:00
|
|
|
else:
|
|
|
|
id_selected = selected[0]
|
|
|
|
id_radio = results[int(id_selected)].get('id')
|
2022-11-07 11:36:02 +00:00
|
|
|
name_radio = results[int(id_selected)].get('name')
|
|
|
|
radio_load(id_radio, name=name_radio)
|
2022-11-06 00:45:56 +00:00
|
|
|
|
2022-11-01 10:15:28 +00:00
|
|
|
|
2022-11-02 00:05:08 +00:00
|
|
|
def radio_generator(radio_session_id):
|
2022-11-06 00:45:56 +00:00
|
|
|
count_t = 0
|
2022-11-02 00:05:08 +00:00
|
|
|
while radio_session_id != '':
|
2022-11-06 00:45:56 +00:00
|
|
|
time.sleep(1)
|
2022-12-18 01:02:53 +00:00
|
|
|
if not radio_event_gen.wait(0):
|
2022-11-06 00:45:56 +00:00
|
|
|
break
|
|
|
|
count_t += 1
|
|
|
|
if count_t >= 60:
|
2022-11-06 22:21:49 +00:00
|
|
|
count_t = 0
|
2022-12-18 01:02:53 +00:00
|
|
|
playlist_remaining = len(player.playlist) - \
|
|
|
|
player.playlist_current_pos
|
|
|
|
if playlist_remaining <= 2:
|
2022-11-24 01:12:34 +00:00
|
|
|
radio_get_track(radio_session_id)
|
2022-12-21 20:08:46 +00:00
|
|
|
sys.stdout.write('\rRadio generator stopped')
|
|
|
|
sys.stdout.flush()
|
2022-11-02 00:05:08 +00:00
|
|
|
|
2022-12-18 01:02:53 +00:00
|
|
|
|
2022-11-06 00:45:56 +00:00
|
|
|
radio_event_gen = threading.Event()
|
2022-11-02 00:05:08 +00:00
|
|
|
|
2022-11-08 18:37:43 +00:00
|
|
|
|
|
|
|
@logger.catch
|
2022-11-07 23:40:26 +00:00
|
|
|
def radio_load(id_radio=None, type_radio='custom', name=None, related_object=None):
|
2022-11-13 23:26:47 +00:00
|
|
|
show_like_button = get_config('show_like_button')
|
2022-11-14 23:02:22 +00:00
|
|
|
player.volume = get_config('mpv_volume')
|
2022-11-01 10:15:28 +00:00
|
|
|
requested_radio = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'custom_radio': id_radio,
|
|
|
|
'radio_type': type_radio,
|
|
|
|
'related_object_id': related_object
|
|
|
|
}
|
2022-11-01 10:15:28 +00:00
|
|
|
radio_session_id = post_radio_session(requested_radio).get('id')
|
2022-11-07 23:40:26 +00:00
|
|
|
for i in range(0, 2):
|
2023-06-14 20:05:14 +00:00
|
|
|
try:
|
|
|
|
radio_get_track(radio_session_id, first_run=True)
|
|
|
|
except Exception as E:
|
|
|
|
return list_radios(error_given=f'Error: {E}')
|
2022-11-02 00:05:08 +00:00
|
|
|
|
2022-11-06 00:45:56 +00:00
|
|
|
radio_event_gen.set()
|
2022-12-18 01:02:53 +00:00
|
|
|
radio_task = threading.Thread(
|
|
|
|
target=radio_generator, args=(radio_session_id,), daemon=True)
|
2022-11-02 00:05:08 +00:00
|
|
|
radio_task.start()
|
2022-12-18 01:02:53 +00:00
|
|
|
player_items_menu = ['Next', 'Prev', 'Pause', 'Download', 'Info']
|
2022-11-29 18:56:33 +00:00
|
|
|
|
2022-11-18 10:22:55 +00:00
|
|
|
if show_like_button:
|
|
|
|
player_items_menu.append('Like')
|
|
|
|
player_items_menu.extend(['Hide artist', 'Exit'])
|
2022-11-02 00:05:08 +00:00
|
|
|
while True:
|
|
|
|
try:
|
2022-11-29 18:56:33 +00:00
|
|
|
if player.pause:
|
|
|
|
player_items_menu[2] = 'Play'
|
|
|
|
else:
|
|
|
|
player_items_menu[2] = 'Pause'
|
2023-06-14 20:05:14 +00:00
|
|
|
try:
|
|
|
|
select = fzf.prompt(player_items_menu,
|
2023-06-04 10:52:50 +00:00
|
|
|
quote(f"--header=\'Radio {name} playing...\'"))[0]
|
2023-06-14 20:05:14 +00:00
|
|
|
except:
|
|
|
|
select = 'Exit'
|
|
|
|
|
2022-11-02 00:05:08 +00:00
|
|
|
if select == 'Next':
|
2022-12-24 16:44:44 +00:00
|
|
|
playlist_remaining = player.playlist_count - player.playlist_current_pos
|
2022-11-24 01:12:34 +00:00
|
|
|
if playlist_remaining <= 2:
|
2022-12-18 01:02:53 +00:00
|
|
|
threading.Thread(target=radio_get_track, args=(
|
|
|
|
radio_session_id,), daemon=True).start()
|
2022-12-20 01:33:29 +00:00
|
|
|
if playlist_remaining > 1:
|
|
|
|
player.playlist_next()
|
|
|
|
else:
|
|
|
|
print('No more tracks, please wait for new...')
|
|
|
|
time.sleep(3)
|
2022-11-02 00:05:08 +00:00
|
|
|
elif select == 'Prev':
|
|
|
|
player.playlist_prev()
|
2022-11-18 10:22:55 +00:00
|
|
|
elif select in ('Pause', 'Play'):
|
2022-11-02 00:05:08 +00:00
|
|
|
if player.pause:
|
|
|
|
player.pause = False
|
|
|
|
else:
|
|
|
|
player.pause = True
|
2023-06-03 22:24:44 +00:00
|
|
|
elif select == 'Hide artist':
|
|
|
|
track = player_fw_storage.storage.get(track_url_to_uuid())
|
|
|
|
hide_content(
|
|
|
|
{'target': {'id': track.get('artist').get('id'), 'type': 'artist'}})
|
2022-11-06 00:45:56 +00:00
|
|
|
elif select == 'Download':
|
2022-11-18 15:57:25 +00:00
|
|
|
name_downloaded = download_track(player.stream_open_filename)
|
2022-11-07 23:40:26 +00:00
|
|
|
elif select == 'Info':
|
2022-12-07 23:24:48 +00:00
|
|
|
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)
|
2022-11-18 10:22:55 +00:00
|
|
|
elif select == 'Like':
|
2022-12-18 01:02:53 +00:00
|
|
|
favorite_track(player_fw_storage.storage.get(
|
|
|
|
track_url_to_uuid())['id'])
|
2022-11-02 00:05:08 +00:00
|
|
|
elif select == 'Exit':
|
2023-06-14 18:39:47 +00:00
|
|
|
radio_event_gen.clear()
|
2023-06-11 12:10:24 +00:00
|
|
|
soft_volume_reduce()
|
2022-11-02 00:05:08 +00:00
|
|
|
player.playlist_clear()
|
|
|
|
player.stop()
|
2022-12-07 23:24:48 +00:00
|
|
|
player_fw_storage.storage = {}
|
2022-11-02 00:05:08 +00:00
|
|
|
break
|
2023-06-14 18:39:47 +00:00
|
|
|
except Exception as E:
|
|
|
|
radio_event_gen.clear()
|
2022-11-09 18:51:20 +00:00
|
|
|
player.playlist_clear()
|
|
|
|
player.stop()
|
2022-12-07 23:24:48 +00:00
|
|
|
player_fw_storage.storage = {}
|
2023-06-14 18:39:47 +00:00
|
|
|
logger.exception(f'Radio force stopped: {E}')
|
2022-11-02 00:05:08 +00:00
|
|
|
break
|
2022-11-01 10:15:28 +00:00
|
|
|
|
|
|
|
|
2023-06-14 20:05:14 +00:00
|
|
|
def radio_get_track(radio_session_id, first_run=False):
|
2022-11-01 10:15:28 +00:00
|
|
|
radio_context = get_track_radio({'session': radio_session_id})
|
2022-11-06 22:21:49 +00:00
|
|
|
if not radio_context:
|
|
|
|
return
|
2022-11-09 18:51:20 +00:00
|
|
|
if isinstance(radio_context, str):
|
|
|
|
logger.error(radio_context)
|
2022-11-10 20:21:56 +00:00
|
|
|
if radio_context == "Radio doesn't have more candidates":
|
|
|
|
radio_event_gen.clear()
|
2023-06-14 20:05:14 +00:00
|
|
|
if first_run:
|
|
|
|
radio_context = 'This radio may be private or haven\'t tracks'
|
|
|
|
raise IOError(radio_context)
|
2022-11-09 18:51:20 +00:00
|
|
|
return
|
|
|
|
if radio_context.get('error'):
|
|
|
|
logger.error(radio_context.get('error'))
|
2022-11-02 23:58:55 +00:00
|
|
|
return
|
|
|
|
else:
|
|
|
|
track = radio_context.get('track')
|
2022-11-18 15:57:25 +00:00
|
|
|
listen_url = track['listen_url']
|
2022-12-07 23:24:48 +00:00
|
|
|
player_fw_storage.storage[track_url_to_uuid(listen_url)] = track
|
2022-12-18 01:02:53 +00:00
|
|
|
player.loadfile(get_audio_file(
|
|
|
|
listen_url, listen_url=True), 'append-play')
|