Devialet DOS API Research

Research Topic: Comprehensive analysis of the Devialet Device Operating System (DOS) API and Android SDK for achieving feature parity in slPhantomRemote.

Comparison of available features across Devialet Operating System (DOS) versions and device types.
Features discovered via GET /systems/currentavailableFeatures[]

Device Types

Phantom Ultimate 98

Speaker • DOS 3

Latest firmware with full feature set including rendering modes, Chromecast, and per-mode audio settings.

Phantom Gold

Speaker • DOS 2

Classic Phantom with standard audio features. Supports basic EQ, night mode, and balance.

Arch

Input Device • DOS 2

HDMI/optical input hub. Not a speaker - provides sources to groups. Has input configuration.

Dialog

Center Channel • DOS 2

Voice/dialog enhancement speaker. Minimal feature set focused on latency sync.

Feature Comparison

Feature Phantom Ultimate 98
DOS 3
Phantom Gold
DOS 2
Arch
DOS 2
Dialog
DOS 2
Audio Processing
Night Mode nightModeOverlay nightMode
Equalizer equalizerPerMode equalizer
Balance balance balance
Loudness loudnessPerMode
Bass Reducer bassReducerPerMode
Adaptive Volume adaptiveVolumeLevelPerMode
Rendering Modes
Rendering Mode renderingMode
Per-Source Modes renderingModesPerSource
Neutral Override neutralModeOverride
Sync & Latency
Latency Control latencyControlPerSystem latencyControlPerSource latencyControlPerSource latencyControlPerSource
Streaming
Chromecast chromecast
Stream Quality streamQuality
Hardware Control
LED Mode ledMode
Standby standby
Power Management powerManagement powerManagement powerManagement powerManagement
Bluetooth Control perDeviceBluetoothControl
Configuration
Installation ID automaticInstallationId explicitInstallationId explicitInstallationId explicitInstallationId
Interface Control preferredInterfaceControl preferredInterfaceControl preferredInterfaceControl
Input Configuration inputConfiguration

Notes

Endpoint Examples

API Endpoints (Verified from APK Binary)

Endpoints discovered via binary string search in Devialet Android app v1.25 dex files:

Audio Settings

System Settings

Voice Assistants

Other Endpoints

API Enum Values (from Decompiled Source)

Valid values for API payloads, extracted from decompiled Devialet Android app Java/Kotlin source:

LedMode

UNKNOWN
AUTO
ALWAYS_ON
ALWAYS_OFF

MicrophoneStatus

UNKNOWN
OFF
ON

NightModeOverlay
(DOS 3)

Enabled
Disabled
Unknown

NightModeState
(DOS 2)

Enabled
Disabled
NotWritable
Unknown

RenderingModes.Mode

Neutral
Movie
Music
Podcast
Spatial
Voice
Unknown

AudioFeature

NONE
NIGHT_MODE
EQUALIZATION
BALANCE
AUDIO_ROUTING_POLICY

API Method Signatures (from Decompiled Source)

Internal SDK methods discovered from decompiled source. These map to HTTP API calls:

AudioSettingsManager

MethodDescription
setNightMode(UUID, boolean)DOS 2 night mode on/off
setNightModeOverlay(UUID, boolean)DOS 3 night mode overlay on/off
setBalance(UUID, int)Balance (-100 to 100)
setEqualizer(UUID, Preset)EQ preset selection
setEqualizer(UUID, Mode, Map<Band, Double>)Per-mode custom EQ bands
setLoudness(UUID, Mode, boolean)Per-mode loudness on/off
setBassReducer(UUID, Mode, boolean)Per-mode bass reducer on/off
setAdaptiveVolumeLevel(UUID, Mode, boolean)Per-mode adaptive volume on/off
setNeutralMode(UUID, boolean)Neutral mode override
setOrientation(UUID, Orientation)Device orientation setting
setRoomAdaptation(UUID, Mode)Room adaptation mode
toggleRoomAdaptation(UUID, boolean)Toggle room adaptation active
setSAM(UUID, boolean, int)SAM enabled + quantity
setSystemLatency(UUID, int)System latency in ms
calibrateADH(UUID)Start ADH calibration
calibrateForRoom(UUID)Start room correction
eraseCalibration(UUID)Erase calibration data
setAmplifierConfiguration(UUID, Selectable)SAM amplifier config

PowerManager

MethodDescription
powerOff(UUID)Power off device
reboot(UUID)Reboot device
resetToFactory(UUID)Factory reset device

Configuration (LED/Microphone)

MethodDescription
availableLedModes()Get available LED modes for device
ledMode()Get current LED mode
setLedMode(LedMode)Set LED mode
microphoneStatus()Get microphone status
features()Get device configuration features

TopologyManager (SDK Methods - HTTP endpoints unknown)

These are Kotlin SDK methods from decompiled source. Actual HTTP endpoints use native Qt code and are not visible.

