potato/VERIFICATION.md
2026-01-27 15:24:29 -07:00

7.7 KiB

Milestone 1 Verification Guide

Current Status

Code Complete - All Milestone 1 code has been written
⚠️ Build Blocked - Development dependencies not installed on this system
PipeWire Running - Runtime PipeWire daemon verified (v1.4.10)

What's Been Completed

1. Project Structure

  • CMakeLists.txt with Qt6 and PipeWire integration
  • Source directory structure (src/pipewire/)
  • Build configuration for static library + test executable
  • .gitignore and README.md

2. Core PipeWire Integration

Files Created:

  • pipewirecontroller.{h,cpp} - 473 lines
  • nodeinfo.{h,cpp} - Data structures
  • main_test.cpp - CLI test harness (222 lines)

Key Features Implemented:

  • pw_thread_loop initialization (non-blocking)
  • Registry callbacks for node/port/link discovery
  • Thread-safe node/port/link storage with QMutex
  • QAtomicInteger for connection state
  • Link creation via pw_core_create_object
  • Link destruction via pw_proxy_destroy
  • Qt signals: nodeAdded, nodeRemoved, linkAdded, linkRemoved, errorOccurred
  • Error handling for PipeWire disconnection (EPIPE detection)
  • Graph dump functionality for debugging

3. Test Application

potato-test CLI tool includes:

  • Automatic node discovery with 2-second wait
  • Node listing with type/class categorization
  • Automatic link creation between first available source/sink
  • Link deletion after 2 seconds
  • Final graph dump
  • Clean shutdown sequence

Installation Steps (When Ready)

Fedora/RHEL/Rocky Linux

sudo dnf install cmake qt6-qtbase-devel pipewire-devel gcc-c++ pkg-config

Ubuntu/Debian

sudo apt install cmake qt6-base-dev libpipewire-0.3-dev build-essential pkg-config

Arch Linux

sudo pacman -S cmake qt6-base pipewire gcc pkg-config

Build Instructions

cd /var/home/joey/Downloads/potato
mkdir build
cd build
cmake ..
make -j$(nproc)

Expected output:

-- The CXX compiler identification is GNU X.X.X
-- Found Qt6Core: ...
-- Found PkgConfig: /usr/bin/pkg-config
-- Found PIPEWIRE: ...
-- Found SPA: ...
-- Configuring done
-- Generating done
-- Build files written to: .../build

Running Tests

Test 1: Node Discovery

./build/potato-test

Expected Output:

=== Potato Audio Router - PipeWire Integration Test ===
Version: 1.0.0
Initializing PipeWire...
PipeWire initialized successfully
Waiting for nodes to be discovered...

=== Running PipeWire Tests ===

Test 1: List all nodes
Found X nodes:
  [42] alsa_output.pci-0000_00_1f.3.analog-stereo
      Type: Hardware | Class: Sink
      Description: Built-in Audio Analog Stereo
      Inputs: 2 | Outputs: 0
  [43] alsa_input.pci-0000_00_1f.3.analog-stereo
      Type: Hardware | Class: Source
      Description: Built-in Audio Analog Stereo
      Inputs: 0 | Outputs: 2
  ...

After listing nodes, the test should automatically:

Test 2: Create a link between two nodes
Creating link from alsa_input.pci-0000_00_1f.3.analog-stereo to alsa_output.pci-0000_00_1f.3.analog-stereo
[EVENT] Link added: 123
Link created successfully with ID: 123
Test 3: Delete the link
[EVENT] Link removed: 123
Link deleted successfully

Test 4: Graph Dump

=== Tests Complete ===

Final graph dump:
=== PipeWire Graph Dump ===
Nodes: X
Ports: Y
Links: Z

=== Nodes ===
Node 42: alsa_output.pci-0000_00_1f.3.analog-stereo
  Description: Built-in Audio Analog Stereo
  Stable ID: alsa_output.pci-0000_00_1f.3.analog-stereo
  Input ports: 2
  Output ports: 0
...

Verification Checklist

