From 87d34335f33d4a8db8a359c5c55dcbdee3e02fbe Mon Sep 17 00:00:00 2001 From: Daniel Nouri Date: Sun, 5 Oct 2025 21:16:23 +0200 Subject: [PATCH] refactor: Remove test-alsa-path-select tool Not run by meson test and requires specific ALSA hardware. Fix verification already completed manually. --- spa/plugins/alsa/acp/meson.build | 9 - spa/plugins/alsa/acp/test-alsa-path-select.c | 346 ------------------- 2 files changed, 355 deletions(-) delete mode 100644 spa/plugins/alsa/acp/test-alsa-path-select.c diff --git a/spa/plugins/alsa/acp/meson.build b/spa/plugins/alsa/acp/meson.build index f5adfa193..0ec97e2b4 100644 --- a/spa/plugins/alsa/acp/meson.build +++ b/spa/plugins/alsa/acp/meson.build @@ -20,12 +20,3 @@ acp_lib = static_library( dependencies : [ spa_dep, alsa_dep, mathlib, ] ) acp_dep = declare_dependency(link_with: acp_lib) - -executable('test-alsa-path-select', - [ 'test-alsa-path-select.c' ], - c_args : acp_c_args, - include_directories : [configinc, includes_inc ], - dependencies : [ spa_dep, alsa_dep, mathlib, ], - link_with : [ acp_lib ], - install : false, -) diff --git a/spa/plugins/alsa/acp/test-alsa-path-select.c b/spa/plugins/alsa/acp/test-alsa-path-select.c deleted file mode 100644 index e9bf4b3cc..000000000 --- a/spa/plugins/alsa/acp/test-alsa-path-select.c +++ /dev/null @@ -1,346 +0,0 @@ -/* ALSA path select test tool */ -/* SPDX-FileCopyrightText: Copyright © 2025 Daniel Nouri */ -/* SPDX-License-Identifier: MIT */ - -/* - * Tests pa_alsa_path_select() to verify mute switches are correctly set - * based on device mute status, regardless of mute_during_activation setting. - * - * Regression test for HDMI/DisplayPort audio bug where IEC958 switches - * remain in kernel default state (OFF) because pa_alsa_path_select() only - * set switches when mute_during_activation=true, but no paths enable this. - * - * Test verification: - * Before fix: IEC958 switch stays OFF after path select → test FAILS - * After fix: IEC958 switch set correctly based on device state → test PASSES - * - * Usage: - * test-alsa-path-select -c [-p ] [-m] [-v] - * - * Examples: - * test-alsa-path-select -c 1 # IEC958 unmuted (expect ON) - * test-alsa-path-select -c 1 -m # IEC958 muted (expect OFF) - * test-alsa-path-select -c 0 -p analog-output # Regression test - * - * Exit codes: - * 0 = Test passed - * 1 = Test failed - * 2 = Setup error - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "alsa-mixer.h" -#include "alsa-util.h" - -#define DEFAULT_PATHS_DIR "/usr/share/alsa-card-profile/mixer/paths" - -struct test_config { - int card; - const char *path_name; - const char *paths_dir; - bool device_muted; - bool verbose; -}; - -static void show_help(const char *name) -{ - printf("Usage: %s [options]\n", name); - printf("\n"); - printf("Test tool for pa_alsa_path_select() - verifies IEC958 unmute fix\n"); - printf("\n"); - printf("Options:\n"); - printf(" -c, --card ALSA card number (required)\n"); - printf(" -p, --path Mixer path name (default: iec958-stereo-output)\n"); - printf(" -d, --paths-dir Path to mixer path configs (default: %s)\n", DEFAULT_PATHS_DIR); - printf(" -m, --muted Test with device muted (default: unmuted)\n"); - printf(" -v, --verbose Verbose output\n"); - printf(" -h, --help Show this help\n"); - printf("\n"); - printf("Examples:\n"); - printf(" # Test IEC958 unmute on card 1\n"); - printf(" %s -c 1\n", name); - printf("\n"); - printf(" # Test analog output\n"); - printf(" %s -c 0 -p analog-output\n", name); - printf("\n"); - printf(" # Test with device muted\n"); - printf(" %s -c 1 -m\n", name); - printf("\n"); - printf("Exit codes:\n"); - printf(" 0 - Test passed (switches set correctly)\n"); - printf(" 1 - Test failed (switches not set as expected)\n"); - printf(" 2 - Setup error (path not found, hardware error, etc.)\n"); -} - -static int parse_args(int argc, char *argv[], struct test_config *config) -{ - static const struct option long_options[] = { - { "card", required_argument, NULL, 'c' }, - { "path", required_argument, NULL, 'p' }, - { "paths-dir", required_argument, NULL, 'd' }, - { "muted", no_argument, NULL, 'm' }, - { "verbose", no_argument, NULL, 'v' }, - { "help", no_argument, NULL, 'h' }, - { NULL, 0, NULL, 0 } - }; - - int c; - config->card = -1; - config->path_name = "iec958-stereo-output.conf"; - config->paths_dir = DEFAULT_PATHS_DIR; - config->device_muted = false; - config->verbose = false; - - while ((c = getopt_long(argc, argv, "c:p:d:mvh", long_options, NULL)) != -1) { - switch (c) { - case 'c': - config->card = atoi(optarg); - break; - case 'p': - config->path_name = optarg; - break; - case 'd': - config->paths_dir = optarg; - break; - case 'm': - config->device_muted = true; - break; - case 'v': - config->verbose = true; - break; - case 'h': - show_help(argv[0]); - return -1; - default: - show_help(argv[0]); - return -2; - } - } - - if (config->card < 0) { - fprintf(stderr, "Error: Card number is required (-c )\n\n"); - show_help(argv[0]); - return -2; - } - - return 0; -} - -static int get_switch_state(snd_mixer_t *mixer, const char *name, int index, bool *state) -{ - snd_mixer_elem_t *elem; - snd_mixer_selem_id_t *sid; - int val; - - snd_mixer_selem_id_alloca(&sid); - snd_mixer_selem_id_set_name(sid, name); - snd_mixer_selem_id_set_index(sid, index); - - elem = snd_mixer_find_selem(mixer, sid); - if (!elem) { - fprintf(stderr, "Warning: Element '%s',%d not found\n", name, index); - return -ENOENT; - } - - if (!snd_mixer_selem_has_playback_switch(elem)) { - fprintf(stderr, "Warning: Element '%s',%d has no playback switch\n", name, index); - return -EINVAL; - } - - if (snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_MONO, &val) < 0) { - if (snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &val) < 0) { - fprintf(stderr, "Error: Cannot read switch state for '%s',%d\n", name, index); - return -EIO; - } - } - - *state = val ? true : false; - return 0; -} - -int main(int argc, char *argv[]) -{ - struct test_config config; - pa_alsa_path *path = NULL; - snd_mixer_t *mixer = NULL; - char card_name[64]; - int ret = 2; // Setup error by default - int err; - - /* Parse arguments */ - err = parse_args(argc, argv, &config); - if (err < 0) { - return err == -1 ? 0 : 2; // -1 is help, -2 is error - } - - printf("Testing pa_alsa_path_select() with:\n"); - printf(" Card: %d\n", config.card); - printf(" Path: %s\n", config.path_name); - printf(" Paths dir: %s\n", config.paths_dir); - printf(" Device muted: %s\n", config.device_muted ? "yes" : "no"); - printf("\n"); - - /* Load mixer path */ - path = pa_alsa_path_new(config.paths_dir, config.path_name, PA_ALSA_DIRECTION_OUTPUT); - if (!path) { - fprintf(stderr, "Error: Failed to load path '%s' from %s\n", - config.path_name, config.paths_dir); - fprintf(stderr, "Make sure the path file exists: %s/%s.conf\n", - config.paths_dir, config.path_name); - goto cleanup; - } - - /* Count elements BEFORE probing */ - int element_count_before = 0; - pa_alsa_element *e_temp; - PA_LLIST_FOREACH(e_temp, path->elements) { - element_count_before++; - } - printf("Elements in path BEFORE probing: %d\n", element_count_before); - - if (config.verbose && element_count_before > 0) { - printf("Loaded path: %s\n", path->name ? path->name : config.path_name); - printf(" mute_during_activation: %s\n", path->mute_during_activation ? "yes" : "no"); - printf(" Elements:\n"); - - PA_LLIST_FOREACH(e_temp, path->elements) { - const char *switch_use; - switch (e_temp->switch_use) { - case PA_ALSA_SWITCH_MUTE: switch_use = "mute"; break; - case PA_ALSA_SWITCH_ON: switch_use = "on"; break; - case PA_ALSA_SWITCH_OFF: switch_use = "off"; break; - default: switch_use = "ignore"; break; - } - printf(" - %s (index %d): switch=%s\n", - e_temp->alsa_id.name, e_temp->alsa_id.index, switch_use); - } - printf("\n"); - } - - /* Open ALSA mixer */ - snprintf(card_name, sizeof(card_name), "hw:%d", config.card); - - if (snd_mixer_open(&mixer, 0) < 0) { - fprintf(stderr, "Error: Failed to open mixer\n"); - goto cleanup; - } - - if (snd_mixer_attach(mixer, card_name) < 0) { - fprintf(stderr, "Error: Failed to attach mixer to %s\n", card_name); - fprintf(stderr, "Make sure card %d exists (check with: aplay -l)\n", config.card); - goto cleanup; - } - - if (snd_mixer_selem_register(mixer, NULL, NULL) < 0) { - fprintf(stderr, "Error: Failed to register mixer\n"); - goto cleanup; - } - - if (snd_mixer_load(mixer) < 0) { - fprintf(stderr, "Error: Failed to load mixer elements\n"); - goto cleanup; - } - - /* Probe the path to ensure elements are available */ - printf("Probing path...\n"); - if (pa_alsa_path_probe(path, NULL, mixer, false) < 0) { - fprintf(stderr, "Error: Path probe failed - required elements not found on card\n"); - goto cleanup; - } - printf("Path probe: OK\n\n"); - - /* Record switch states before activation */ - printf("Switch states BEFORE pa_alsa_path_select():\n"); - pa_alsa_element *e; - int mute_switch_count = 0; - PA_LLIST_FOREACH(e, path->elements) { - if (e->switch_use == PA_ALSA_SWITCH_MUTE) { - bool state; - mute_switch_count++; - if (get_switch_state(mixer, e->alsa_id.name, e->alsa_id.index, &state) == 0) { - printf(" %s,%d = %s\n", e->alsa_id.name, e->alsa_id.index, - state ? "ON" : "OFF"); - } - } - } - - if (mute_switch_count == 0) { - fprintf(stderr, "Warning: No mute switches found in path\n"); - printf("This test requires a path with switch=mute elements\n"); - goto cleanup; - } - - /* Call pa_alsa_path_select() - THE FUNCTION UNDER TEST */ - printf("\nCalling pa_alsa_path_select(path, NULL, mixer, device_is_muted=%s)...\n", - config.device_muted ? "true" : "false"); - - err = pa_alsa_path_select(path, NULL, mixer, config.device_muted); - if (err < 0) { - fprintf(stderr, "Error: pa_alsa_path_select() failed with error %d\n", err); - goto cleanup; - } - printf("pa_alsa_path_select(): OK\n\n"); - - /* Verify switch states after activation */ - printf("Switch states AFTER pa_alsa_path_select():\n"); - bool all_correct = true; - bool expected_state = !config.device_muted; // unmuted device = switches ON - - PA_LLIST_FOREACH(e, path->elements) { - if (e->switch_use == PA_ALSA_SWITCH_MUTE) { - bool actual_state; - if (get_switch_state(mixer, e->alsa_id.name, e->alsa_id.index, &actual_state) == 0) { - printf(" %s,%d = %s", e->alsa_id.name, e->alsa_id.index, - actual_state ? "ON" : "OFF"); - - if (actual_state == expected_state) { - printf(" ✓\n"); - } else { - printf(" ✗ (expected %s)\n", expected_state ? "ON" : "OFF"); - all_correct = false; - } - } - } - } - - /* Determine test result */ - printf("\n"); - printf("========================================\n"); - if (all_correct) { - printf("TEST PASSED\n"); - printf("All mute switches correctly set to %s\n", expected_state ? "ON" : "OFF"); - if (!path->mute_during_activation) { - printf("\nThis proves the fix works:\n"); - printf("- Path has mute_during_activation=false (default)\n"); - printf("- Switches were still set correctly\n"); - printf("- Bug would have left them in kernel default state\n"); - } - ret = 0; - } else { - printf("TEST FAILED\n"); - printf("One or more switches NOT set correctly\n"); - printf("Expected: %s, but some switches were %s\n", - expected_state ? "ON (unmuted)" : "OFF (muted)", - expected_state ? "OFF" : "ON"); - printf("\nThis indicates the bug is still present:\n"); - printf("- Switches not set when mute_during_activation=false\n"); - printf("- IEC958 fix may not be applied\n"); - ret = 1; - } - printf("========================================\n"); - -cleanup: - if (mixer) - snd_mixer_close(mixer); - if (path) - pa_alsa_path_free(path); - - return ret; -}