MethodDescription
getGroups()Get all groups
getSystems()Get all systems
getDevices()Get all devices
createSystem(name, type, deviceRoles)Create new system (Solo, Duo, Surround, Multi, Loop)
joinGroup(systemId, groupId)Add system to group
ejectFromGroup(systemId)Remove system from group
splitFromSystem(deviceId)Split device from system
setDeviceName(deviceId, name)Set device name
setSystemName(systemId, name)Set system name
setDeviceRoles(systemId, roles)Set device roles (FrontLeft, FrontRight, etc.)
setDeviceSetupState(deviceId, state)Set setup state (Ongoing, Finalized)

GroupManager (SDK Methods - HTTP endpoints unknown)

These are Kotlin SDK methods. Likely map to /ipcontrol/v1/groups/ namespace but exact endpoints need testing.

MethodDescription
join(systemId, groupId)Add system to group
leaveGroup(systemId)Remove system from group
removeGroupLeader(groupId)Remove group leader
getCompatibleSystems(groupId)Get systems that can join group
canPerformGroupOperations(groupId)Check if group operations allowed

Topology Enum Values

System types, device roles, and setup states:

System.Type

Solo
Duo
Surround
Multi
Loop

Device.Role

Mono
FrontLeft
FrontRight
Loop(identifier)
Unknown

Device.SetupState

Ongoing
Finalized
Unknown

Device.Feature

AutomaticInstallationId
BatteryPowered
Chromecast
ExplicitInstallationId
InputConfiguration
LatencyControlPerSource
Orientation
PowerManagement
PreferredInterfaceControl
RoomCorrection
Standby
StreamQuality

System.Feature

AdaptiveVolumeLevelPerSource
AdaptiveVolumeLevelPerMode
ADHCalibration
Balance
BassReducerPerMode
BatteryPowered
ConfigurationBundle
Display
Equalizer
EqualizerPerMode
LatencyControlPerSource
LatencyControlPerSystem
LedMode
LoudnessPerMode
NightMode
NightModeOverlay
NightModePerSource
NeutralModeOverride
PerDeviceBluetoothControl
PowerManagement
PreferredInterfaceControl
PreOutPerSource
RenderingMode
RenderingModesPerSourceType
RoomAdaptation
SAM
Standby

Raw Feature Lists

As reported by each device via GET /systems/currentavailableFeatures[]

Phantom Ultimate 98 (DOS 3)

Available Features:
  • adaptiveVolumeLevelPerMode
  • automaticInstallationId
  • balance
  • bassReducerPerMode
  • chromecast
  • equalizerPerMode
  • latencyControlPerSystem
  • ledMode
  • loudnessPerMode
  • neutralModeOverride
  • nightModeOverlay
  • perDeviceBluetoothControl
  • powerManagement
  • renderingMode
  • renderingModesPerSource
  • standby
  • streamQuality

Phantom Gold (DOS 2)

Available Features:
  • balance
  • equalizer
  • explicitInstallationId
  • latencyControlPerSource
  • nightMode
  • powerManagement
  • preferredInterfaceControl

Arch (DOS 2)

Available Features:
  • inputConfiguration
  • powerManagement
  • preferredInterfaceControl
  • latencyControlPerSource
  • explicitInstallationId

Dialog (DOS 2)

Available Features:
  • powerManagement
  • preferredInterfaceControl
  • latencyControlPerSource
  • explicitInstallationId

Internal SDK Architecture (from Native Library)

Devialet uses a multi-layer architecture with song-themed codenames. Extracted from libmetaandroidd.so (24.5 MB native library):

SDK Module Codenames

CodenamePurposeKey Classes
MasterOfPuppetsTopology & group managementGroup, System, Node, Renderer, Topology, GlobalTopology
SourceOfAllSource, playback, sound controlSource, Playback, SoundControl, Metadata, Topology, Configuration
SettingTheSystemAudio & general settingsAudioSettings, AudioSettingsManager, Settings, BaseService
ComeTogetherGroup managementGroupManager, SynchronizabilityMonitor
GetThePartyStartedDevice discovery & setupDevice, Installation, GtpsManager, NetworkDescription
BlazeSetup workflows & troubleshootingSystemCreator, InstallationTroubleshoot, DeviceConfigurator
FreshFirmware updatesDevice, UpdateCoordinatorManager, UpdateImage
CantTouchThisLED & power configurationPowerManager, Configuration, LedMode, MicrophoneStatus
IMASlave4UPlayback & room correctionPlayback, PlaybackManager, RoomCorrectionSetup, Configuration
LiveIsLifeHardware-specific configurationsIec958, Manolo, PacoV3, Paula, Twix (input types)
WhatsUpService discovery & endpointsEndpointResolver, Host, HostMonitor
CallMeMaybeRPC/messaging frameworkEndpoint, Client, Server, Call, Notification
Blue / LightBlueBluetooth managementPeerDevice, Configuration, DeviceDiscoveryAgent
UnderTheBridgeAudio routingConfiguration, AudioRoutingPolicy
RoonRaatRoon RAAT integrationMetadata, MetadataManager
CollectorLogging & bug reportsBugReport, StorageKey, LogFacility
WhoAmIDevice identificationDeviceInfo
TikTokService registry & timing (heartbeat/scheduling)Registry