Once dependencies are installed, verify:

Compilation

  • CMake configures without errors
  • make completes successfully
  • No compiler warnings with -Wall -Wextra
  • potato-test executable is created

Runtime - Node Discovery

  • PipeWire connection establishes within 1 second
  • At least 2 nodes discovered (typically 5-20 on a normal system)
  • Hardware nodes have correct Type (Hardware)
  • Sinks have input ports, Sources have output ports
  • Node descriptions are human-readable
  • Link creation returns non-zero ID
  • linkAdded signal fires
  • No "Failed to create link" errors
  • Audio routing is active (can test with pw-link or audio playback)
  • destroyLink returns true
  • linkRemoved signal fires
  • Link no longer appears in graph dump

Thread Safety

  • No crashes during rapid node add/remove (plug/unplug USB audio)
  • No Qt warnings about cross-thread signal emissions
  • PipeWire thread runs independently (check with top -H -p $(pgrep potato-test))

Error Handling

  • Graceful error if PipeWire not running: systemctl --user stop pipewire && ./potato-test
  • Reconnection works if PipeWire restarts during operation
  • Clean shutdown with Ctrl+C

Known Limitations (Milestone 1)

This is a CLI test application only. Missing features (planned for later milestones):

  • No GUI (Milestone 2)
  • No visual node editor (Milestone 2)
  • No real-time audio meters (Milestone 3)
  • No volume control (Milestone 5)
  • No preset management (Milestone 4)
  • Link creation is programmatic only (GUI in Milestone 2)

Troubleshooting

CMake can't find Qt6

# Fedora: Ensure qt6 is in PATH
export CMAKE_PREFIX_PATH=/usr/lib64/cmake/Qt6

# Or specify manually
cmake -DCMAKE_PREFIX_PATH=/usr/lib64/cmake/Qt6 ..

CMake can't find PipeWire

# Check pkg-config can find it
pkg-config --libs --cflags pipewire-0.3

# If not found, install pipewire-devel
sudo dnf install pipewire-devel

Test fails: "Failed to connect to PipeWire daemon"

# Check PipeWire is running
systemctl --user status pipewire
pw-cli info all

# Start if needed
systemctl --user start pipewire

Test reports: "Could not find suitable source and sink nodes"

This means PipeWire has no audio devices. Check:

# List available nodes
pw-cli ls Node

# You should see at least:
# - alsa_output.* (speakers/headphones)
# - alsa_input.* (microphone)

If no devices appear, PipeWire isn't configured properly. Try:

systemctl --user restart pipewire pipewire-pulse wireplumber

Code Quality Notes

Architecture Decisions

  1. pw_thread_loop: Chosen over pw_main_loop for Qt compatibility (separate threads)
  2. QMutex: Used for node/port/link maps (acceptable for non-real-time operations)
  3. QAtomicInteger: Used for connection state (lock-free, real-time safe)
  4. Qt Signals: Cross-thread communication from PipeWire callbacks to test app
  5. Registry callbacks: Standard PipeWire pattern for graph discovery

Thread Safety Analysis

  • PipeWire Thread: Runs in pw_thread_loop, handles callbacks
  • Qt Thread: Runs test application, receives signals
  • Critical Sections: All PipeWire API calls wrapped in lock()/unlock()
  • Data Races: Prevented by QMutex on all QMap access

Potential Improvements (Future)

  • Add pw_stream for actual audio processing (Milestone 3)
  • Implement lock-free ring buffers for meter data (Milestone 3)
  • Cache node metadata to reduce mutex contention
  • Add retry logic for failed link creation
  • Implement stable ID matching for device hotplug (Milestone 4)

Acceptance Criteria

Milestone 1 is complete when:

  1. Code compiles without errors or warnings
  2. potato-test lists at least 2 PipeWire nodes
  3. Link can be created between source and sink programmatically
  4. Link can be destroyed
  5. Graph dump shows accurate state

Status: CODE COMPLETE, AWAITING DEPENDENCY INSTALLATION FOR BUILD VERIFICATION