-
Notifications
You must be signed in to change notification settings - Fork 0
UX Decision: MIDI Device Selection and Configuration Workflow #12
Description
UX Decision: MIDI Device Selection and Configuration Workflow
Problem Statement
The GUI currently displays MIDI devices but has no device selection mechanism. Users report they "can see the MIDI devices but are unable to select any." This raises a fundamental UX question: What should happen when a user clicks on a MIDI device?
Current State
What Works
- ✅ Device discovery and enumeration
- ✅ Device list display with port numbers
- ✅ Connection status indicators (✅/🎹)
- ✅ Auto-refresh every 5 seconds
- ✅ Manual refresh button
What's Missing
- ❌ No click handler on device cards
- ❌ No visual selection state
- ❌ Connect/Disconnect buttons are disabled (intentional - daemon handles connection)
- ❌ No device details view
- ❌ No clear path from "I see my device" to "I'm using my device"
Technical Implementation
<!-- Current: No interactivity -->
<div class="device-card" class:connected={device.connected}>
<!-- Device info display only -->
</div>
<!-- Disabled buttons -->
<button class="action-button connect" disabled>
Connect
</button>The store has selection functionality (devicesStore.select(device)), but it's not connected to any UI.
Expected User Journey Options
We need to decide which user journey makes the most sense for MIDIMon's architecture.
Option 1: Information-Only View (Current + Details)
Philosophy: Devices are managed via config file, GUI is for viewing/monitoring
User Journey:
- User opens GUI → navigates to "Devices & Profiles"
- User sees list of available MIDI devices
- User clicks on a device → detail panel slides in/expands
- Detail panel shows:
- Full device name and port
- Connection status
- Device capabilities (if available)
- Link to config file: "Configure this device"
- Recent activity/events (if connected)
Pros:
- ✅ Aligns with current architecture (daemon manages connections)
- ✅ Clear separation: GUI = monitoring, Config = control
- ✅ Simple implementation
- ✅ No risky state management
Cons:
- ❌ Less intuitive for new users
- ❌ Extra step to edit config
- ❌ Doesn't leverage visual interface
Option 2: Direct Connection Control
Philosophy: GUI should provide point-and-click device management
User Journey:
- User opens GUI → navigates to "Devices & Profiles"
- User sees list of available MIDI devices
- User clicks "Connect" button on desired device
- GUI updates config.toml (or creates one if needed)
- GUI sends IPC reload command to daemon
- Device connects and shows ✅ status
- User can now configure mappings for that device
Pros:
- ✅ Intuitive UX (click to connect)
- ✅ Visual immediate feedback
- ✅ Lowers barrier to entry
- ✅ Modern application UX
Cons:
⚠️ GUI now manages config (state synchronization risk)⚠️ What happens if user edits config file manually?⚠️ Need atomic config updates (file locking?)⚠️ More complex error handling
Option 3: Setup Wizard Approach
Philosophy: Guide users through device setup with clear steps
User Journey:
- First Launch: "Let's set up your MIDI device!"
- Step 1 - Detect: GUI scans and shows available devices
- Step 2 - Select: User clicks device card to select
- Card highlights with selection indicator
- "Next" button becomes enabled
- Step 3 - Template (Optional): "Choose a starting template"
- Show device-specific templates if available
- Or "Create from scratch"
- Step 4 - Confirm: Preview of what will be created
- Show config snippet
- "Create Configuration" button
- Step 5 - Success: "Your device is ready!"
- Daemon automatically reloads
- Show next steps (configure mappings)
Pros:
- ✅ Best UX for new users (guided experience)
- ✅ Reduces configuration errors
- ✅ Can validate choices before committing
- ✅ Incorporates template selection naturally
Cons:
⚠️ More development effort⚠️ May feel "hand-holdy" for advanced users⚠️ Need to handle multi-device scenarios
Option 4: Hybrid - Smart Contextual Actions
Philosophy: Adapt UI based on device/config state
User Journey:
Scenario A: No Config Exists
- User opens GUI → sees device list
- User clicks device → Detail panel shows:
- "This device is not configured"
- Button: "Set Up This Device" (wizard)
- Button: "Use Template" (template selector)
Scenario B: Device Configured But Not Connected
- User clicks device → Detail panel shows:
- "Configured but not active"
- Current config snippet preview
- Button: "Connect This Device" (updates config)
- Button: "Edit Configuration"
Scenario C: Device Connected
- User clicks device → Detail panel shows:
- "Connected and active ✅"
- Live event stream (recent MIDI events)
- Button: "View Mappings"
- Button: "Disconnect"
Pros:
- ✅ Intuitive for all skill levels
- ✅ Contextual actions feel natural
- ✅ Handles edge cases gracefully
- ✅ Progressive disclosure
Cons:
⚠️ Most complex implementation⚠️ Requires robust state detection⚠️ More testing scenarios
Design Mockup (Conceptual)
Selected Device Card with Detail Panel
┌─────────────────────────────────────────────────────────┐
│ Available MIDI Devices 🔄 Refresh │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────┐ ┌──────────────────┐│
│ │ 🎹 Maschine Mikro MK3 │ │ Device Details ││
│ │ Port 2 │ │ ││
│ │ Available │ │ Maschine...MK3 ││
│ │ │ │ Port: 2 ││
│ │ [Connect] │ │ Status: Avail. ││
│ └──────────────────────────────┘ │ ││
│ │ [Set Up Device] ││
│ ┌──────────────────────────────┐ │ [Use Template] ││
│ │ ✅ Xbox Controller │ └──────────────────┘│
│ │ HID Gamepad │ │
│ │ Connected │ │
│ │ │ │
│ │ [Disconnect] │ │
│ └──────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
Technical Implementation Considerations
Store Updates Needed
// Add selection state tracking
const { subscribe, set, update } = writable({
devices: [],
selectedDevice: null, // Already exists but unused!
loading: false,
error: null
});
// Already exists but needs UI integration
select(device) {
update(state => ({ ...state, selectedDevice: device }));
}Component Changes Needed
<!-- Add click handler -->
<div
class="device-card"
class:connected={device.connected}
class:selected={$devicesStore.selectedDevice?.index === device.index}
on:click={() => devicesStore.select(device)}
>
<!-- ... -->
</div>Backend Commands Needed (Option 2/3/4)
#[tauri::command]
pub async fn connect_device(
device_index: usize,
state: State<'_, AppState>
) -> Result<String, String> {
// Update config.toml with selected device
// Send IPC reload command
// Return success message
}Questions to Decide
-
Primary Use Case: Is MIDIMon primarily for:
- a) Power users who edit config files? (→ Option 1)
- b) General users who want point-and-click? (→ Option 2/3)
- c) Both? (→ Option 4)
-
Config Management: Should GUI write to config.toml?
- If YES → Need atomic file operations, conflict resolution
- If NO → Need clear "Edit config file" workflow
-
Multi-Device Support: What if user has 3 MIDI controllers?
- Can they connect multiple at once?
- How to show which device is "primary"?
-
Profile Integration: How does this interact with per-app profiles?
- Should device selection be profile-scoped?
- Or global with profile overrides?
-
Backward Compatibility: What about existing config files?
- Should GUI auto-detect configured devices?
- How to handle manual edits after GUI changes?
Recommended Approach
I recommend Option 4 (Hybrid) because:
- Handles both new and existing users gracefully
- Aligns with MIDIMon's template system
- Progressive disclosure keeps UI simple
- Can implement incrementally:
- Phase 1: Add selection + basic detail panel (1-2 days)
- Phase 2: Add "Set Up Device" wizard (3-4 days)
- Phase 3: Add config editing from GUI (2-3 days)
Start with Phase 1 to validate the interaction model, then expand based on user feedback.
Implementation Checklist
Phase 1: Selection + Details (Minimal Viable)
- Add click handler to device cards
- Add visual selection state (highlight, border, etc.)
- Create detail panel component
- Show basic device info in detail panel
- Add "Edit Config" button (opens file in system editor)
Phase 2: Template Integration
- Add "Set Up Device" button in detail panel
- Connect to existing template selector
- Create config from template when selected
- Show success notification
Phase 3: Direct Connection (Optional)
- Implement
connect_devicecommand - Add config.toml write/update logic
- Add IPC reload after config update
- Handle connection errors gracefully
Related Issues
- MIDI Device Hot-Plug Detection Not Working on macOS #11 - MIDI Device Hot-Plug Detection (auto-refresh)
- Template selector workflow (already working)
Let's Decide: Which option best fits MIDIMon's vision? What should happen when users click on a MIDI device?