Protocol Buffer Definitions

The SDK uses Protocol Buffers for serialization. These .proto files define the data structures:

Message Definition Files

SourceOfAll (Playback)

Devialet/SourceOfAll/BaseService.proto
Devialet/SourceOfAll/Configuration.proto
Devialet/SourceOfAll/Metadata.proto
Devialet/SourceOfAll/Playback.proto
Devialet/SourceOfAll/SoundControl.proto
Devialet/SourceOfAll/Source.proto
Devialet/SourceOfAll/Topology.proto

SettingTheSystem (Settings)

Devialet/SettingTheSystem/AudioSettings.proto
Devialet/SettingTheSystem/BaseService.proto
Devialet/SettingTheSystem/GeneralSettings.proto
Devialet/SettingTheSystem/PowerManagementSettings.proto

Setup & Installation

Devialet/GetThePartyStarted/DeviceInfo.proto
Devialet/GetThePartyStarted/Installation/Device.proto
Devialet/GetThePartyStarted/Installation/DeviceState.proto
Devialet/GetThePartyStarted/Network.proto
Devialet/GetThePartyStarted/Setup/Api.proto
Devialet/Fresh/Device.proto
Devialet/Fresh/UpdateImage.proto

Hardware & Input

Devialet/IMASlave4U/Configuration.proto
Devialet/IMASlave4U/Playback.proto
Devialet/IMASlave4U/RoomCorrectionSetup.proto
Devialet/LiveIsLife/Iec958/Configuration.proto
Devialet/LiveIsLife/Manolo/Configuration.proto
Devialet/LiveIsLife/PacoV3/Configuration.proto
Devialet/LiveIsLife/Paula/Configuration.proto
Devialet/LiveIsLife/Twix/Configuration.proto

Other Services

Devialet/Blue/Configuration.proto
Devialet/CantTouchThis/Configuration.proto
Devialet/CantTouchThis/PowerManager.proto
Devialet/UnderTheBridge/Configuration.proto
Devialet/UnderTheBridge/Messages.proto
Devialet/RoonRaat/Metadata.proto
Devialet/Collector/LogFacility.proto
Devialet/TikTok/Registry.proto

JNI Class Mappings

Java/Kotlin classes that wrap native C++ code. The io.dvlt.* namespace maps to Devialet's internal SDK:

Core Classes (io.dvlt.*)

JNI ClassDescription
Topology & Groups (masterofpuppets)
io.dvlt.masterofpuppets.GlobalTopologyGlobal topology state
io.dvlt.masterofpuppets.GroupGroup model
io.dvlt.masterofpuppets.SystemSystem model
io.dvlt.masterofpuppets.NodeNode (device in topology)
io.dvlt.masterofpuppets.RendererAudio renderer
io.dvlt.masterofpuppets.TopologyTopology manager
io.dvlt.cometogether.GroupManagerGroup operations
Sources & Playback (sourceofall)
io.dvlt.sourceofall.SourceAudio source
io.dvlt.sourceofall.PlaybackPlayback state (State, RepeatMode)
io.dvlt.sourceofall.SoundControlVolume control (Origin)
io.dvlt.sourceofall.MetadataTrack metadata (ChannelCount, PictureType)
io.dvlt.sourceofall.ConfigurationSource configuration (TargetType)
io.dvlt.sourceofall.AudioModeAudio mode settings
io.dvlt.sourceofall.PlaybackFeaturesAvailable playback features
Audio Settings (settingthesystem)
io.dvlt.settingthesystem.consumer.AudioSettingsAudio settings state
io.dvlt.settingthesystem.consumer.AudioSettingsManagerAudio settings operations
io.dvlt.settingthesystem.consumer.EqualizationParametersEQ band settings
io.dvlt.settingthesystem.consumer.EqualizationPresetEQ presets
io.dvlt.settingthesystem.consumer.BandEQ bands
Device Setup (getthepartystarted / blaze)
io.dvlt.getthepartystarted.DeviceDiscovered device
io.dvlt.getthepartystarted.InstallationInstallation info (Type)
io.dvlt.getthepartystarted.NetworkDescriptionNetwork info (WiFi, Wired, PLC)
io.dvlt.blaze.topology.SystemCreatorCreate systems (Step)
io.dvlt.blaze.setup.unconfigured.DeviceConfiguratorConfigure new devices
io.dvlt.blaze.setup.migration.MigrationManagerDevice migration (Step)
Hardware (canttouchthis / liveislife)
io.dvlt.canttouchthis.PowerManagerPower operations
io.dvlt.canttouchthis.ConfigurationLED/mic configuration
io.dvlt.imaslave4u.RoomCorrectionSetupRoom correction
io.dvlt.liveislife.manolo.client.ConfigurationManolo (analog input)
io.dvlt.liveislife.pacov3.client.ConfigurationPacoV3 (HDMI input)
io.dvlt.liveislife.twix.client.ConfigurationTwix (display settings)
Discovery & Updates
io.dvlt.whatsup.EndpointResolverService endpoint discovery
io.dvlt.whatsup.HostMonitorHost state monitoring
io.dvlt.fresh.UpdateCoordinatorManagerFirmware updates (Readiness)
io.dvlt.fresh.DeviceDevice update state (State)

Additional Enum Values (from Native Library)

Node.Type

Group
System
Device
Renderer

Source.SourceType

Spotify
Tidal
AirPlay
Chromecast
Bluetooth
HDMI
Optical
Analog
Roon

Playback.State

Playing
Paused
Stopped
Loading
Buffering

Playback.RepeatMode

Off
All
One

SoundControl.Origin

App
Source
Remote
Hardware

Configuration.TargetType

System
Group
Device

NetworkDescription Types

WiFi (Band: 2.4GHz, 5GHz)
Wired (Ethernet)
PLC (Powerline)

Manolo SourceType (Analog)

Line
Phono
Microphone

Decompiled Source Code Examples

Real code from the Devialet Android SDK (decompiled from APK v1.25):

PowerManager.java — Native Power Control

Shows how JNI wraps native C++ calls. All methods delegate to libmetaandroidd.so:

package io.dvlt.canttouchthis;

public class PowerManager extends NativeWrapper {
    private native void initialize();

    // Power off device - calls native Qt code
    public native Task<Void> powerOff(UUID uuid);

    // Reboot device
    public native Task<Void> reboot(UUID uuid);

    // Factory reset
    public native Task<Void> resetToFactory(UUID uuid);
}

Configuration.java — LED & Microphone Control

Observable configuration with listener pattern:

package io.dvlt.canttouchthis;

public class Configuration extends NativeWrapper {
    public interface Listener {
        void onLedModeChanged();
        void onMicrophoneStatusChanged();
    }

    // Get available LED modes for this device
    public native Set<LedMode> availableLedModes();

    // Get current LED mode
    public native LedMode ledMode();

    // Set LED mode (AUTO, ALWAYS_ON, ALWAYS_OFF)
    public native Task<Void> setLedMode(LedMode ledMode);

    // Get microphone status (ON, OFF, UNKNOWN)
    public native MicrophoneStatus microphoneStatus();

    // Get device configuration features
    public native Set<ConfigurationFeature> features();
}

EndpointResolver.java — Dynamic Endpoint Discovery

This is why HTTP endpoints aren't hardcoded - they're resolved at runtime:

package io.dvlt.whatsup;

public class EndpointResolver extends NativeWrapper {
    // Resolve service endpoints for a device by UUID
    // Returns set of endpoint URLs/paths
    public native Set<String> resolve(UUID uuid);
}

AudioSettingsManager.java — Complete Audio Control Interface

The main interface for all audio settings. 30+ methods for complete control:

public interface AudioSettingsManager {
    // State getters - all return Map<UUID, State>
    Map<UUID, NightModeState> getNightModeStates();
    Map<UUID, NightModeOverlay> getNightModeOverlayStates();
    Map<UUID, BalanceState> getBalanceStates();
    Map<UUID, EqualizerState> getEqualizerStates();
    Map<UUID, SAMState> getSamStates();
    Map<UUID, RoomAdaptationState> getRoomAdaptationStates();
    Map<UUID, Latency> getSystemLatencies();

    // Per-rendering-mode states
    Map<UUID, Map<RenderingModes.Mode, EqualizerState>> getRenderingModeEqualizerStates();
    Map<UUID, Map<RenderingModes.Mode, LoudnessState>> getRenderingModeLoudnessStates();
    Map<UUID, Map<RenderingModes.Mode, BassReducerState>> getRenderingModeBassReducerStates();

    // Setters - all return Completable (RxJava)
    Completable setNightMode(UUID uuid, boolean enabled);        // DOS 2
    Completable setNightModeOverlay(UUID uuid, boolean enabled); // DOS 3
    Completable setBalance(UUID uuid, int value);               // -100 to 100
    Completable setSystemLatency(UUID uuid, int ms);
    Completable setSAM(UUID uuid, boolean enabled, int quantity);

    // Per-mode setters
    Completable setEqualizer(UUID uuid, RenderingModes.Mode mode, Map<Band, Double> values);
    Completable setLoudness(UUID uuid, RenderingModes.Mode mode, boolean enabled);
    Completable setBassReducer(UUID uuid, RenderingModes.Mode mode, boolean enabled);

    // Calibration
    Completable calibrateADH(UUID systemId);
    Completable calibrateForRoom(UUID deviceId);
    Completable eraseCalibration(UUID deviceId);
}

Device.java — Complete Device Model

Data class with topology relationships and features:

public final class Device {
    private final UUID id;           // Unique device identifier
    private final UUID rendererId;   // Audio renderer ID
    private final UUID systemId;     // Parent system ID
    private final UUID groupId;      // Parent group ID
    private final boolean isSystemLeader;
    private final String name;       // User-defined name
    private final String modelName;  // e.g., "Phantom Ultimate 98"
    private final String serial;
    private final Role role;         // Mono, FrontLeft, FrontRight, Loop
    private final Set<Feature> availableFeatures;
    private final SetupState setupState;

