added some media keys
This commit is contained in:
1 parent
14ac9b197d
commit
6d37093b26
2 files changed
+82
-10
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import multiprocessing
|
||||
import configparser
|
||||
import logging
|
||||
import asyncio
|
||||
@@ -11,10 +12,6 @@ LOG_FILE = 'textual.log'
|
||||
LOGGING_LEVEL = logging.DEBUG
|
||||
LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
|
||||
|
||||
# Clear Log File
|
||||
if os.path.exists(LOG_FILE):
|
||||
os.remove(LOG_FILE)
|
||||
|
||||
# Read config file
|
||||
config = configparser.ConfigParser()
|
||||
config.read('config.ini')
|
||||
@@ -25,16 +22,11 @@ BITRATE = re.findall(r'[0-9]+', BITRATE)[0]
|
||||
BITRATE = int(BITRATE) if BITRATE else BITRATE
|
||||
IMAGE_MODE = config.getboolean('GENERAL', 'GUI')
|
||||
|
||||
os.makedirs(".cache/art/", exist_ok=True)
|
||||
os.makedirs(".cache/audio/", exist_ok=True)
|
||||
os.makedirs(".cache/art/artists/", exist_ok=True)
|
||||
|
||||
logging.basicConfig(filename=LOG_FILE, level=LOGGING_LEVEL, format=LOG_FORMAT)
|
||||
|
||||
import SubSonic
|
||||
|
||||
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
|
||||
import pygame
|
||||
import pynput
|
||||
|
||||
from rich.text import Text
|
||||
|
||||
@@ -967,6 +959,45 @@ class MainView(Screen):
|
||||
queue_table.update_queue()
|
||||
app.update_now_playing()
|
||||
|
||||
# Startup keyboard listener for media keys
|
||||
def listen_media_keys(queue: multiprocessing.Queue):
|
||||
|
||||
media_log_file = 'media_keys.log'
|
||||
logger = logging.getLogger('media_keys')
|
||||
logger.setLevel(LOGGING_LEVEL)
|
||||
formatter = logging.Formatter('[%(asctime)s] %(levelname)s in %(module)s: %(message)s')
|
||||
handler = logging.FileHandler(media_log_file)
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
|
||||
logger.info('media_key logger initialized')
|
||||
|
||||
try:
|
||||
def on_press(key: pynput.keyboard.Key | pynput.keyboard.KeyCode | None) -> None:
|
||||
logger.debug(f'Process Key: {key}')
|
||||
match key:
|
||||
case pynput.keyboard.Key.media_play_pause:
|
||||
logger.info('Media play/pause key pressed')
|
||||
queue.put('play_pause')
|
||||
case pynput.keyboard.Key.media_next:
|
||||
logger.info('Media next key pressed')
|
||||
queue.put('next')
|
||||
case pynput.keyboard.Key.media_previous:
|
||||
logger.info('Media rewind pressed')
|
||||
queue.put('prev')
|
||||
case pynput.keyboard.Key.media_volume_down:
|
||||
logger.info('Media volume down')
|
||||
queue.put('vdown')
|
||||
case pynput.keyboard.Key.media_volume_up:
|
||||
logger.info('Media volume up')
|
||||
queue.put('udown')
|
||||
with pynput.keyboard.Listener(on_press=on_press) as listener:
|
||||
logger.info('Media key listener started')
|
||||
listener.join()
|
||||
except Exception as e:
|
||||
pass
|
||||
logger.error(f'Media key listener failed: {e}')
|
||||
|
||||
class TextualSubpyPlayer(App):
|
||||
BINDINGS = [
|
||||
("r", "rewind()", "⏪"),
|
||||
@@ -998,12 +1029,17 @@ class TextualSubpyPlayer(App):
|
||||
is_paused: bool = False
|
||||
place: int = 0
|
||||
|
||||
music_command_queue: multiprocessing.Queue
|
||||
|
||||
check_playing_timer: Timer | None = None
|
||||
check_music_commands: Timer
|
||||
|
||||
def on_mount(self) -> None:
|
||||
self.title = "SubPy"
|
||||
self.switch_mode('main')
|
||||
|
||||
self.check_music_commands = self.set_interval(2/3, self._music_player_loop, pause=False)
|
||||
|
||||
@work(exclusive=True)
|
||||
async def play_song(self, song: SubSonic.Song) -> None:
|
||||
self.currently_playing = song
|
||||
@@ -1051,6 +1087,24 @@ class TextualSubpyPlayer(App):
|
||||
# Set callback loop for progress bar
|
||||
# self.progress_timer = self.set_interval(1 / 10, self.update_progress, pause=False)
|
||||
|
||||
def _music_player_loop(self) -> None:
|
||||
if self.music_command_queue.empty():
|
||||
return
|
||||
|
||||
command = self.music_command_queue.get_nowait()
|
||||
|
||||
match command:
|
||||
case "play_pause":
|
||||
self.action_play_pause_song()
|
||||
case "next":
|
||||
self.action_skip()
|
||||
case "prev":
|
||||
self.action_rewind()
|
||||
case "vdown":
|
||||
self.action_volume_down()
|
||||
case "udown":
|
||||
self.action_volume_up()
|
||||
|
||||
def _cache_audio(self, path: str, content: bytes) -> None:
|
||||
"""Helper method to write audio to cache."""
|
||||
with open(path, "wb") as file:
|
||||
@@ -1168,5 +1222,22 @@ class TextualSubpyPlayer(App):
|
||||
logging.debug(event.key)
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.makedirs(".cache/art/", exist_ok=True)
|
||||
os.makedirs(".cache/audio/", exist_ok=True)
|
||||
os.makedirs(".cache/art/artists/", exist_ok=True)
|
||||
|
||||
# Clear Log File
|
||||
if os.path.exists(LOG_FILE):
|
||||
os.remove(LOG_FILE)
|
||||
|
||||
logging.basicConfig(filename=LOG_FILE, level=LOGGING_LEVEL, format=LOG_FORMAT)
|
||||
|
||||
q = multiprocessing.Queue(-1)
|
||||
p = multiprocessing.Process(target=listen_media_keys, args=(q,))
|
||||
p.start()
|
||||
|
||||
app = TextualSubpyPlayer()
|
||||
app.music_command_queue = q
|
||||
|
||||
app.run()
|
||||
p.terminate()
|
||||
Reference in new issue
Block a user