97 lines
7.5 KiB
Python
97 lines
7.5 KiB
Python
"""Bundled station list.
|
|
|
|
Only used when somafm.com cannot be reached *and* no cache exists yet, so the
|
|
app is still useful on a plane. The live list from ``channels.json`` always
|
|
wins. Stream links are built from SomaFM's well-known ``.pls`` naming scheme
|
|
and are additionally resolved at runtime.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
# (id, title, genre, description)
|
|
_CHANNELS: tuple[tuple[str, str, str, str], ...] = (
|
|
("groovesalad", "Groove Salad", "ambient|electronic", "A nicely chilled plate of ambient/downtempo beats and grooves."),
|
|
("dronezone", "Drone Zone", "ambient", "Served best chilled, safe with most medications. Atmospheric textures with minimal beats."),
|
|
("deepspaceone", "Deep Space One", "ambient", "Deep ambient electronic, experimental and space music. For inner and outer space exploration."),
|
|
("spacestation", "Space Station Soma", "electronic", "Tune in, turn on, space out. Spaced-out ambient and mid-tempo electronica."),
|
|
("missioncontrol", "Mission Control", "ambient|electronic", "Celebrating NASA and Space Explorers everywhere."),
|
|
("darkzone", "The Dark Zone", "ambient", "The darker side of deep ambient. Music for staring into the Abyss."),
|
|
("dz2", "Drone Zone 2", "ambient", "A more eclectic alternative mix of atmospheric textures with minimal beats."),
|
|
("synphaera", "Synphaera Radio", "ambient|electronic", "Featuring the music from an independent record label focused on modern electronic ambient and space music."),
|
|
("secretagent", "Secret Agent", "lounge", "The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!"),
|
|
("illstreet", "Illinois Street Lounge", "lounge", "Classic bachelor pad, playful exotica and vintage music of tomorrow."),
|
|
("tikitime", "Tiki Time", "tiki|world", "Classic Tiki music and Vintage island rhythms to sip cocktails by."),
|
|
("bossa", "Bossa Beyond", "bossanova|world", "Silky-smooth, laid-back Brazilian-style rhythms of Bossa Nova, Samba and beyond"),
|
|
("suburbsofgoa", "Suburbs of Goa", "world", "Desi-influenced Asian world beats and beyond."),
|
|
("thistle", "ThistleRadio", "celtic|world", "Exploring music from Celtic roots and branches"),
|
|
("indiepop", "Indie Pop Rocks!", "alternative|rock", "New and classic favorite indie pop tracks."),
|
|
("digitalis", "Digitalis", "electronic|alternative", "Digitally affected analog rock to calm the agitated heart."),
|
|
("poptron", "PopTron", "alternative", "Electropop and indie dance rock with sparkle and pop."),
|
|
("u80s", "Underground 80s", "alternative|electronic", "Early 80s UK Synthpop and a bit of New Wave."),
|
|
("seventies", "Left Coast 70s", "70s|rock", "Mellow album rock from the Seventies. Yacht not required."),
|
|
("reggae", "Heavyweight Reggae", "reggae", "Reggae, Ska, Rocksteady classic and deep tracks."),
|
|
("bootliquor", "Boot Liquor", "americana", "Americana Roots music for Cowhands, Cowpokes and Cowtippers"),
|
|
("folkfwd", "Folk Forward", "folk|alternative", "Indie Folk, Alt-folk and the occasional folk classics."),
|
|
("lush", "Lush", "electronic", "Sensuous and mellow female vocals, many with an electronic influence."),
|
|
("fluid", "Fluid", "electronic|hiphop", "Drown in the electronic sound of instrumental hiphop, future soul and liquid trap."),
|
|
("beatblender", "Beat Blender", "electronic", "A late night blend of deep-house and downtempo chill."),
|
|
("cliqhop", "cliqhop idm", "electronic", "Blips'n'beeps backed mostly w/beats. Intelligent Dance Music."),
|
|
("thetrip", "The Trip", "electronic", "Progressive house / trance. Tip top tunes."),
|
|
("defcon", "DEF CON Radio", "electronic|specials", "Music for Hacking. The DEF CON Year-Round Channel."),
|
|
("dubstep", "Dub Step Beyond", "electronic", "Dubstep, Dub and Deep Bass. May damage speakers at high volume."),
|
|
("vaporwaves", "Vaporwaves", "electronic", "All Vaporwave. All the time."),
|
|
("sonicuniverse", "Sonic Universe", "jazz", "Transcending the world of jazz with eclectic, avant-garde takes on tradition."),
|
|
("metal", "Metal Detector", "metal", "From black to doom, prog to sludge, thrash to post, stoner to crossover, punk to industrial."),
|
|
("doomed", "Doomed", "ambient|industrial", "Where every day is Halloween: Dark industrial/ambient music for tortured souls."),
|
|
("covers", "Covers", "eclectic", "Just covers. Songs you know by artists you don't. We've got you covered."),
|
|
("brfm", "Black Rock FM", "eclectic", "From the Black Rock Desert playa to the world, year round!"),
|
|
("7soul", "Seven Inch Soul", "oldies", "Vintage soul tracks from the original 45 RPM vinyl."),
|
|
("insound", "The In-Sound", "oldies", "60s/70s Hipster Euro Pop where psychedelic melodies meets groovy vibes."),
|
|
("sf1033", "SF 10-33", "ambient|news", "Ambient music mixed with the sounds of San Francisco public safety radio traffic."),
|
|
("scanner", "SF Police Scanner", "live|news", "San Francisco Public Safety Scanner Feed"),
|
|
("sfinsf", "SF in SF", "spoken", "Author readings and discussions from the science fiction, fantasy, horror, and genre literary fields."),
|
|
("live", "SomaFM Live", "live|specials", "Special Live Events and rebroadcasts of past live events"),
|
|
("specials", "SomaFM Specials", "specials", "Now featuring Afternoon Jazz, Wavepool, DubX, The Surf Report & More!"),
|
|
("n5md", "n5MD Radio", "specials", "Emotional Experiments in Music: Ambient, modern composition, post-rock, & experimental electronic music"),
|
|
("chillits", "Chillits Radio", "chill|live", "Celebrating 25 years of music, chilling and camping"),
|
|
("groovesalad2", "Groove Salad 2", "ambient|electronic", "A different mix of nicely chilled ambient/downtempo beats and grooves."),
|
|
("gsclassic", "Groove Salad Classic", "ambient|electronic", "The classic (early 2000s) version of a nicely chilled plate of ambient/downtempo beats and grooves."),
|
|
("christmas", "Christmas Lounge", "holiday", "Chilled holiday grooves and classic winter lounge tracks."),
|
|
("xmasrocks", "Christmas Rocks!", "holiday", "Have yourself an indie/alternative holiday season!"),
|
|
("jollysoul", "Jolly Ol' Soul", "holiday", "Where we cut right to the soul of the season."),
|
|
("deptstore", "Department Store Christmas", "holiday", "Holiday Elevator Music from a more innocent time."),
|
|
("xmasinfrisko", "Xmas in Frisko", "holiday", "SomaFM's wacky and eclectic holiday mix. Not for the easily offended."),
|
|
)
|
|
|
|
|
|
def _playlists(channel_id: str) -> list[dict[str, str]]:
|
|
return [
|
|
{"url": f"https://somafm.com/{channel_id}.pls", "format": "mp3", "quality": "highest"},
|
|
{"url": f"https://somafm.com/{channel_id}130.pls", "format": "aac", "quality": "highest"},
|
|
{"url": f"https://somafm.com/{channel_id}64.pls", "format": "aacp", "quality": "high"},
|
|
{"url": f"https://somafm.com/{channel_id}32.pls", "format": "aacp", "quality": "low"},
|
|
]
|
|
|
|
|
|
def fallback_channels() -> list[dict[str, Any]]:
|
|
"""Return a channels.json-shaped payload so the normal parser can eat it."""
|
|
payload: list[dict[str, Any]] = []
|
|
for channel_id, title, genre, description in _CHANNELS:
|
|
payload.append(
|
|
{
|
|
"id": channel_id,
|
|
"title": title,
|
|
"description": description,
|
|
"dj": "SomaFM",
|
|
"genre": genre,
|
|
"image": f"https://somafm.com/logos/256/{channel_id}256.png",
|
|
"largeimage": f"https://somafm.com/logos/512/{channel_id}512.png",
|
|
"playlists": _playlists(channel_id),
|
|
"listeners": "0",
|
|
"lastPlaying": "",
|
|
}
|
|
)
|
|
return payload
|