    // Role: Position in stereo/surround setup
    public interface Role {
        class Mono implements Role { }     // Single speaker
        class FrontLeft implements Role { } // Stereo left
        class FrontRight implements Role { }// Stereo right
        class Loop implements Role {       // Multi-room loop
            String identifier;
        }
        class Unknown implements Role { }
    }

    // Device-level features
    public enum Feature {
        AutomaticInstallationId, BatteryPowered, Chromecast,
        ExplicitInstallationId, InputConfiguration, LatencyControlPerSource,
        Orientation, PowerManagement, PreferredInterfaceControl,
        RoomCorrection, Standby, StreamQuality
    }

    public enum SetupState { Ongoing, Finalized, Unknown }
}

System.java — System Configuration Model

A "System" is a logical grouping of devices (Solo, Duo, Surround, Multi):

public final class System {
    private final UUID id;
    private final UUID groupId;           // Parent group
    private final Map<UUID, Device> devices;
    private final Type type;              // Solo, Duo, Surround, Multi, Loop
    private final String name;
    private final Set<Feature> availableFeatures;
    private final SyncFamily syncFamily;
    private final boolean isGroupLeader;

    public enum Type { Solo, Duo, Surround, Multi, Loop }

    // System-level features (27 total)
    public enum Feature {
        AdaptiveVolumeLevelPerSource, AdaptiveVolumeLevelPerMode,
        ADHCalibration, Balance, BassReducerPerMode, BatteryPowered,
        ConfigurationBundle, Display, Equalizer, EqualizerPerMode,
        LatencyControlPerSource, LatencyControlPerSystem, LedMode,
        LoudnessPerMode, NightMode, NightModeOverlay, NightModePerSource,
        NeutralModeOverride, PerDeviceBluetoothControl, PowerManagement,
        PreferredInterfaceControl, PreOutPerSource, RenderingMode,
        RenderingModesPerSourceType, RoomAdaptation, SAM, Standby
    }
}

Complete API Reference for Feature Parity

All SDK interfaces and methods needed for slPhantomRemote to match the Android app's functionality:

SourceManager.java — Complete Playback Control Interface

The central interface for all source, playback, and volume operations. This is what slPhantomRemote needs to implement full control:

public interface SourceManager {
    // === Constants ===
    static final int defaultSeekStepMs = 15000;      // 15 sec seek step
    static final int defaultSkipThresholdMs = 5000;  // 5 sec skip threshold
    static final int defaultVolumeStep = 5;          // Volume step size
    static final long volumeThrottleIntervalMs = 100; // Rate limit

    // === State Getters (all keyed by UUID) ===
    Map<UUID, SourceState> getActiveSourceByGroup();       // Active source per group
    Map<UUID, List<Source>> getSourcesByGroup();        // All sources per group
    Map<UUID, Integer> getVolumeByNode();                // Volume per node (0-100)
    Map<UUID, UUID> getPlaybackTargets();                // Playback target per source
    Map<UUID, RenderingModes> getRenderingModes();        // Audio mode per system
    Map<UUID, SourceConfiguration> getSourceConfigurations();
    Map<UUID, NightModeState> getNightModeStates();
    Map<UUID, AdaptiveVolumeLevelState> getAdaptiveVolumeLevelStates();
    Map<UUID, PreAmplificationOutputState> getPreAmplificationOutputStates();

    // === Input Configuration ===
    Map<UUID, ManoloConfiguration> getManoloConfigurations();  // Analog (RCA)
    Map<UUID, AuxConfiguration> getAuxConfigurations();       // Aux inputs
    Map<UUID, PhonoInputSettings> getPhonoInputSettings();    // Phono stage
    Map<UUID, BluetoothConfiguration> getBluetoothConfigurations();

    // === Streaming Metadata ===
    Map<UUID, ChromecastState> getChromecastStatuses();
    Map<UUID, RoonMetadata> getRoonMetadata();

    // === Events (RxJava Observable) ===
    Observable<SourceEvent> getObserve();

    // === Playback Control ===
    Completable play(UUID groupId, UUID sourceId);     // Play specific source
    Completable pause(UUID groupId);                    // Pause playback
    Completable togglePlay(UUID groupId);               // Play/pause toggle
    Completable next(UUID groupId);                     // Next track
    Completable previous(UUID groupId, int skipThresholdMs); // Previous track

    // === Seeking ===
    Completable seekTo(UUID groupId, int positionMs);   // Seek to position
    Completable seekBy(UUID groupId, int seekAmountMs, int skipThresholdMs);
    Completable seekForward(UUID groupId);              // +15 seconds
    Completable seekBackwards(UUID groupId);            // -15 seconds

    // === Volume Control ===
    Completable setVolume(UUID nodeId, int volume);     // Set volume (0-100)
    Completable increaseVolume(UUID nodeId);            // +5 volume
    Completable decreaseVolume(UUID nodeId);            // -5 volume
    Completable setMute(UUID groupId, boolean isMuted);

    // === Audio Settings Per Source ===
    Completable setRenderingMode(UUID sourceId, RenderingModes.Mode mode);
    Completable setConfiguredRenderingMode(UUID systemId, Source.Type sourceType, RenderingModes.Mode mode);
    Completable setNightMode(UUID sourceId, NightModeState state);
    Completable setAdaptiveVolumeLevel(UUID sourceId, AdaptiveVolumeLevelState state);
    Completable setLatency(UUID sourceId, int latencyMs);
    Completable setPreAmplificationOutput(UUID sourceId, PreAmplificationOutputState state);

    // === Analog Input (Manolo) ===
    Completable setActiveInput(UUID deviceId, ManoloConfiguration.InputMode mode);
    Completable setAutoSwitch(UUID sourceId, boolean enabled);
    Completable setAutoSwitch(UUID sourceId, ManoloConfiguration.InputMode mode, boolean enabled);
    Completable setInputSensitivity(UUID sourceId, ManoloConfiguration.InputMode mode, long sensitivity);

    // === Phono Stage Settings ===
    Completable setPhonoCartridgeBalance(UUID sourceId, int balance);
    Completable setPhonoLoadingCapacitance(UUID sourceId, PhonoInputSettings.LoadCapacitance capacitance);
    Completable setPhonoLoadingResistance(UUID sourceId, PhonoInputSettings.LoadResistance resistance);
    Completable setPhonoMaxOutputLevel(UUID sourceId, int maxLevel);
    Completable setPhonoStartupCurve(UUID sourceId, PhonoInputSettings.StartupCurve curve);

    // === Bluetooth ===
    Completable startBluetoothDiscoverability(UUID nodeId);

    // === Chromecast ===
    Completable acceptChromecastTermsOfService(UUID deviceId);
    Completable setChromecastDataSharingPolicy(UUID deviceId, boolean allowed);
}

Source.java — Source Model with All Types

public final class Source {
    private final UUID id;            // Source UUID
    private final UUID hostDeviceId;  // Host device UUID
    private final Type type;          // Source type enum
    private final String subType;     // Optional subtype
    private final String displayName; // User-visible name
    private final ImageResource icon;

    public enum Category { Online, Physical, Bluetooth, Unknown }

    public enum Type {
        // Online/Streaming (Category.Online)
        SpotifyConnect, Airplay, Airplay2, Chromecast, UPnP,
        RAAT, TidalConnect, Audirvana, Alexa,

        // Physical Inputs (Category.Physical)
        Optical1, Optical2, Optical, OpticalJack,
        Digital1, Digital2, Digital3, Digital4, DigitalLeft, DigitalRight,
        Line1, Line2, Line,
        Phono1, Phono2, Phono,
        UsbIn, HDMI, ArchPhysical,

        // Bluetooth (Category.Bluetooth)
        Bluetooth,

        Unknown
    }

    // Returns false for Chromecast, Airplay(1/2), Alexa, RAAT (multiroom not supported)
    public boolean getSupportsMultiroom();
}

Metadata.java — Track Information

public final class Metadata {
    private final String title;       // Track title
    private final String artist;      // Artist name
    private final String album;       // Album name
    private final MediaType mediaType;
    private final Integer duration;   // Duration in ms (nullable)
    private final ImageResource coverArt;

    public enum MediaType { Track, Podcast, Station, Live, Unknown }
}

RenderingModes.java — Audio Modes (Sound Profiles)

public final class RenderingModes {
    private final Set<Mode> availableModes;
    private final Mode activeMode;

    public enum Mode {
        Neutral,   // Flat response
        Music,     // Music optimized
        Movie,     // Movie/cinema
        Voice,     // Voice/dialog enhancement
        Podcast,   // Podcast/spoken word
        Spatial    // Spatial audio
    }
}

HTTP Endpoint → SDK Method Mapping

Quick Reference: What HTTP endpoints map to what SDK methods

HTTP EndpointMethodSDK InterfaceNotes
GET systems/current/sources/currentGETSourceManager.getActiveSourceByGroup()Current playing source
GET systems/current/sourcesGETSourceManager.getSourcesByGroup()All available sources
PUT systems/current/sources/currentPUTSourceManager.play()Switch source
PUT systems/current/sources/current/soundControl/volumePUTSourceManager.setVolume()Set volume 0-100
POST systems/current/sources/current/soundControl/playPOSTSourceManager.play()Play current source
POST systems/current/sources/current/soundControl/pausePOSTSourceManager.pause()Pause playback
POST systems/current/sources/current/soundControl/nextPOSTSourceManager.next()Next track
POST systems/current/sources/current/soundControl/previousPOSTSourceManager.previous()Previous track
PUT systems/current/settings/audio/nightModePUTAudioSettingsManager.setNightMode()DOS 2
PUT systems/current/settings/audio/nightModeOverlayPUTAudioSettingsManager.setNightModeOverlay()DOS 3
PUT systems/current/settings/audio/balancePUTAudioSettingsManager.setBalance()-100 to 100
PUT systems/current/settings/audio/equalizerPUTAudioSettingsManager.setEqualizer()Per rendering mode
PUT systems/current/settings/audio/samPUTAudioSettingsManager.setSAM()Speaker Active Matching
PUT systems/current/settings/audio/renderingModePUTSourceManager.setRenderingMode()Sound profile
PUT systems/current/settings/ledModePUTConfiguration.setLedMode()AUTO, ALWAYS_ON, OFF
PUT systems/current/settings/powerManagementPUTPowerManager.*Power off, reboot
GET systems/current/bluetoothGETSourceManager.getBluetoothConfigurations()BT state
POST devices/current/bluetooth/discoverablePOSTSourceManager.startBluetoothDiscoverability()Enable pairing

