diff --git a/CHANGELOG.md b/CHANGELOG.md index bcadd52..61a4a22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.0.1 + +1. Fix broken install on windows +2. Fix recording issues on windows + ## 4.0.0 1. Shazam !! song identification built-in 🚀 diff --git a/README.md b/README.md index 0811b20..19f78d9 100644 --- a/README.md +++ b/README.md @@ -284,7 +284,7 @@ A complex filter example: `--filter "country!=CA&tags!=islamic,classical&votes>5 ### Default Configs -Default configuration file is added into your home directory as `.radio-active-configs.ini` +Default configuration file is located at ~/radioactive/config.ini ```bash [AppConfig] @@ -293,7 +293,7 @@ limit = 100 sort = votes filter = none volume = 80 -filepath = /home/{user}/radioactive/recordings/ +filepath = {home}/radioactive/recordings/ filetype = mp3 player = ffplay ``` diff --git a/radioactive/actions.py b/radioactive/actions.py index de39131..83c805a 100644 --- a/radioactive/actions.py +++ b/radioactive/actions.py @@ -485,6 +485,7 @@ def handle_shazam(target_url: str): # Create temp file temp_dir = tempfile.gettempdir() temp_file = os.path.join(temp_dir, "radioactive_shazam.mp3") + log.debug(f"temp_file: {temp_file}") # ffmpeg command to record 7 seconds # we use libmp3lame to ensure it's a valid mp3 for shazam diff --git a/radioactive/app.py b/radioactive/app.py index b606a3e..5be146a 100644 --- a/radioactive/app.py +++ b/radioactive/app.py @@ -18,7 +18,7 @@ def __init__(self): try: self.__VERSION__ = metadata.version("radio-active") except metadata.PackageNotFoundError: - self.__VERSION__ = "4.0.0" # change this on every update # + self.__VERSION__ = "4.0.1" # change this on every update # self.pypi_api = "https://pypi.org/pypi/radio-active/json" self.remote_version = "" diff --git a/radioactive/config.py b/radioactive/config.py index d15005d..39c5b23 100644 --- a/radioactive/config.py +++ b/radioactive/config.py @@ -5,6 +5,7 @@ import configparser import getpass +import os import sys from typing import Any, Dict, Optional @@ -16,10 +17,8 @@ def write_a_sample_config_file() -> None: Create a sample configuration file with default settings. Checks for the XDG config path and writes the file there. """ - # Create a ConfigParser object config = configparser.ConfigParser() - - from radioactive.paths import get_recordings_path + from radioactive.paths import get_recordings_path, get_user_home # Add sections and key-value pairs config["AppConfig"] = { @@ -28,7 +27,7 @@ def write_a_sample_config_file() -> None: "sort": "votes", "filter": "none", "volume": "80", - "filepath": get_recordings_path(), + "filepath": os.path.join("{home}", "radioactive", "recordings"), "filetype": "mp3", "player": "ffplay", } @@ -85,16 +84,22 @@ def get_option(key: str, default: str = "") -> str: options["sort"] = get_option("sort", "votes") options["filter"] = get_option("filter", "none") options["limit"] = get_option("limit", "100") - from radioactive.paths import get_recordings_path + from radioactive.paths import get_recordings_path, get_user_home options["filepath"] = get_option("filepath", get_recordings_path()) - # if filepath has any placeholder, replace {user} to actual user map if "{user}" in options["filepath"]: options["filepath"] = options["filepath"].replace( "{user}", getpass.getuser() ) + if "{home}" in options["filepath"]: + options["filepath"] = options["filepath"].replace( + "{home}", get_user_home() + ) + + options["filepath"] = os.path.expanduser(options["filepath"]) + options["filetype"] = get_option("filetype", "mp3") options["player"] = get_option("player", "ffplay") diff --git a/radioactive/recorder.py b/radioactive/recorder.py index 1106586..4461a20 100644 --- a/radioactive/recorder.py +++ b/radioactive/recorder.py @@ -36,6 +36,7 @@ def record_audio_from_url(input_url, output_file, force_mp3, loglevel, duration= Record audio from a URL using FFmpeg. Returns the subprocess.Popen object to allow UI tracking. """ + log.debug(f"Recording audio from {input_url} to {output_file}") try: ffmpeg_command = [ "ffmpeg", @@ -75,6 +76,8 @@ def record_audio_from_url(input_url, output_file, force_mp3, loglevel, duration= ) return process + except FileNotFoundError: + log.error("FFmpeg not found! Please install FFmpeg to use the recording feature.") except Exception as ex: log.error(f"Error while starting recording: {ex}") return None diff --git a/radioactive/utilities.py b/radioactive/utilities.py index 95c459f..201871d 100644 --- a/radioactive/utilities.py +++ b/radioactive/utilities.py @@ -5,10 +5,8 @@ import os import sys -import termios import threading import time -import tty from random import randint from typing import Any, Dict, List, Optional, Tuple, Union @@ -132,22 +130,41 @@ def handle_station_selection_menu(handler, last_station, alias) -> Tuple[str, st def get_key(): - """Helper to capture single key on Linux.""" - import sys - import termios - import tty + """Helper to capture single key on Linux and Windows.""" + if sys.platform == "win32": + import msvcrt + + ch = msvcrt.getch() + if ch in [b"\x00", b"\xe0"]: # Special keys + ch2 = msvcrt.getch() + if ch2 == b"M": # Right arrow + return "\x1b[C" + return "" + + if ch == b"\r": + return "\n" + if ch == b"\x08": + return "\x08" - fd = sys.stdin.fileno() - old_settings = termios.tcgetattr(fd) - try: - tty.setraw(sys.stdin.fileno()) - ch = sys.stdin.read(1) - if ch == "\x1b": # Escape sequence - seq = sys.stdin.read(2) - ch += seq - finally: - termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) - return ch + try: + return ch.decode("utf-8") + except: + return "" + else: + import termios + import tty + + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + if ch == "\x1b": # Escape sequence + seq = sys.stdin.read(2) + ch += seq + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch def handle_vim_style_prompt(alias, history) -> str: