mx-remote 7.0.0__tar.gz → 8.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mx_remote-7.0.0 → mx_remote-8.0.2}/PKG-INFO +1 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/api.md +100 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/callbacks.md +1 -1
- mx_remote-8.0.2/docs/devices-and-bays.md +94 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/oneip.md +103 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/routing.md +6 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/Interface.py +482 -51
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/Interface.pyi +168 -5
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/const.py +1 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/BayConfig.py +5 -4
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Constants.py +263 -15
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Constants.pyi +129 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Factory.py +9 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameAudioSetRoute.py +16 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameAudioSetRoute.pyi +3 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBase.py +65 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBase.pyi +7 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBayConfig.py +4 -0
- mx_remote-8.0.2/mx_remote/proto/FrameBayContent.py +77 -0
- mx_remote-8.0.2/mx_remote/proto/FrameBayContent.pyi +18 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBayHide.py +8 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBayStatus.py +5 -5
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameDiscover.py +12 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameDiscover.pyi +3 -0
- mx_remote-8.0.2/mx_remote/proto/FrameFactoryReset.py +51 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameFactoryReset.pyi +2 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameFilterStatus.py +7 -3
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameFirmwareVersion.py +34 -3
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameFirmwareVersion.pyi +2 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameHello.py +9 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameMirrorStatus.py +16 -8
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameMonitoringPulse.py +3 -3
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameNetworkStatus.py +6 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRCIr.py +11 -1
- mx_remote-8.0.2/mx_remote/proto/FrameReboot.py +39 -0
- mx_remote-8.0.2/mx_remote/proto/FrameReboot.pyi +13 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRoutingChange.py +17 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSetName.py +13 -8
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSetName.pyi +2 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSetRoute.py +5 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSetRoute.pyi +2 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSetupStatus.py +4 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSignalStatusNew.py +35 -15
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSysTemperature.py +3 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSystemStatus.py +4 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTopology.py +7 -3
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTxIR.py +3 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameUnitStatus.py +11 -5
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameUnitStatus.pyi +3 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPAudio.py +129 -26
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPAudio.pyi +21 -4
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPBayMapping.py +4 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPDeviceConfiguration.py +93 -55
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPDeviceConfiguration.pyi +9 -3
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPManualSourceSwitch.py +9 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPMultiviewer.py +4 -0
- mx_remote-8.0.2/mx_remote/proto/FrameV2IPOsdSync.py +251 -0
- mx_remote-8.0.2/mx_remote/proto/FrameV2IPOsdSync.pyi +41 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPSettingsAll.py +11 -5
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPSettingsAll.pyi +1 -1
- mx_remote-8.0.2/mx_remote/proto/FrameV2IPSinkSdp.py +122 -0
- mx_remote-8.0.2/mx_remote/proto/FrameV2IPSinkSdp.pyi +29 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPSourceSwitch.py +9 -3
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPTestcard.py +6 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameVolumeSet.py +18 -15
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/Bay.py +299 -42
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/Bay.pyi +19 -5
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/ConnectionAsync.py +5 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/ConnectionAsync.pyi +2 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/Device.py +278 -30
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/Device.pyi +34 -3
- mx_remote-8.0.2/mx_remote/remote/OsdSync.py +250 -0
- mx_remote-8.0.2/mx_remote/remote/OsdSync.pyi +47 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/Remote.py +175 -17
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/Remote.pyi +10 -3
- mx_remote-8.0.2/tests/audiolock.py +219 -0
- mx_remote-8.0.2/tests/baycontent.py +99 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/complete.py +31 -6
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/deprecated.py +37 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/e2e.py +43 -3
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/handlers.py +7 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/handlers_cover.py +26 -83
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/hello.py +3 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/idempotent.py +14 -9
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/lengths.py +3 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/merge.py +24 -24
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/mesh.py +17 -3
- mx_remote-8.0.2/tests/meshbays.py +295 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/newops.py +7 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/offline.py +23 -1
- mx_remote-8.0.2/tests/osdsync.py +315 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/ping.py +10 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/proto_stamp.py +2 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/rcsettings.py +4 -2
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/roundtrip.py +24 -1
- mx_remote-8.0.2/tests/routes.py +244 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/run.py +5 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/smoke.py +23 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/structs.py +5 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/unit.py +18 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/unknowns.py +24 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/v2ipscaling.py +17 -7
- mx_remote-8.0.2/tests/v2ipsdp.py +117 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/v2ipsettings.py +132 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/v2ipsubject.py +1 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/v2iptestcard.py +13 -1
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/wirefix.py +86 -33
- mx_remote-7.0.0/docs/devices-and-bays.md +0 -54
- mx_remote-7.0.0/mx_remote/proto/FrameFactoryReset.py +0 -53
- mx_remote-7.0.0/mx_remote/proto/FrameReboot.py +0 -21
- mx_remote-7.0.0/mx_remote/proto/FrameReboot.pyi +0 -6
- mx_remote-7.0.0/tests/audiolock.py +0 -119
- {mx_remote-7.0.0 → mx_remote-8.0.2}/.gitignore +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/AGENTS.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/CLAUDE.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/LICENSE +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/README.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/README.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/_static/brand.css +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/_static/favicon.svg +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/_static/logo-dark.svg +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/_static/logo.svg +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/audio.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/conf.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/configuration.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/diagnostics.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/index.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/multiviewer.md +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/docs/requirements.txt +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/hatch_build.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/Uid.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/Uid.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/__init__.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/__init__.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/compat.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/compat.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/const.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/deprecated.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/deprecated.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/main.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/main.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/BayConfig.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Data.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Data.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Factory.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameAmpDolbySettings.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameAmpDolbySettings.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameAmpZoneSettings.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameAmpZoneSettings.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameAudioClip.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameAudioClip.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBayConfig.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBayConfigSecondary.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBayConfigSecondary.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBayHide.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameBayStatus.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameConnectStatus.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameConnectStatus.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameDebug.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameDebug.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameEDID.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameEDID.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameEDIDProfile.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameEDIDProfile.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameFilterStatus.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameHeader.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameHeader.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameHello.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameLinks.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameLinks.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameMeshOperation.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameMeshOperation.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameMirrorStatus.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameMonitoringPulse.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameNetworkStatus.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FramePing.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FramePing.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FramePowerChange.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FramePowerChange.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRCAction.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRCAction.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRCIr.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRCKey.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRCKey.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRCSettings.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRCSettings.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameRoutingChange.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSetInstaller.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSetInstaller.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSetupStatus.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSignalStatus.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSignalStatus.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSignalStatusNew.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSysTemperature.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameSystemStatus.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTXRCAction.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTXRCAction.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTXRCKey.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTXRCKey.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTime.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTime.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTimeZone.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTimeZone.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTopology.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameTxIR.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameUnitCommand.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameUnitCommand.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameUpgradeFPGA.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameUpgradeFPGA.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPBayMapping.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPDetectBays.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPDetectBays.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPLink.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPLink.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPManualSourceSwitch.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPMultiviewer.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPPowerSave.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPPowerSave.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPSetMaster.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPSetMaster.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPSourceSwitch.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPSources.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPSources.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPStats.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPStats.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPTestcard.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPTiling.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPTiling.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPVideoWall.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameV2IPVideoWall.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameVolume.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameVolume.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameVolumeDown.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameVolumeDown.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameVolumeSet.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameVolumeUp.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/FrameVolumeUp.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/LinkConfig.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/LinkConfig.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Multiviewer.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Multiviewer.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Svd.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/Svd.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/V2IPConfig.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/V2IPConfig.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/V2IPStats.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/V2IPStats.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/__init__.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/__init__.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/proto/svd.csv +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/py.typed +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/Link.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/Link.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/State.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/State.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/V2IP.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/mx_remote/remote/V2IP.pyi +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/pyproject.toml +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/audio_ir.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/capture.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/entry.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/offsets.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/protogate.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/sources.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/staterequest.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/stats.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/txresult.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/v2ipptp.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/v2ipvlan.py +0 -0
- {mx_remote-7.0.0 → mx_remote-8.0.2}/tests/vdetails.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mx_remote
|
|
3
|
-
Version:
|
|
3
|
+
Version: 8.0.2
|
|
4
4
|
Summary: Python 3 library for interfacing with MX Remote compatible devices
|
|
5
5
|
Project-URL: Homepage, https://github.com/opdenkamp/mx-remote/
|
|
6
6
|
Project-URL: Documentation, https://opdenkamp.github.io/mx-remote/
|
|
@@ -31,6 +31,60 @@ they are what the registry hands out and what a callback receives.
|
|
|
31
31
|
:members:
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
## Bay content
|
|
35
|
+
|
|
36
|
+
What the source on an input is showing, and how much of it a unit keeps.
|
|
37
|
+
|
|
38
|
+
```{eval-rst}
|
|
39
|
+
.. autodata:: mx_remote.proto.Constants.BAY_CONTENT_KEY_MAX
|
|
40
|
+
|
|
41
|
+
.. autodata:: mx_remote.proto.Constants.BAY_CONTENT_VALUE_MAX
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Overlay sync
|
|
45
|
+
|
|
46
|
+
A management unit having other units copy its overlay captions, logo choice and
|
|
47
|
+
place, backgrounds and logo images.
|
|
48
|
+
|
|
49
|
+
```{eval-rst}
|
|
50
|
+
.. autoclass:: mx_remote.proto.Constants.OsdSyncWhat
|
|
51
|
+
:members:
|
|
52
|
+
|
|
53
|
+
.. autoclass:: mx_remote.proto.Constants.OsdSyncState
|
|
54
|
+
:members:
|
|
55
|
+
|
|
56
|
+
.. autoclass:: mx_remote.proto.Constants.OsdSyncSize
|
|
57
|
+
:members:
|
|
58
|
+
|
|
59
|
+
.. autoclass:: mx_remote.proto.Constants.OsdCaptionAlign
|
|
60
|
+
:members:
|
|
61
|
+
|
|
62
|
+
.. autoclass:: mx_remote.proto.Constants.OsdCaptionFormat
|
|
63
|
+
:members:
|
|
64
|
+
|
|
65
|
+
.. autoclass:: mx_remote.proto.Constants.OsdCaptionField
|
|
66
|
+
:members:
|
|
67
|
+
|
|
68
|
+
.. autoclass:: mx_remote.proto.Constants.OsdLogoField
|
|
69
|
+
:members:
|
|
70
|
+
|
|
71
|
+
.. autodata:: mx_remote.proto.Constants.OSD_SYNC_SLOTS
|
|
72
|
+
|
|
73
|
+
.. autodata:: mx_remote.proto.Constants.OSD_SYNC_RECORDS_MAX
|
|
74
|
+
|
|
75
|
+
.. autodata:: mx_remote.proto.Constants.OSD_SYNC_FONT_MAX
|
|
76
|
+
|
|
77
|
+
.. autodata:: mx_remote.proto.Constants.OSD_SYNC_TEXT_MAX
|
|
78
|
+
|
|
79
|
+
.. autodata:: mx_remote.proto.Constants.OSD_SYNC_IMAGE_MAX
|
|
80
|
+
|
|
81
|
+
.. autodata:: mx_remote.proto.Constants.OSD_SYNC_IMAGE_WIDTH_MAX
|
|
82
|
+
|
|
83
|
+
.. autodata:: mx_remote.proto.Constants.OSD_SYNC_IMAGE_HEIGHT_MAX
|
|
84
|
+
|
|
85
|
+
.. autodata:: mx_remote.proto.Constants.OSD_SYNC_PERCENT_MAX
|
|
86
|
+
```
|
|
87
|
+
|
|
34
88
|
## Device identity
|
|
35
89
|
|
|
36
90
|
```{eval-rst}
|
|
@@ -81,6 +135,9 @@ bit, and the range of the infrared profiles.
|
|
|
81
135
|
.. autoclass:: mx_remote.OneIPPowerSaveSchedule
|
|
82
136
|
:members:
|
|
83
137
|
|
|
138
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPPowerSaveLevel
|
|
139
|
+
:members:
|
|
140
|
+
|
|
84
141
|
.. autoclass:: mx_remote.OneIPVlan
|
|
85
142
|
:members:
|
|
86
143
|
|
|
@@ -114,6 +171,15 @@ state only the device reports.
|
|
|
114
171
|
|
|
115
172
|
.. autodata:: mx_remote.proto.Constants.ONEIP_DEVICE_SETTINGS_PTP
|
|
116
173
|
|
|
174
|
+
.. autoclass:: mx_remote.OneIPPtpMessages
|
|
175
|
+
:members:
|
|
176
|
+
|
|
177
|
+
.. autodata:: mx_remote.proto.Constants.ONEIP_DEVICE_SETTINGS_PTP_MESSAGES
|
|
178
|
+
|
|
179
|
+
.. autodata:: mx_remote.proto.Constants.ONEIP_DEVICE_SETTINGS_BLOCK
|
|
180
|
+
|
|
181
|
+
.. autodata:: mx_remote.proto.Constants.ONEIP_STREAM_TTL_DEFAULT
|
|
182
|
+
|
|
117
183
|
.. autodata:: mx_remote.proto.Constants.ONEIP_PTP_DOMAIN_MAX
|
|
118
184
|
```
|
|
119
185
|
|
|
@@ -138,6 +204,40 @@ A unit's health and IP configuration, and the commands sent to one unit.
|
|
|
138
204
|
:members:
|
|
139
205
|
|
|
140
206
|
.. autodata:: mx_remote.proto.Constants.UNIT_MAX_TEMPERATURES
|
|
207
|
+
|
|
208
|
+
.. autoclass:: mx_remote.proto.Constants.UnitPowerSave
|
|
209
|
+
:members:
|
|
210
|
+
|
|
211
|
+
.. autodata:: mx_remote.proto.Constants.UNIT_POWER_SAVE_LEVELS
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## OneIP session descriptions
|
|
215
|
+
|
|
216
|
+
What an output plays from a session description, and how it is timed.
|
|
217
|
+
|
|
218
|
+
```{eval-rst}
|
|
219
|
+
.. autoclass:: mx_remote.OneIPSinkSdp
|
|
220
|
+
:members:
|
|
221
|
+
|
|
222
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPSdpFlag
|
|
223
|
+
:members:
|
|
224
|
+
|
|
225
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPSdpEncoding
|
|
226
|
+
:members:
|
|
227
|
+
|
|
228
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPSdpMediaClock
|
|
229
|
+
:members:
|
|
230
|
+
|
|
231
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPSdpRefClock
|
|
232
|
+
:members:
|
|
233
|
+
|
|
234
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPSdpClockMode
|
|
235
|
+
:members:
|
|
236
|
+
|
|
237
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPSdpClockState
|
|
238
|
+
:members:
|
|
239
|
+
|
|
240
|
+
.. autodata:: mx_remote.proto.Constants.ONEIP_SDP_MAX
|
|
141
241
|
```
|
|
142
242
|
|
|
143
243
|
## OneIP test card
|
|
@@ -51,7 +51,7 @@ Available callback methods:
|
|
|
51
51
|
| `on_status_signal_detected_changed` | signal detect status changed |
|
|
52
52
|
| `on_status_faulty_changed` | fault status changed |
|
|
53
53
|
| `on_status_hidden_changed` | hidden status changed |
|
|
54
|
-
| `
|
|
54
|
+
| `on_status_zone_powered_changed` | The amplifier zone a bay drives powered on or off (ProAmp8v2) |
|
|
55
55
|
| `on_status_hdbt_connected_changed` | HDBaseT link status changed |
|
|
56
56
|
| `on_status_signal_type_changed` | signal type changed |
|
|
57
57
|
| `on_status_hpd_detected_changed` | hotplug detect changed |
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Devices and bays
|
|
2
|
+
|
|
3
|
+
Naming, hiding, EDID and the device registry.
|
|
4
|
+
|
|
5
|
+
## Device Management
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
# reboot a device
|
|
9
|
+
await device.reboot()
|
|
10
|
+
|
|
11
|
+
# ask a device to hello now; False for one below protocol 0x2A
|
|
12
|
+
await device.ping()
|
|
13
|
+
|
|
14
|
+
# read the device log
|
|
15
|
+
log = await device.get_log()
|
|
16
|
+
|
|
17
|
+
# call an HTTP API endpoint on the device
|
|
18
|
+
result = await device.get_api("system/status")
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
A device on protocol 0x2A pings a peer it suspects is gone and takes it
|
|
22
|
+
offline when nothing answers within about 1.5s. The client answers a ping
|
|
23
|
+
addressed to it with a hello at once, from any sender.
|
|
24
|
+
|
|
25
|
+
## Bay Naming
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
await bay.set_name("Living Room TV")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Bay Visibility
|
|
32
|
+
|
|
33
|
+
Hide or show bays:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
await bay.set_hidden(True) # hide
|
|
37
|
+
await bay.set_hidden(False) # show
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## EDID Profiles
|
|
41
|
+
|
|
42
|
+
Change the EDID profile on input bays:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from mx_remote import EdidProfile
|
|
46
|
+
|
|
47
|
+
await bay.select_edid_profile(EdidProfile.TEMPLATE_1080P_STEREO)
|
|
48
|
+
await bay.select_edid_profile(EdidProfile.TEMPLATE_4K_HDR_7_1)
|
|
49
|
+
await bay.select_edid_profile(EdidProfile.LOWEST_COMMON_DENOMINATOR)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Bay Content
|
|
53
|
+
|
|
54
|
+
A unit with a source driver, such as the Sky Q one, reports what the source on
|
|
55
|
+
an input is showing as named values, in the order they are meant to be shown:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
print(bay.content) # e.g. name='BBC One', number='101'
|
|
59
|
+
print(bay.content.get('name')) # None when the source reports no such value
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The names are open-ended: a driver for a new kind of source adds its own, so
|
|
63
|
+
pass on the ones you do not know. Each value is cleaned as a receiving unit
|
|
64
|
+
cleans it, so it reads as the unit's own API shows it. The content outlives the
|
|
65
|
+
signal, so check `signal_detected` before showing it. `on_bay_content_changed`
|
|
66
|
+
reports a change, and an empty `content` is a source showing nothing.
|
|
67
|
+
|
|
68
|
+
## Mesh Bays
|
|
69
|
+
|
|
70
|
+
A OneIP unit lists the inputs and outputs of the other units in its mesh as
|
|
71
|
+
bays of its own. Such a mesh bay stands for bay 0 in the same direction on the
|
|
72
|
+
unit its `oneip_uid` names, and `is_local` is False for it.
|
|
73
|
+
|
|
74
|
+
A mesh bay keeps only its identity: its port, `bay_name`, bay number, features
|
|
75
|
+
and `oneip_uid`. Everything else - its user name, signal, status, routes and
|
|
76
|
+
volume - is read from the bay it stands for, since what one unit reports about
|
|
77
|
+
another unit's bay is a copy that is never refreshed. Until that unit has
|
|
78
|
+
reported the bay, the rest reads as never reported. A change to the bay is
|
|
79
|
+
reported for every mesh bay standing for it too, except its registration and
|
|
80
|
+
the key presses and actions that arrive on it.
|
|
81
|
+
|
|
82
|
+
A command about a mesh bay - a rename, hide, EDID profile, action, key,
|
|
83
|
+
power, volume, zone settings or route - goes to the unit it stands for, about
|
|
84
|
+
that unit's bay, and is refused while that unit has not reported the bay. A
|
|
85
|
+
route names that unit as the sink, and its source by port in the numbering of
|
|
86
|
+
the unit listing the mesh bay.
|
|
87
|
+
|
|
88
|
+
Mesh bays are created by the unit's bay mappings, numbered by port in the
|
|
89
|
+
unit's own numbering: from protocol 0x2B input n is port n and output n port
|
|
90
|
+
127 + n; below it the first 16 bays of each direction come first.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
[Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
|
|
@@ -107,9 +107,9 @@ output mode. Each is written behind its own validity bit, so moving one leaves
|
|
|
107
107
|
the other where it is.
|
|
108
108
|
|
|
109
109
|
```python
|
|
110
|
-
# what the sink reports
|
|
110
|
+
# what the sink reports, read only from a device whose hello carries
|
|
111
111
|
# CONFIG_INITIALISED - firmware without it builds the block over uninitialised
|
|
112
|
-
# stack, where the valid bit itself is noise.
|
|
112
|
+
# stack, where the valid bit itself is noise. No released build announces it.
|
|
113
113
|
scaling = device.oneip_details.scaling
|
|
114
114
|
print(scaling.auto_scaling) # None when the sender did not say
|
|
115
115
|
print(scaling.configured_mode) # (signal type, refresh), None when it has none
|
|
@@ -133,6 +133,9 @@ in silence. Setting the mode first and turning automatic scaling back on
|
|
|
133
133
|
afterwards is the order that survives, because the mode is checked while
|
|
134
134
|
automatic scaling is still off.
|
|
135
135
|
|
|
136
|
+
These are refused for a unit below protocol 0x2F: released firmware drops a
|
|
137
|
+
scaling write from management.
|
|
138
|
+
|
|
136
139
|
Nothing acknowledges any of these. `set_oneip_output_mode` returns False for a
|
|
137
140
|
mode no sink would take, but a True only says the frame went out: the sink
|
|
138
141
|
weighs the format against the display's EDID and against what its own output
|
|
@@ -222,6 +225,28 @@ goes out at 176 bytes: a receiver with the schedule ignores the settings of a
|
|
|
222
225
|
shorter frame, and one whose settings end at the idle minutes takes it all the
|
|
223
226
|
same.
|
|
224
227
|
|
|
228
|
+
How far a device powers down is its power save level: reduced, low or off, each
|
|
229
|
+
powering more down than the one before. Its unit status says which levels it
|
|
230
|
+
supports and what wakes it at each.
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
from mx_remote import OneIPPowerSaveLevel, UnitPowerSave
|
|
234
|
+
|
|
235
|
+
print(settings.power_save_level)
|
|
236
|
+
print(device.unit_status.power_save_level(OneIPPowerSaveLevel.LOW)) # e.g. SUPPORTED|INPUT_WAKE
|
|
237
|
+
|
|
238
|
+
await device.set_oneip_power_save_level(OneIPPowerSaveLevel.LOW)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
A level this library does not name is refused before it is sent, and not cached
|
|
242
|
+
from another controller's write.
|
|
243
|
+
|
|
244
|
+
`OneIPDeviceSetting.POWER_SAVE_DISABLED` is a switch that keeps a device from
|
|
245
|
+
powering down by itself; a power save request still powers it down. A device
|
|
246
|
+
that takes a power save level switches it off, so a level write, this client's
|
|
247
|
+
or another sender's, clears it unless the same frame states it. Firmware
|
|
248
|
+
without the bit never reports it, and the switch is refused there.
|
|
249
|
+
|
|
225
250
|
### PTP
|
|
226
251
|
|
|
227
252
|
A device's PTP mode, domain and grandmaster priority1 are settings like the
|
|
@@ -240,6 +265,31 @@ await device.set_oneip_ptp_priority1(128) # lower wins
|
|
|
240
265
|
A mode this library does not name and a domain above `ONEIP_PTP_DOMAIN_MAX` are
|
|
241
266
|
refused before they are sent, and not cached from another controller's write.
|
|
242
267
|
|
|
268
|
+
How the device paces its PTP messages is five settings more, whose values
|
|
269
|
+
travel in a block of their own: the announce, sync and delay request intervals
|
|
270
|
+
as base-2 logarithms of seconds, the announce timeout and the messages' DSCP.
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
from mx_remote import OneIPDeviceSetting, OneIPPtpMessages
|
|
274
|
+
|
|
275
|
+
print(settings.ptp_messages) # None until the device reports one of them
|
|
276
|
+
|
|
277
|
+
await device.set_oneip_ptp_messages(
|
|
278
|
+
OneIPDeviceSetting.PTP_SYNC | OneIPDeviceSetting.PTP_DSCP,
|
|
279
|
+
OneIPPtpMessages(log_sync_interval=-3, dscp=46)) # 125 ms, EF
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The SAP expiry in minutes and announcement interval in seconds travel in the
|
|
283
|
+
same block, behind `SAP_EXPIRE` and `SAP_INTERVAL`, and are set the same way;
|
|
284
|
+
`SAP_LISTEN` and `SAP_ANNOUNCE` are switches like the other on/off settings.
|
|
285
|
+
A device with an encoder reports its streams' TTL there too, behind
|
|
286
|
+
`STREAM_TTL`; a TTL of 0 is refused, as a device changes nothing for one.
|
|
287
|
+
|
|
288
|
+
Only the values behind the bits named are sent. A DSCP above `ONEIP_DSCP_MAX` is
|
|
289
|
+
refused, and not cached from another controller's write. A write carrying one of
|
|
290
|
+
these runs on to 224 bytes, or 232 with the TTL; every other write keeps the 176
|
|
291
|
+
every device knows.
|
|
292
|
+
|
|
243
293
|
What the device's clock is actually doing is its PTP state, which only the
|
|
244
294
|
device reports about itself and nothing writes:
|
|
245
295
|
|
|
@@ -311,6 +361,57 @@ falls outside them in silence: see `OneIPTestTone.is_valid()` and
|
|
|
311
361
|
as the sink stops it regardless. The frame needs protocol 0x2B, so a sink
|
|
312
362
|
announcing less is refused as well.
|
|
313
363
|
|
|
364
|
+
### Session descriptions
|
|
365
|
+
|
|
366
|
+
An output plays an AES67 stream from a session description it is handed, and
|
|
367
|
+
reports what it plays when that changes and at least once a minute.
|
|
368
|
+
|
|
369
|
+
```python
|
|
370
|
+
await sink.play_oneip_sdp(sdp_text) # sent in 1 KB pages, played once the last is in
|
|
371
|
+
await sink.set_oneip_sdp_screen(1) # what it shows while it plays audio alone
|
|
372
|
+
await sink.request_oneip_sink_sdp() # report now
|
|
373
|
+
await sink.stop_oneip_sdp()
|
|
374
|
+
|
|
375
|
+
print(sink.oneip_sink_sdp) # None until the output has reported
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
An output takes these only from its mesh controller or a management
|
|
379
|
+
application, which this client announces itself as, and only from protocol
|
|
380
|
+
0x2E. A description is 1 to `ONEIP_SDP_MAX` bytes: an output drops a longer one
|
|
381
|
+
after its last page, so one is refused before it is sent. Nothing acknowledges
|
|
382
|
+
the pages; `oneip_sink_sdp` reads what the output reports next.
|
|
383
|
+
|
|
384
|
+
### Overlay sync
|
|
385
|
+
|
|
386
|
+
A management unit can have the other units copy its overlay captions, logo
|
|
387
|
+
choice and place, backgrounds and logo images. Watching one between units:
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
print(controller.osd_sync) # the last sync it sent
|
|
391
|
+
print(unit.osd_sync_report) # taking, done, failed or deferred, and why
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
This client can send one too, which every unit then takes:
|
|
395
|
+
|
|
396
|
+
```python
|
|
397
|
+
from mx_remote import OsdCaption, OsdSyncContent, OsdSyncEntry, OsdSyncImage
|
|
398
|
+
from mx_remote.proto.Constants import OsdCaptionField, OsdSyncWhat
|
|
399
|
+
|
|
400
|
+
seq = await mx.send_osd_sync(OsdSyncContent(
|
|
401
|
+
what=OsdSyncWhat.CAPTIONS,
|
|
402
|
+
entries=(OsdSyncEntry(value=OsdCaption(text='Lobby'), set=OsdCaptionField.TEXT),),
|
|
403
|
+
images=None)) # or four OsdSyncImage, served by this client
|
|
404
|
+
await mx.resend_osd_sync(unit) # one unit again
|
|
405
|
+
await mx.clear_osd_sync() # stop answering for it
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Each unit asks for the settings it lacks and takes only those, so this client
|
|
409
|
+
holds the content and answers until it is replaced or cleared, announcing
|
|
410
|
+
itself meanwhile as the mesh's overlay sync manager: a unit waking from power
|
|
411
|
+
save then takes this content rather than the controller's. Logo images are
|
|
412
|
+
served over HTTP from this client, on `logo_port` or a free port. Content a unit
|
|
413
|
+
would refuse is refused before anything is sent; see `send_osd_sync`.
|
|
414
|
+
|
|
314
415
|
### Every device at once
|
|
315
416
|
|
|
316
417
|
One broadcast changes settings on every OneIP device of the mesh. Each device
|
|
@@ -19,6 +19,12 @@ await output.select_video_source_by_user_name("Blu-ray")
|
|
|
19
19
|
await output.select_audio_source(source=0)
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
On a OneIP output the audio follows the video once the video is routed: a
|
|
23
|
+
separate audio route is dropped, so route the audio after the video to keep the
|
|
24
|
+
two apart. A unit below protocol 0x27 is told the source's audio stream
|
|
25
|
+
instead, since some of those route no audio for "follow the video".
|
|
26
|
+
`audio_source` reads the video source while the audio follows it.
|
|
27
|
+
|
|
22
28
|
---
|
|
23
29
|
|
|
24
30
|
[Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
|