Topology Hierarchy

Device → System → Group Relationship

┌─────────────────────────────────────────────────────────────────────────────┐
│  GROUP (Multi-room zone)                                                    │
│  └── groupId: UUID                                                          │
│  └── systemIds: Set<UUID>                                                   │
│                                                                             │
│  ┌─────────────────────────────┐    ┌─────────────────────────────┐        │
│  │ SYSTEM (Stereo pair/single)  │    │ SYSTEM                        │        │
│  │ type: Duo                   │    │ type: Solo                   │        │
│  │ isGroupLeader: true         │    │ isGroupLeader: false         │        │
│  │                             │    │                              │        │
│  │  ┌─────────┐  ┌─────────┐  │    │  ┌─────────┐                 │        │
│  │  │DEVICE   │  │DEVICE   │  │    │  │DEVICE   │                 │        │
│  │  │FrontLeft│  │FrontRigt│  │    │  │Mono     │                 │        │
│  │  │leader   │  │         │  │    │  │         │                 │        │
│  │  └─────────┘  └─────────┘  │    │  └─────────┘                 │        │
│  └─────────────────────────────┘    └─────────────────────────────┘        │
└─────────────────────────────────────────────────────────────────────────────┘

// Example: Get all devices in a group
Group group = topologyManager.getGroups().get(groupId);
for (UUID systemId : group.getSystemIds()) {
    System system = topologyManager.getSystems().get(systemId);
    for (Device device : system.getDevices().values()) {
        // Process each device
    }
}

TopologyManager.java — Group/System/Device Operations

Main interface for topology management. HTTP endpoints are resolved internally:

public interface TopologyManager {
    // Observable events (RxJava)
    Observable<TopologyEvent> getObserve();

    // Read topology state
    Map<UUID, Group> getGroups();
    Map<UUID, System> getSystems();
    Map<UUID, Device> getDevices();

    // Configured (persisted) state
    Map<UUID, Group> getConfiguredGroups();
    Map<UUID, System> getConfiguredSystems();
    Map<UUID, Device> getConfiguredDevices();

    // Create new system (Solo, Duo, Surround, Multi)
    Single<UUID> createSystem(String name, System.Type type, Map<UUID, Device.Role> devices);

    // Group operations
    Single<UUID> joinGroup(UUID systemId, UUID groupId);
    Single<UUID> ejectFromGroup(UUID systemId);

    // Device/System naming
    Completable setDeviceName(UUID deviceId, String name);
    Completable setSystemName(UUID systemId, String name);

    // Device configuration
    Completable setDeviceRoles(UUID systemId, Map<UUID, Device.Role> roles);
    Completable setDeviceSetupState(UUID deviceId, Device.SetupState state);
    Completable splitFromSystem(UUID deviceId);
}

GroupManager.java — Multi-room Group Operations

Kotlin coroutine-based interface for group management:

public interface GroupManager {
    // Check if group operations are allowed
    boolean canPerformGroupOperations(UUID groupId);

    // Get systems compatible with this group (same sync family)
    Set<UUID> getCompatibleSystems(UUID groupId);

    // Join a system to a group (suspend function - Kotlin coroutine)
    // Returns Result<UUID> - the new group ID
    Object join(UUID systemId, UUID groupId, Continuation<Result<UUID>> cont);

    // Remove system from its current group
    Object leaveGroup(UUID systemId, Continuation<Result<UUID>> cont);

    // Remove a system as group leader (makes another system leader)
    Object removeGroupLeader(UUID groupId, Continuation<Result<UUID>> cont);
}

Group.java — Group Data Model

public final class Group {
    private final UUID id;
    private final Set<UUID> systemIds;  // Systems in this group

    // Immutable operations - return new Group
    public Group plusSystem(UUID... systemIds);  // Add systems
    public Group minusSystem(UUID systemId);    // Remove system
}

Network Service Resolution

How Module Codenames Map to Network Services

The song-themed codenames you see in network traffic are internal service identifiers used by Devialet's WhatsUp endpoint resolver. The resolver maps Java class namespaces to network endpoints:

