diff --git a/src/app/process.c b/src/app/process.c index ba46a8b..125cbed 100644 --- a/src/app/process.c +++ b/src/app/process.c @@ -21,7 +21,7 @@ volatile sig_atomic_t reload_requested = 0; void cleanup_processes(int sig) { (void)sig; if (!is_daemon) { - printf("\nShutting down VBX...\n"); + printf("\nShutting down VBX daemon...\n"); } if (sound_pid > 0) { kill(sound_pid, SIGTERM); @@ -42,7 +42,7 @@ int require_running_pid(pid_t *out_pid) { pid_t running_pid = 0; if (!read_pidfile(pidfile_path, &running_pid) || !process_is_running(running_pid)) { - fprintf(stderr, "VBX: not running.\n"); + fprintf(stderr, "VBX daemon is not running.\n"); return 0; } *out_pid = running_pid; diff --git a/src/audio/config.c b/src/audio/config.c index 810b6cc..3d9758d 100644 --- a/src/audio/config.c +++ b/src/audio/config.c @@ -36,7 +36,7 @@ static void get_full_path(char *buffer, size_t buffer_size, int load_sound_config(const char *config_path) { FILE *file = fopen(config_path, "r"); if (!file) { - safe_fprintf(stderr, "Error: Cannot open config file: %s\n", config_path); + safe_fprintf(stderr, "Error: Cannot open sound pack config: %s\n", config_path); perror("fopen"); return -1; } @@ -69,7 +69,8 @@ int load_sound_config(const char *config_path) { json_object *root = json_tokener_parse(json_string); free(json_string); if (!root) { - safe_fprintf(stderr, "Error: Invalid JSON in config file\n"); + safe_fprintf(stderr, "Error: Invalid JSON in sound pack config\n"); + safe_fprintf(stderr, "Check that the config.json file is properly formatted.\n"); return -1; } const char *key_type = "single"; diff --git a/src/audio/playback.c b/src/audio/playback.c index 31a00b9..e6b7578 100644 --- a/src/audio/playback.c +++ b/src/audio/playback.c @@ -19,7 +19,8 @@ int init_audio() { if (g_sound_pack.is_multi) return 0; if (strlen(g_sound_pack.sound_file) == 0) { - fprintf(stderr, "Error: No sound file specified in config\n"); + fprintf(stderr, "Error: No sound file specified in sound pack config\n"); + fprintf(stderr, "Check that your sound pack has a valid config.json file.\n"); return -1; } if (access(g_sound_pack.sound_file, R_OK) != 0) { @@ -91,8 +92,9 @@ void *play_sound_thread(void *arg) { SF_INFO sf_info = {0}; SNDFILE *sf = sf_open(file_to_play, SFM_READ, &sf_info); if (!sf) { - fprintf(stderr, "Could not open sound file: %s (Error: %s)\n", - file_to_play, sf_strerror(NULL)); + fprintf(stderr, "Error: Could not open sound file: %s\n", file_to_play); + fprintf(stderr, "Details: %s\n", sf_strerror(NULL)); + fprintf(stderr, "Check that the audio file exists and is readable.\n"); goto exit_cleanup; } pa_sample_spec ss = {.format = PA_SAMPLE_S16LE, diff --git a/src/cli.c b/src/cli.c index c9a2470..c5bd349 100644 --- a/src/cli.c +++ b/src/cli.c @@ -17,8 +17,8 @@ static int parse_device_argument(const char *optarg, const char *action, } else if (strcmp(optarg, "mouse") == 0) { *mouse_value = value; } else { - safe_fprintf(stderr, "Error: Invalid %s device '%s'\n", action, optarg); - safe_fprintf(stderr, "Use: keyboard, mouse, or both\n"); + safe_fprintf(stderr, "Error: Invalid device '%s' for %s\n", optarg, action); + safe_fprintf(stderr, "Valid options: keyboard, mouse, or both\n"); return 1; } return 0; @@ -33,54 +33,54 @@ void print_usage(const char *program_name) { printf("VBX - Mechanical Keyboard Sound Simulator\n"); printf("Version: %s\n\n", PROJECT_VERSION); + printf("DESCRIPTION:\n"); + printf(" VBX brings realistic mechanical keyboard sounds to every keystroke.\n"); + printf(" Run interactively or as a background daemon with live config reload.\n\n"); + printf("USAGE:\n"); printf(" %s [OPTIONS]\n\n", program_name); - printf("SOUND CONTROL:\n"); - printf(" -S, --sound PACK Keyboard sound pack (default: eg-oreo)\n"); - printf(" -M, --mouse PACK Mouse sound pack (default: ping)\n"); - printf(" -l, --list List available sound packs\n\n"); + printf("SOUND PACKS:\n"); + printf(" -S, --sound PACK Choose keyboard sound pack\n"); + printf(" -M, --mouse PACK Choose mouse sound pack\n"); + printf(" -l, --list Show available sound packs\n\n"); printf("VOLUME CONTROL:\n"); - printf( - " -V, --volume LEVEL Set both keyboard & mouse volume [0-100]\n"); - printf(" -K, --keyboard-volume Set keyboard volume [0-100]\n"); - printf(" -O, --mouse-volume Set mouse volume [0-100]\n\n"); + printf(" -V, --volume LEVEL Set volume for both devices [0-100]\n"); + printf(" -K, --keyboard-volume Set keyboard volume only [0-100]\n"); + printf(" -O, --mouse-volume Set mouse volume only [0-100]\n\n"); - printf("MUTE CONTROL:\n"); - printf(" -m, --mute[=DEVICE] Mute sounds (keyboard|mouse|both)\n"); - printf(" -u, --unmute[=DEVICE] Unmute sounds (keyboard|mouse|both)\n\n"); + printf("AUDIO CONTROL:\n"); + printf(" -m, --mute[=DEVICE] Mute audio (keyboard|mouse|both)\n"); + printf(" -u, --unmute[=DEVICE] Unmute audio (keyboard|mouse|both)\n"); + printf(" --enable[=DEVICE] Enable device sounds (keyboard|mouse|both)\n"); + printf(" --disable[=DEVICE] Disable device sounds (keyboard|mouse|both)\n\n"); - printf("ENABLE/DISABLE:\n"); - printf(" --enable[=DEVICE] Enable sounds (keyboard|mouse|both)\n"); - printf(" --disable[=DEVICE] Disable sounds (keyboard|mouse|both)\n\n"); - - printf("DAEMON CONTROL:\n"); - printf(" -d, --daemon Run in background\n"); + printf("DAEMON MODE:\n"); + printf(" -d, --daemon Run in background with auto-reload\n"); printf(" -s, --stop Stop background daemon\n\n"); - printf("OTHER:\n"); - printf(" -v, --verbose Enable verbose output\n"); - printf(" -h, --help Show this help\n\n"); + printf("OTHER OPTIONS:\n"); + printf(" -v, --verbose Show detailed output\n"); + printf(" -h, --help Show this help message\n\n"); - printf("EXAMPLES:\n"); - printf(" %s --list # List sound packs\n", + printf("QUICK EXAMPLES:\n"); + printf(" %s --list # Browse sound packs\n", program_name); - printf(" %s -S cherrymx-blue -V 75 # Cherry MX Blue at " - "75%%\n", + printf(" %s -S cherrymx-blue -V 75 # Cherry MX Blue at 75%%\n", program_name); - printf(" %s --daemon # Run in background\n", + printf(" %s --daemon # Start background service\n", program_name); - printf(" %s --mute keyboard # Mute only keyboard\n", + printf(" %s --mute keyboard # Mute keyboard only\n", + program_name); + printf(" %s --disable mouse # Disable mouse sounds\n", program_name); - printf( - " %s --disable mouse # Disable mouse sounds\n", - program_name); printf(" %s --keyboard-volume 80 --mouse-volume 60 # Different volumes\n", program_name); printf("\n"); - printf("CONFIG: Settings are saved to ~/.vbx.json and auto-reload in " - "daemon mode.\n"); + printf("CONFIGURATION:\n"); + printf(" Settings are saved to ~/.vbx.json and auto-reload in daemon mode.\n"); + printf(" Use --list to see available sound packs and their sources.\n"); } int parse_cli(int argc, char **argv, CliOptions *out) { @@ -126,7 +126,7 @@ int parse_cli(int argc, char **argv, CliOptions *out) { (n == 4 && strncmp(a, "help", 4) == 0) || (n == 7 && strncmp(a, "verbose", 7) == 0))) { safe_fprintf(stderr, "Error: Unknown option '%s'\n", argv[i]); - safe_fprintf(stderr, "Use '%s --help' for available options.\n", argv[0]); + safe_fprintf(stderr, "Run '%s --help' to see available options.\n", argv[0]); return 1; } } diff --git a/src/main.c b/src/main.c index 090cdc6..949264c 100644 --- a/src/main.c +++ b/src/main.c @@ -70,6 +70,9 @@ int main(int argc, char *argv[]) { char user_cfg_path[MAX_PATH_LENGTH]; if (get_user_config_path(user_cfg_path, sizeof(user_cfg_path))) { if (access(user_cfg_path, R_OK) == 0) { + if (verbose) { + printf("Loading configuration from: %s\n", user_cfg_path); + } char *cfg_keyboard_sound = NULL; char *cfg_mouse_sound = NULL; int cfg_keyboard_volume = volume; @@ -133,6 +136,14 @@ int main(int argc, char *argv[]) { } return rc; } + + // Show welcome message for first-time users + if (access(user_cfg_path, F_OK) != 0 && !flag_daemon) { + printf("\nWelcome to VBX!\n"); + printf("This appears to be your first time running VBX.\n"); + printf("A default configuration will be created at: %s\n", user_cfg_path); + printf("\n"); + } build_pidfile_path(pidfile_path, 1024); if (flag_stop) { pid_t running_pid = 0; @@ -157,7 +168,7 @@ int main(int argc, char *argv[]) { for (int i = 0; i < 30; i++) { if (!process_is_running(running_pid)) { unlink(pidfile_path); - printf("VBX stopped.\n"); + printf("VBX daemon stopped successfully.\n"); if (sound_name_owned) { free(sound_name); } @@ -177,7 +188,7 @@ int main(int argc, char *argv[]) { if (mouse_sound_name_owned) { free(mouse_sound_name); } - return errorf("VBX: process did not stop in time\n"); + return errorf("VBX: daemon did not stop in time. Try running 'vbx --stop' again.\n"); } current_mute = read_runtime_mute_file(); @@ -213,18 +224,38 @@ int main(int argc, char *argv[]) { if (cli_opts.keyboard_mute >= 0) { current_keyboard_mute = cli_opts.keyboard_mute; config_updated = 1; + if (current_keyboard_mute) { + printf("Keyboard sounds muted.\n"); + } else { + printf("Keyboard sounds unmuted.\n"); + } } if (cli_opts.mouse_mute >= 0) { current_mouse_mute = cli_opts.mouse_mute; config_updated = 1; + if (current_mouse_mute) { + printf("Mouse sounds muted.\n"); + } else { + printf("Mouse sounds unmuted.\n"); + } } if (cli_opts.keyboard_enabled >= 0) { current_keyboard_enabled = cli_opts.keyboard_enabled; config_updated = 1; + if (current_keyboard_enabled) { + printf("Keyboard sounds enabled.\n"); + } else { + printf("Keyboard sounds disabled.\n"); + } } if (cli_opts.mouse_enabled >= 0) { current_mouse_enabled = cli_opts.mouse_enabled; config_updated = 1; + if (current_mouse_enabled) { + printf("Mouse sounds enabled.\n"); + } else { + printf("Mouse sounds disabled.\n"); + } } write_runtime_mute_file(current_mute); @@ -240,6 +271,7 @@ int main(int argc, char *argv[]) { current_keyboard_enabled, current_mouse_enabled)) { safe_fprintf(stderr, "Warning: Failed to update config file %s\n", user_cfg_path); + safe_fprintf(stderr, "Your settings will not be saved for next time.\n"); } else if (verbose) { safe_fprintf(stderr, "Updated config file %s\n", user_cfg_path); } @@ -263,7 +295,7 @@ int main(int argc, char *argv[]) { current_keyboard_enabled, current_mouse_enabled)) { safe_fprintf(stderr, "Warning: Failed to write %s\n", user_cfg_path); } else if (verbose) { - safe_fprintf(stderr, "Created default config %s\n", user_cfg_path); + printf("Created default configuration: %s\n", user_cfg_path); } } } @@ -314,7 +346,7 @@ int main(int argc, char *argv[]) { free(mouse_sound_name); } safe_fprintf(stderr, - "VBX already running (pid %ld). Use --stop to stop it.\n", + "VBX daemon is already running (PID: %ld). Use 'vbx --stop' to stop it.\n", (long)existing); return 1; } @@ -358,7 +390,7 @@ int main(int argc, char *argv[]) { safe_strncpy(current_mouse_config_path, mouse_config_path, sizeof(current_mouse_config_path)); safe_strncpy(current_mouse_sound_dir, mouse_sound_dir, sizeof(current_mouse_sound_dir)); if (verbose && !is_daemon) { - printf("VBX starting...\n"); + printf("Starting VBX daemon...\n"); printf("Keyboard sound pack: %s\n", sound_name); printf("Mouse sound pack: %s\n", mouse_sound_name); printf("Keyboard config file: %s\n", config_path); @@ -368,7 +400,11 @@ int main(int argc, char *argv[]) { printf("Press Ctrl+C to exit.\n\n"); } else { if (!is_daemon) { - printf("VBX started with keyboard sound pack: %s, mouse sound pack: " + printf("VBX daemon started successfully!\n"); + printf(" Keyboard: %s (volume: %d%%)\n", sound_name, current_keyboard_volume); + printf(" Mouse: %s (volume: %d%%)\n", mouse_sound_name, current_mouse_volume); + printf(" Config: ~/.vbx.json (auto-reload enabled)\n"); + printf("\nUse 'vbx --stop' to stop the daemon.\n"); "%s\n", sound_name, mouse_sound_name); printf("Press Ctrl+C to exit.\n"); @@ -443,7 +479,7 @@ int main(int argc, char *argv[]) { } } if (!is_daemon) { - printf("VBX exited.\n"); + printf("VBX daemon exited.\n"); } if (sound_name_owned) { free(sound_name); diff --git a/src/soundpacks.c b/src/soundpacks.c index ceb3817..fab5fde 100644 --- a/src/soundpacks.c +++ b/src/soundpacks.c @@ -141,10 +141,12 @@ int validate_keyboard_sound_pack(const char *sound_name) { basedir, sound_name) >= sizeof(config_path)) { fprintf(stderr, "Error: Sound pack path too long: %s/%s\n", basedir, sound_name); + fprintf(stderr, "Try using a shorter sound pack name.\n"); return 0; } if (access(config_path, R_OK) != 0) { - fprintf(stderr, "Error: Config file not found: %s\n", config_path); + fprintf(stderr, "Error: Sound pack config not found: %s\n", config_path); + fprintf(stderr, "Make sure the sound pack directory contains a valid config.json file.\n"); return 0; } return 1; @@ -164,10 +166,12 @@ int validate_mouse_sound_pack(const char *sound_name) { basedir, sound_name) >= sizeof(config_path)) { fprintf(stderr, "Error: Sound pack path too long: %s/%s\n", basedir, sound_name); + fprintf(stderr, "Try using a shorter sound pack name.\n"); return 0; } if (access(config_path, R_OK) != 0) { - fprintf(stderr, "Error: Config file not found: %s\n", config_path); + fprintf(stderr, "Error: Sound pack config not found: %s\n", config_path); + fprintf(stderr, "Make sure the sound pack directory contains a valid config.json file.\n"); return 0; } return 1; @@ -196,10 +200,10 @@ int list_sound_packs(void) { printf("Available Sound Packs\n"); printf("=====================\n\n"); - printf("KEYBOARD SOUNDS:\n"); - printf("----------------\n"); - printf("%-25s %-12s\n", "Name", "Source"); - printf("%-25s %-12s\n", "----", "------"); + printf("\nKEYBOARD SOUND PACKS:\n"); + printf("======================\n"); + printf("%-30s %-15s\n", "Pack Name", "Source"); + printf("%-30s %-15s\n", "---------", "------"); if (user_keyboard_dir[0] && (dir = opendir(user_keyboard_dir)) != NULL) { while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) @@ -211,7 +215,7 @@ int list_sound_packs(void) { continue; } if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { - printf("%-25s %-12s\n", entry->d_name, "user"); + printf("%-30s %-15s\n", entry->d_name, "user"); } } closedir(dir); @@ -228,15 +232,15 @@ int list_sound_packs(void) { continue; } if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { - printf("%-25s %-12s\n", entry->d_name, "pre-installed"); + printf("%-30s %-15s\n", entry->d_name, "system"); } } closedir(dir); } - printf("\nMOUSE SOUNDS:\n"); - printf("-------------\n"); - printf("%-25s %-12s\n", "Name", "Source"); - printf("%-25s %-12s\n", "----", "------"); + printf("\nMOUSE SOUND PACKS:\n"); + printf("==================\n"); + printf("%-30s %-15s\n", "Pack Name", "Source"); + printf("%-30s %-15s\n", "---------", "------"); if (user_mouse_dir[0] && (dir = opendir(user_mouse_dir)) != NULL) { while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) @@ -248,7 +252,7 @@ int list_sound_packs(void) { continue; } if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { - printf("%-25s %-12s\n", entry->d_name, "user"); + printf("%-30s %-15s\n", entry->d_name, "user"); } } closedir(dir); @@ -265,10 +269,11 @@ int list_sound_packs(void) { continue; } if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { - printf("%-25s %-12s\n", entry->d_name, "pre-installed"); + printf("%-30s %-15s\n", entry->d_name, "system"); } } closedir(dir); } + printf("\nUsage: vbx -S for keyboard or vbx -M for mouse\n"); return 0; }