coder-music-cli 0.8.3__tar.gz → 0.8.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/PKG-INFO +1 -1
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/coder_music_cli.egg-info/PKG-INFO +1 -1
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/__init__.py +1 -1
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/cli.py +29 -4
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/config.py +57 -1
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/pyproject.toml +1 -1
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/LICENSE +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/README.md +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/coder_music_cli.egg-info/SOURCES.txt +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/coder_music_cli.egg-info/dependency_links.txt +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/coder_music_cli.egg-info/entry_points.txt +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/coder_music_cli.egg-info/requires.txt +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/coder_music_cli.egg-info/top_level.txt +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/__main__.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/ai_tracks.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/client.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/context/__init__.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/context/mood.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/context/temporal.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/daemon.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/hf_cache.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/history.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/model_manager.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/platform/__init__.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/platform/ipc.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/platform/paths.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/platform/player_control.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/player/__init__.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/player/base.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/player/ffplay.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/__init__.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_generator.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/__init__.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/audioldm_strategy.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/bark_strategy.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/model_config.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/model_registry.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/model_strategy.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/musicgen_strategy.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/progress_callback.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/strategy_cache.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/local.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/radio.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/youtube.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/youtube_cache.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/setup.cfg +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/tests/test_ai_tracks.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/tests/test_config.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/tests/test_context.py +0 -0
- {coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/tests/test_history.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coder-music-cli
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.4
|
|
4
4
|
Summary: A command-line music application for coders with daemon support, radio streaming, and AI-generated music
|
|
5
5
|
Author-email: Luong Nguyen <luongnv89@gmail.com>
|
|
6
6
|
Maintainer-email: Luong Nguyen <luongnv89@gmail.com>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coder-music-cli
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.4
|
|
4
4
|
Summary: A command-line music application for coders with daemon support, radio streaming, and AI-generated music
|
|
5
5
|
Author-email: Luong Nguyen <luongnv89@gmail.com>
|
|
6
6
|
Maintainer-email: Luong Nguyen <luongnv89@gmail.com>
|
|
@@ -416,7 +416,7 @@ def radios_group(ctx):
|
|
|
416
416
|
def radios_list():
|
|
417
417
|
"""List all available radio stations."""
|
|
418
418
|
config = get_config()
|
|
419
|
-
radios = config.
|
|
419
|
+
radios = config.get_radios_categorized()
|
|
420
420
|
|
|
421
421
|
if not radios:
|
|
422
422
|
click.echo(f"No stations configured. Add stations to: {config.radios_file}")
|
|
@@ -424,10 +424,35 @@ def radios_list():
|
|
|
424
424
|
return
|
|
425
425
|
|
|
426
426
|
click.echo("Available radio stations:\n")
|
|
427
|
-
for i, (name, _url) in enumerate(radios, 1):
|
|
428
|
-
click.echo(f" {i:2}. {name}")
|
|
429
427
|
|
|
430
|
-
|
|
428
|
+
# Group stations by category
|
|
429
|
+
categories: dict[str, list[dict]] = {}
|
|
430
|
+
for station in radios:
|
|
431
|
+
cat = station["category"]
|
|
432
|
+
if cat not in categories:
|
|
433
|
+
categories[cat] = []
|
|
434
|
+
categories[cat].append(station)
|
|
435
|
+
|
|
436
|
+
# Display each category
|
|
437
|
+
for category, stations in categories.items():
|
|
438
|
+
click.echo(f" [{category}]")
|
|
439
|
+
|
|
440
|
+
# Display in 2 columns
|
|
441
|
+
col_width = 32 # Width for each column
|
|
442
|
+
for i in range(0, len(stations), 2):
|
|
443
|
+
left = stations[i]
|
|
444
|
+
left_str = f" {left['index']:2}. {left['name'][: col_width - 8]}"
|
|
445
|
+
|
|
446
|
+
if i + 1 < len(stations):
|
|
447
|
+
right = stations[i + 1]
|
|
448
|
+
right_str = f"{right['index']:2}. {right['name'][: col_width - 5]}"
|
|
449
|
+
click.echo(f"{left_str:<{col_width}}{right_str}")
|
|
450
|
+
else:
|
|
451
|
+
click.echo(left_str)
|
|
452
|
+
|
|
453
|
+
click.echo() # Empty line after each category
|
|
454
|
+
|
|
455
|
+
click.echo(f"Total: {len(radios)} station(s)")
|
|
431
456
|
click.echo("Play with: music-cli radios play <number>")
|
|
432
457
|
|
|
433
458
|
|
|
@@ -197,7 +197,7 @@ Top Hits|https://streams.ilovemusic.de/iloveradio1.mp3
|
|
|
197
197
|
Rock Radio|https://streams.ilovemusic.de/iloveradio3.mp3
|
|
198
198
|
Metal [SomaFM]|http://ice1.somafm.com/metal-128-mp3
|
|
199
199
|
|
|
200
|
-
# Synthwave
|
|
200
|
+
# Synthwave/Retrowave
|
|
201
201
|
Nightride FM|https://stream.nightride.fm/nightride.mp3
|
|
202
202
|
Chillsynth FM|https://stream.nightride.fm/chillsynth.mp3
|
|
203
203
|
Darksynth FM|https://stream.nightride.fm/darksynth.mp3
|
|
@@ -354,6 +354,62 @@ Radio Capital|https://icecast.unitedradio.it/Capital.mp3
|
|
|
354
354
|
radios.append((line, line))
|
|
355
355
|
return radios
|
|
356
356
|
|
|
357
|
+
def get_radios_categorized(self) -> list[dict]:
|
|
358
|
+
"""Load radio stations with category information.
|
|
359
|
+
|
|
360
|
+
Returns list of dicts with keys: index, name, url, category
|
|
361
|
+
Category is extracted from comment lines in radios.txt.
|
|
362
|
+
"""
|
|
363
|
+
radios: list[dict] = []
|
|
364
|
+
if not self.radios_file.exists():
|
|
365
|
+
return radios
|
|
366
|
+
|
|
367
|
+
current_category = "Other"
|
|
368
|
+
station_index = 0
|
|
369
|
+
|
|
370
|
+
for line in self.radios_file.read_text().splitlines():
|
|
371
|
+
line = line.strip()
|
|
372
|
+
if not line:
|
|
373
|
+
continue
|
|
374
|
+
|
|
375
|
+
if line.startswith("#"):
|
|
376
|
+
# Check for major category (e.g., "# ========== ENGLISH ==========")
|
|
377
|
+
if "==========" in line:
|
|
378
|
+
# Extract category name between equals signs
|
|
379
|
+
category = line.replace("=", "").replace("#", "").strip()
|
|
380
|
+
if category:
|
|
381
|
+
current_category = category
|
|
382
|
+
# Check for subcategory (e.g., "# Chill/Lo-fi")
|
|
383
|
+
elif not line.startswith("# Format:") and not line.startswith("# Add"):
|
|
384
|
+
subcategory = line.lstrip("#").strip()
|
|
385
|
+
if subcategory and not subcategory.startswith("Format"):
|
|
386
|
+
current_category = subcategory
|
|
387
|
+
continue
|
|
388
|
+
|
|
389
|
+
# Parse station
|
|
390
|
+
station_index += 1
|
|
391
|
+
if "|" in line:
|
|
392
|
+
name, url = line.split("|", 1)
|
|
393
|
+
radios.append(
|
|
394
|
+
{
|
|
395
|
+
"index": station_index,
|
|
396
|
+
"name": name.strip(),
|
|
397
|
+
"url": url.strip(),
|
|
398
|
+
"category": current_category,
|
|
399
|
+
}
|
|
400
|
+
)
|
|
401
|
+
else:
|
|
402
|
+
radios.append(
|
|
403
|
+
{
|
|
404
|
+
"index": station_index,
|
|
405
|
+
"name": line,
|
|
406
|
+
"url": line,
|
|
407
|
+
"category": current_category,
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
return radios
|
|
412
|
+
|
|
357
413
|
def get_radio_by_index(self, index: int) -> tuple[str, str] | None:
|
|
358
414
|
"""Get a radio station by its 1-based index.
|
|
359
415
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "coder-music-cli"
|
|
7
|
-
version = "0.8.
|
|
7
|
+
version = "0.8.4"
|
|
8
8
|
description = "A command-line music application for coders with daemon support, radio streaming, and AI-generated music"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/coder_music_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/audioldm_strategy.py
RENAMED
|
File without changes
|
{coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/bark_strategy.py
RENAMED
|
File without changes
|
|
File without changes
|
{coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/model_registry.py
RENAMED
|
File without changes
|
{coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/model_strategy.py
RENAMED
|
File without changes
|
{coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/musicgen_strategy.py
RENAMED
|
File without changes
|
{coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/progress_callback.py
RENAMED
|
File without changes
|
{coder_music_cli-0.8.3 → coder_music_cli-0.8.4}/music_cli/sources/ai_models/strategy_cache.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|