Java NamespaceService NameHTTP Endpoint PatternDescription
io.dvlt.canttouchthis CantTouchThis systems/current/settings/ledMode
systems/current/settings/powerManagement
LED mode, microphone, power control
io.dvlt.getthepartystarted GetThePartyStarted devices/*
systems/current/network
Device discovery, installation, network config
io.dvlt.whatsup WhatsUp Internal service discovery Endpoint resolver - maps services to URLs
io.dvlt.sourceofall SourceOfAll systems/current/sources/*
systems/current/sourceConfiguration
Source management, playback, volume
io.dvlt.settingthesystem SettingTheSystem systems/current/settings/audio/* All audio settings (EQ, night mode, etc.)
io.dvlt.masterofpuppets MasterOfPuppets groups/*
systems/*
Topology management (groups, systems)
io.dvlt.cometogether ComeTogether Via MasterOfPuppets Group join/leave operations
io.dvlt.fresh Fresh devices/current/update Firmware update management
io.dvlt.blue Blue systems/current/bluetooth Bluetooth configuration
io.dvlt.liveislife.* LiveIsLife systems/current/settings/* Hardware input configuration (Manolo, Paco, etc.)

Service Resolution Flow

// When you call setLedMode(), this happens internally:

// 1. Java layer (canttouchthis.Configuration)
configuration.setLedMode(LedMode.ALWAYS_ON);  // native method

// 2. JNI → Native (libmetaandroidd.so)
//    Calls into Qt/C++ code

// 3. EndpointResolver resolves service URL
Set<String> endpoints = endpointResolver.resolve(deviceUuid);
// Returns: ["http://192.168.1.x:80/ipcontrol/v1/"]

// 4. CallMeMaybe RPC serializes request as protobuf
//    or JSON depending on content-type

// 5. HTTP request sent:
PUT /ipcontrol/v1/systems/current/settings/ledMode
Content-Type: application/json
{"value": "alwaysOn"}

HTTP API vs Native Library — Feature Availability

⚠️ Important for Third-Party Implementations: Not all Devialet app features are accessible via the HTTP IP Control API. Group management operations require the native library (libmetaandroidd.so) which uses a proprietary protocol.

✅ Available via HTTP API (/ipcontrol/v1/)

These features can be implemented by any HTTP client (slPhantomRemote, Home Assistant, etc.):

CategoryFeaturesEndpoints
Playback Control Play, Pause, Stop, Next, Previous, Seek POST .../playback/play, .../pause, etc.
Volume Get/Set Volume, Mute/Unmute GET/POST .../volume, .../mute
Source Selection List sources, Switch source, Get current source GET .../sources, POST .../sources/current
Now Playing Track metadata, Album art, Position, Duration GET .../sources/current/soundControl/nowPlaying
Audio Settings Night Mode, Equalizer, Rendering Mode GET/POST .../settings/audio/nightMode, etc.
Device Info Model, Serial, Firmware, Network, Status GET .../general/info, .../network
Power Restart, Power Off POST .../power/restart, .../powerOff
LED/Display Brightness, Color GET/POST .../settings/led
Group Status Read group membership, list systems GET /groups/, /systems/
Bluetooth Pairing Activate pairing mode POST .../bluetooth/pairing

❌ Requires Native Library (Not Available via HTTP)

These features require libmetaandroidd.so and proprietary protocols — cannot be implemented via HTTP:

CategoryFeaturesSDK MethodWhy
Group Creation Create new multi-room group TopologyManager.createSystem() Uses native multicast protocol
Group Join Add device to existing group GroupManager.join() Requires peer-to-peer coordination
Group Leave Remove device from group GroupManager.leaveGroup() Must notify all group members
Leader Assignment Change group leader/master GroupManager.removeGroupLeader() Affects audio sync coordination
System Split Split stereo pair back to mono TopologyManager.splitFromSystem() Reconfigures audio routing
Device Roles Assign Left/Right/Mono roles TopologyManager.setDeviceRoles() Part of stereo pairing protocol
Firmware Update Download and install updates Native update protocol Secure signed update chain
Initial Setup Wi-Fi provisioning, first-time config Native setup flow Uses Bluetooth + proprietary handshake

What This Means for slPhantomRemote

Current Capability: slPhantomRemote can control playback, volume, sources, and read group status — covering ~80% of daily use cases.

Limitation: Users must use the official Devialet app (iOS/Android) to:

Workaround: Once groups are configured via the Devialet app, slPhantomRemote can control them using the /groups/ namespace.

Native Protocol Analysis (Future Research)

The native library uses these components for group management:

Reverse engineering would require:

  1. Packet capture during group operations (Wireshark)
  2. Analysis of Protocol Buffer message structures
  3. Understanding the multicast coordination protocol
  4. Potentially decompiling the native ARM64 library

This is a significant undertaking and may not be practical for a third-party project.

Architecture Notes

Protocol & Communication

Native Library Details

Hardware Codenames

Data collected via slPhantomRemote Device Management & Devialet APK v1.25 analysis (DEX + Native) • December 2025