Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
],
"files.autoSave": "off",
"editor.wordWrap": "wordWrapColumn",
"workbench.colorTheme": "GitHub Dark",
"editor.minimap.autohide": true,
"workbench.colorTheme": "Visual Studio Light",
"editor.minimap.autohide": "mouseover",
"editor.minimap.renderCharacters": false,
"editor.experimentalWhitespaceRendering": "font",
"editor.fontFamily": "'Fira Code', Consolas, 'Courier New', monospace",
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ SRC_DIR = "radioactive"
TEST_DIR = "test"

.PHONY: all clean isort check dist deploy test-deploy help build install install-dev test
all: clean isort format check build install
all: clean isort format check configure build install

configure:
@echo "Configuring features..."
${PYTHON} configure.py

check:
@echo "Chceking linting errors......."
Expand Down
24 changes: 19 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
- [x] Discovers stations by language
- [x] VLC, MPV player support
- [x] Default config file
- [x] Sleep Timer (pomodoro) ⏲️
- [ ] I'm feeling lucky! Play Random stations


Expand Down Expand Up @@ -144,7 +145,7 @@ Search a station with `radio --search [STATION_NAME]` or simply `radio` :zap: to
| `--uuid`, `-U` | Optional | ID of the station | None | |
| `--record` , `-R` | Optional | Record a station and save to file | False | |
| `--filename`, `-N` | Optional | Filename to used to save the recorded audio | None | |
| `--filepath` | Optional | Path to save the recordings | <DEFAULT_DIR> | |
| `--filepath` | Optional | Path to save the recordings | `~/radioactive/recordings` | |
| `--filetype`, `-T` | Optional | Format of the recording | mp3 | `mp3`,`auto` |
| `--last` | Optional | Play last played station | False | |
| `--random` | Optional | Play a random station from favorite list | False | |
Expand Down Expand Up @@ -185,7 +186,7 @@ Search a station with `radio --search [STATION_NAME]` or simply `radio` :zap: to

> `--filetype`: Specify the extension of the final recording file. default is `mp3`. you can provide `-T auto` to autodetect the codec and set file extension accordingly (in original form).

> DEFAULT_DIR: is `/home/user/Music/radioactive`


### Runtime Commands

Expand All @@ -197,6 +198,9 @@ Enter a command to perform an action: ?
t/T/track: Current song name (track info)
r/R/record: Record a station
f/F/fav: Add station to favorite list
s/S/search: Search for a new station
n/N/next: Play next station from search results or favorite list
timer/sleep: Set a sleep timer (duration in minutes)
rf/RF/recordfile: Specify a filename for the recording.
h/H/help/?: Show this help message
q/Q/quit: Quit radioactive
Expand Down Expand Up @@ -258,13 +262,23 @@ limit = 100
sort = votes
filter = none
volume = 80
filepath = /home/{user}/recordings/radioactive/
filepath = /home/{user}/radioactive/recordings/
filetype = mp3
player = ffplay
```

### Configuration Paths
All the data files are stored in a folder called `radioactive` under your user home directory.

- **Configuration**: `~/radioactive/config.ini`
- **Favorites**: `~/radioactive/alias_map`
- **Last Station**: `~/radioactive/last_station`
- **Recordings**: `~/radioactive/recordings`

Legacy configuration files are automatically migrated to this new location on the first run.

> [!WARNING]
> Do NOT modify the keys, only change the values. you can give any absolute or relative path as filepath.
> Do NOT modify the keys, only change the values.

### Bonus Tips

Expand All @@ -282,7 +296,7 @@ see [CHANGELOG](./CHANGELOG.md)

Share you favorite list with our community 🌐 ➡️ [Here](https://github.com/deep5050/radio-active/discussions/10)

> Your favorite list `.radio-active-alias` is under your home directory as a hidden file :)
> Your favorite list `alias_map` is under `~/radioactive/` directory.


### Support
Expand Down
49 changes: 49 additions & 0 deletions configure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

import os

CONFIG_FILE = "features.conf"
FEATURE_FLAGS_FILE = "radioactive/feature_flags.py"

def generate_flags():
print(f"Generating {FEATURE_FLAGS_FILE} from {CONFIG_FILE}...")

flags = {}
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
if "=" in line:
key, value = line.split("=", 1)
flags[key.strip()] = value.strip().lower() == "true"
else:
print(f"Warning: {CONFIG_FILE} not found. Using defaults.")
# Default flags if config is missing
flags["RECORDING_FEATURE"] = True
flags["TRACK_FEATURE"] = True
flags["SEARCH_FEATURE"] = True
flags["CYCLE_FEATURE"] = True
flags["INFO_FEATURE"] = True
flags["TIMER_FEATURE"] = True
flags["MINIMAL_FEATURE"] = False

# Apply limits if MINIMAL_FEATURE is True
if flags.get("MINIMAL_FEATURE", False):
print("MINIMAL_FEATURE is enabled. Disabling all optional features.")
flags["RECORDING_FEATURE"] = False
flags["TRACK_FEATURE"] = False
flags["SEARCH_FEATURE"] = False
flags["CYCLE_FEATURE"] = False
flags["INFO_FEATURE"] = False
flags["TIMER_FEATURE"] = False

with open(FEATURE_FLAGS_FILE, "w") as f:
f.write("# This file is auto-generated by the configure step. Do not edit manually.\n\n")
for key, value in flags.items():
f.write(f"{key} = {value}\n")

print(f"done. {FEATURE_FLAGS_FILE} is ready.")

if __name__ == "__main__":
generate_flags()
11 changes: 11 additions & 0 deletions features.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Feature Configuration File
# Set features to true or false to enable/disable them at "compile time"
# If MINIMAL_FEATURE is true, it will override and disable all optional features (Recording, Track, Search, Cycle, Info, Timer)

MINIMAL_FEATURE=false
RECORDING_FEATURE=true
TRACK_FEATURE=true
SEARCH_FEATURE=true
CYCLE_FEATURE=true
INFO_FEATURE=true
TIMER_FEATURE=true
19 changes: 13 additions & 6 deletions radioactive/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
player = None


def final_step(options, last_station, alias, handler):
def final_step(options, last_station, alias, handler, station_list=None):
global ffplay # always needed
global player

Expand Down Expand Up @@ -104,6 +104,8 @@ def final_step(options, last_station, alias, handler):
record_file=options["record_file"],
record_file_format=options["record_file_format"],
loglevel=options["loglevel"],
handler=handler,
station_list=station_list,
)


Expand Down Expand Up @@ -169,7 +171,7 @@ def main():
options["curr_station_name"],
options["target_url"],
) = handle_user_choice_from_search_result(handler, response)
final_step(options, last_station, alias, handler)
final_step(options, last_station, alias, handler, response)
else:
sys.exit(0)

Expand All @@ -186,7 +188,7 @@ def main():
options["curr_station_name"],
options["target_url"],
) = handle_user_choice_from_search_result(handler, response)
final_step(options, last_station, alias, handler)
final_step(options, last_station, alias, handler, response)
else:
sys.exit(0)

Expand All @@ -203,7 +205,7 @@ def main():
options["curr_station_name"],
options["target_url"],
) = handle_user_choice_from_search_result(handler, response)
final_step(options, last_station, alias, handler)
final_step(options, last_station, alias, handler, response)
else:
sys.exit(0)

Expand All @@ -220,7 +222,7 @@ def main():
options["curr_station_name"],
options["target_url"],
) = handle_user_choice_from_search_result(handler, response)
final_step(options, last_station, alias, handler)
final_step(options, last_station, alias, handler, response)
else:
sys.exit(0)

Expand Down Expand Up @@ -268,7 +270,7 @@ def main():
) = handle_user_choice_from_search_result(handler, response)
# options["codec"] = response["codec"]
# print(response)
final_step(options, last_station, alias, handler)
final_step(options, last_station, alias, handler, response)
else:
sys.exit(0)
# ------------------------- direct play ------------------------#
Expand All @@ -292,6 +294,11 @@ def main():
final_step(options, last_station, alias, handler)

# final_step()
# If response is not defined yet, initialize it
if "response" not in locals():
response = []

final_step(options, last_station, alias, handler, response)

if os.name == "nt":
while True:
Expand Down
Loading