Skip to content

Commit 15d1a1c

Browse files
authored
Merge pull request #8 from rit-sse/dev/update_config
now can place songs folder anywhere according to config.json
2 parents d846cd4 + a4d00b5 commit 15d1a1c

2 files changed

Lines changed: 41 additions & 53 deletions

File tree

mentor-script/src/app.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ impl eframe::App for MentorApp {
358358
.corner_radius(8.0);
359359

360360
if ui.add(folder_button).clicked() {
361-
Config::open_songs_folder();
361+
Config::open_songs_folder(&self.config);
362362
}
363363
})
364364
},

mentor-script/src/config.rs

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
//!
33
//! Loads application settings from config.json located next to the executable.
44
5+
use serde::Deserialize;
56
use std::fs;
6-
use std::path::PathBuf;
7+
use std::path::{Path, PathBuf};
78
use std::process::Command;
8-
use serde::Deserialize;
99

1010
/// Application configuration loaded from config.json
1111
#[derive(Debug, Deserialize, Clone)]
@@ -16,13 +16,20 @@ pub struct Config {
1616
pub hourly_link: String,
1717
/// URL to open for 30-minute check-ins
1818
pub thirty_link: String,
19-
/// Audio files loaded from the songs folder
19+
20+
/// Folder containing audio files (can be anywhere).
21+
///
22+
/// If relative, it is resolved relative to the executable's directory.
2023
#[serde(default)]
24+
pub songs_dir: PathBuf,
25+
26+
/// Audio files discovered from `songs_dir`
27+
#[serde(skip)]
2128
pub songs: Vec<PathBuf>,
2229
}
2330

2431
impl Config {
25-
/// Loads configuration from config.json and discovers audio files from songs folder
32+
/// Loads configuration from config.json and discovers audio files from songs_dir
2633
pub fn load() -> Option<Self> {
2734
let exe_dir: PathBuf = std::env::current_exe()
2835
.expect("Failed to get executable path")
@@ -32,71 +39,54 @@ impl Config {
3239

3340
let path = exe_dir.join("config.json");
3441

35-
let raw = fs::read_to_string(&path)
36-
.unwrap();
42+
let raw = fs::read_to_string(&path).unwrap();
43+
44+
let mut config: Config =
45+
serde_json::from_str(&raw).expect("Invalid JSON in config.json");
3746

38-
let mut config: Config = serde_json::from_str(&raw)
39-
.expect("Invalid JSON in config.json");
47+
// Resolve songs_dir:
48+
// - if missing/empty => default to <exe_dir>/songs
49+
// - if relative => resolve relative to exe_dir
50+
if config.songs_dir.as_os_str().is_empty() {
51+
config.songs_dir = exe_dir.join("songs");
52+
} else if config.songs_dir.is_relative() {
53+
config.songs_dir = exe_dir.join(&config.songs_dir);
54+
}
4055

41-
config.songs = Self::load_songs();
56+
config.songs = Self::load_songs_from(&config.songs_dir);
4257

4358
Some(config)
4459
}
4560

46-
/// Scans the songs folder for supported audio files (.mp3, .wav, .ogg, .flac)
47-
fn load_songs() -> Vec<PathBuf> {
48-
let mut dir = std::env::current_exe().unwrap();
49-
dir.pop();
50-
dir.push("songs");
51-
52-
let entries = match fs::read_dir(&dir) {
61+
/// Scans a folder for supported audio files (.mp3, .wav, .ogg, .flac)
62+
fn load_songs_from(dir: &Path) -> Vec<PathBuf> {
63+
let entries = match fs::read_dir(dir) {
5364
Ok(entries) => entries,
54-
Err(_) => return Vec::new(), // songs folder missing -> no sounds
65+
Err(_) => return Vec::new(), // folder missing/unreadable -> no sounds
5566
};
5667

5768
entries
5869
.filter_map(|e| e.ok())
5970
.map(|e| e.path())
6071
.filter(|p| {
6172
matches!(
62-
p.extension().and_then(|e| e.to_str()),
63-
Some("mp3" | "wav" | "ogg" | "flac")
64-
)
73+
p.extension().and_then(|e| e.to_str()),
74+
Some("mp3" | "wav" | "ogg" | "flac")
75+
)
6576
})
6677
.collect()
6778
}
6879

69-
/// ```rust
70-
/// Opens the "songs" folder located in the same directory as the executable.
71-
///
72-
/// This function uses platform-specific commands to open the "songs" folder:
73-
/// - On **Windows**, it uses the `explorer` command.
74-
/// - On **macOS**, it uses the `open` command.
75-
/// - On **Linux**, it uses the `xdg-open` command.
76-
///
77-
/// If the platform is unsupported or an error occurs while spawning the command,
78-
/// a message will be printed to the console.
79-
///
80-
/// This will open the "songs" folder in the default file explorer, provided the
81-
/// folder exists and the platform is supported.
82-
/// ```
83-
pub fn open_songs_folder() {
84-
let mut dir = std::env::current_exe().unwrap();
85-
dir.pop();
86-
dir.push("songs");
80+
/// Opens the configured songs folder in the OS file explorer.
81+
pub fn open_songs_folder(&self) {
82+
let dir = &self.songs_dir;
83+
8784
let spawn_result = if cfg!(target_os = "windows") {
88-
Command::new("explorer")
89-
.arg(dir)
90-
.spawn()
85+
Command::new("explorer").arg(dir).spawn()
9186
} else if cfg!(target_os = "macos") {
92-
Command::new("open")
93-
.arg(dir)
94-
.spawn()
87+
Command::new("open").arg(dir).spawn()
9588
} else if cfg!(target_os = "linux") {
96-
// xdg-open is a common utility on Linux to open files/urls with the default app
97-
Command::new("xdg-open")
98-
.arg(dir)
99-
.spawn()
89+
Command::new("xdg-open").arg(dir).spawn()
10090
} else {
10191
println!("Unsupported operating system for opening file explorer automatically.");
10292
return;
@@ -105,7 +95,5 @@ impl Config {
10595
if let Err(e) = spawn_result {
10696
eprintln!("Failed to open songs folder: {e}");
10797
}
108-
109-
}
110-
111-
}
98+
}
99+
}

0 commit comments

Comments
 (0)