Skip to content

v4.1.0#151

Open
deep5050 wants to merge 17 commits intomainfrom
bugfix
Open

v4.1.0#151
deep5050 wants to merge 17 commits intomainfrom
bugfix

Conversation

@deep5050
Copy link
Copy Markdown
Owner

@deep5050 deep5050 commented Apr 25, 2026

4.1.0

  1. Significant improvements on app loading speed ⚡
  2. Recording quality improved 🎶
  3. Faster station lookup
  4. Optimize interaction with external player, improving play/pause time
  5. Improved fuzzy find logic 🔍
  6. Stability improvements for windows
  7. Critical bug fixes 🐛
  8. Minor UI fixes

deep5050 added 15 commits April 25, 2026 21:42
1. add timeout and FileNotFoundError handling to record_audio_auto_codec
   - Added timeout=10 to subprocess.check_output to prevent indefinite
     blocking on unreachable streams
   - Added FileNotFoundError catch for missing ffprobe binary
   - Extended except clause to also catch subprocess.TimeoutExpired

2. add missing return None in FileNotFoundError handler, remove dead except block
   - record_audio_from_url was missing 'return None' in the FileNotFoundError
     handler; caller (handle_record) would crash with TypeError unpacking None
   - Removed unreachable duplicate 'except Exception' block (dead code);
     merged its debug log into the surviving handler
…esult handler

handle_user_choice_from_search_result was calling sys.exit(1) on bad
user input (out-of-range ID, non-integer, or unexpected exception).
This killed the entire application instead of returning control to the
interactive command prompt in handle_listen_keypress.

Also fixed an off-by-one in the 'random' branch:
  randint(1, len(response) - 1) skipped the last search result;
  corrected to randint(1, len(response)) (inclusive on both ends).
…dead quit branch

- v+, v-, and 'v <n>' all called player.volume / player.set_volume()
  without checking if player is None, causing AttributeError when no
  station has been selected yet; added 'if player:' guard to all three
- Removed the unreachable duplicate 'elif user_input in ["q","Q","quit"]'
  branch at the bottom of handle_listen_keypress; the first quit branch
  at line 622 always matched first, making the second one dead code;
  additionally the dead branch called player.stop() without a None guard
- 'help' command now correctly routes to handle_runtime_help_menu()
  alongside '?'; previously typing 'help' fell through to fuzzy search
- auto_fetcher.update_url() is now called after fuzzy-play station
  switch so the AutoFetcher polls the correct new stream URL
…her on station cycle

- The 'n'/'next' command called player.stop()/play() unconditionally;
  when player is None (no station playing yet) this raised AttributeError
- Added 'if player:' guard around the stop/url/play block
- auto_fetcher.update_url() was never called after cycling to a new
  station via 'next', leaving the AutoFetcher polling the old stream URL;
  added the call after target_url is updated
…ecific exceptions

The bare 'except:' clause caught BaseException, including
KeyboardInterrupt and SystemExit, silently swallowing them and
making Ctrl+C unresponsive on Windows.
Narrowed to 'except (UnicodeDecodeError, ValueError):' which covers
the only realistic failure modes of bytes.decode().
…unction

Using a mutable list as a default argument (matches=[]) is a classic
Python gotcha: the list is created once at function definition and
shared across all calls, causing state to leak between invocations.
Replaced with the idiomatic 'matches=None' + 'if matches is None: matches = []'
pattern to ensure each call gets a fresh list.
The fallback for missing 'stationuuid' was itself a dict access
(last_station_info["uuid_or_url"]) inside an except block.
If both keys are absent (e.g. corrupted last-station file) this raised
a second KeyError inside the handler, crashing the selection menu.
Replaced the try/except chain with a safe .get() cascade that returns
an empty string as a last resort instead of raising.
…child process

- open(os.devnull, 'w') was called without keeping a reference to the
  file objects; the anonymous handles could never be explicitly closed,
  causing a file descriptor leak in a long-running background process.
  Assigned them to named variables and close them before sys.exit().
- Replaced bare 'except:' around signal.pause() with
  'except (AttributeError, OSError):' to stop silently swallowing
  KeyboardInterrupt and SystemExit in the child process.
…imports and executing blocking network operations in background threads
…s with empty list returns for graceful error handling
…g logic

Added defensive checks in generate_map to gracefully skip invalid lines, ensuring the application remains stable even if the data file is manually edited or corrupted.

Refactored add_entry to update the in-memory state directly after appending to the file. This eliminates the need for a redundant file re-scan, making the "Add to Favorite" operation much faster and more efficient.

Ensured that the favorite map and dictionary are properly reset during refreshes to prevent duplicate entries or stale data from persisting in memory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant