mx-remote 5.4.0__tar.gz → 5.5.1__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.
Files changed (221) hide show
  1. {mx_remote-5.4.0 → mx_remote-5.5.1}/AGENTS.md +22 -0
  2. {mx_remote-5.4.0 → mx_remote-5.5.1}/PKG-INFO +17 -11
  3. {mx_remote-5.4.0 → mx_remote-5.5.1}/README.md +14 -9
  4. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/README.md +1 -1
  5. mx_remote-5.5.1/docs/_static/brand.css +34 -0
  6. mx_remote-5.5.1/docs/_static/favicon.svg +3 -0
  7. mx_remote-5.5.1/docs/_static/logo-dark.svg +8 -0
  8. mx_remote-5.5.1/docs/_static/logo.svg +8 -0
  9. mx_remote-5.5.1/docs/api.md +59 -0
  10. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/audio.md +1 -1
  11. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/callbacks.md +1 -1
  12. mx_remote-5.5.1/docs/conf.py +102 -0
  13. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/configuration.md +1 -1
  14. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/devices-and-bays.md +1 -1
  15. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/diagnostics.md +1 -1
  16. mx_remote-5.5.1/docs/index.md +34 -0
  17. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/multiviewer.md +1 -1
  18. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/oneip.md +1 -1
  19. mx_remote-5.5.1/docs/requirements.txt +3 -0
  20. {mx_remote-5.4.0 → mx_remote-5.5.1}/docs/routing.md +1 -1
  21. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/Interface.py +2 -2
  22. mx_remote-5.5.1/mx_remote/compat.py +22 -0
  23. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/const.py +1 -1
  24. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Constants.py +5 -6
  25. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBayConfig.py +1 -1
  26. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameFactoryReset.py +1 -1
  27. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameLinks.py +1 -1
  28. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSystemStatus.py +1 -1
  29. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSystemStatus.pyi +1 -1
  30. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPAudio.py +2 -2
  31. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPAudio.pyi +1 -1
  32. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPBayMapping.py +1 -1
  33. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPBayMapping.pyi +1 -1
  34. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPMultiviewer.py +1 -1
  35. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPMultiviewer.pyi +1 -1
  36. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPVideoWall.py +2 -3
  37. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/V2IPConfig.py +2 -1
  38. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/V2IPConfig.pyi +2 -1
  39. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/V2IPStats.py +3 -3
  40. mx_remote-5.5.1/mx_remote/py.typed +0 -0
  41. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/Bay.py +2 -1
  42. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/Bay.pyi +2 -1
  43. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/ConnectionAsync.py +2 -2
  44. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/Device.py +2 -1
  45. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/Device.pyi +2 -1
  46. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/Remote.py +4 -3
  47. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/Remote.pyi +2 -1
  48. {mx_remote-5.4.0 → mx_remote-5.5.1}/pyproject.toml +3 -1
  49. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/capture.py +2 -3
  50. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/hello.py +2 -2
  51. {mx_remote-5.4.0 → mx_remote-5.5.1}/.gitignore +0 -0
  52. {mx_remote-5.4.0 → mx_remote-5.5.1}/CLAUDE.md +0 -0
  53. {mx_remote-5.4.0 → mx_remote-5.5.1}/LICENSE +0 -0
  54. {mx_remote-5.4.0 → mx_remote-5.5.1}/hatch_build.py +0 -0
  55. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/Interface.pyi +0 -0
  56. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/Uid.py +0 -0
  57. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/Uid.pyi +0 -0
  58. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/__init__.py +0 -0
  59. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/__init__.pyi +0 -0
  60. /mx_remote-5.4.0/mx_remote/py.typed → /mx_remote-5.5.1/mx_remote/compat.pyi +0 -0
  61. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/const.pyi +0 -0
  62. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/main.py +0 -0
  63. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/main.pyi +0 -0
  64. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/BayConfig.py +0 -0
  65. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/BayConfig.pyi +0 -0
  66. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Constants.pyi +0 -0
  67. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Data.py +0 -0
  68. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Data.pyi +0 -0
  69. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Factory.py +0 -0
  70. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Factory.pyi +0 -0
  71. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameAmpDolbySettings.py +0 -0
  72. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameAmpDolbySettings.pyi +0 -0
  73. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameAmpZoneSettings.py +0 -0
  74. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameAmpZoneSettings.pyi +0 -0
  75. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameAudioClip.py +0 -0
  76. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameAudioClip.pyi +0 -0
  77. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameAudioSetRoute.py +0 -0
  78. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameAudioSetRoute.pyi +0 -0
  79. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBase.py +0 -0
  80. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBase.pyi +0 -0
  81. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBayConfig.pyi +0 -0
  82. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBayConfigSecondary.py +0 -0
  83. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBayConfigSecondary.pyi +0 -0
  84. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBayHide.py +0 -0
  85. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBayHide.pyi +0 -0
  86. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBayStatus.py +0 -0
  87. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameBayStatus.pyi +0 -0
  88. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameConnectStatus.py +0 -0
  89. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameConnectStatus.pyi +0 -0
  90. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameDebug.py +0 -0
  91. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameDebug.pyi +0 -0
  92. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameDiscover.py +0 -0
  93. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameDiscover.pyi +0 -0
  94. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameEDID.py +0 -0
  95. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameEDID.pyi +0 -0
  96. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameEDIDProfile.py +0 -0
  97. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameEDIDProfile.pyi +0 -0
  98. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameFactoryReset.pyi +0 -0
  99. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameFilterStatus.py +0 -0
  100. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameFilterStatus.pyi +0 -0
  101. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameFirmwareVersion.py +0 -0
  102. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameFirmwareVersion.pyi +0 -0
  103. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameHeader.py +0 -0
  104. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameHeader.pyi +0 -0
  105. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameHello.py +0 -0
  106. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameHello.pyi +0 -0
  107. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameLinks.pyi +0 -0
  108. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameMeshOperation.py +0 -0
  109. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameMeshOperation.pyi +0 -0
  110. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameMirrorStatus.py +0 -0
  111. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameMirrorStatus.pyi +0 -0
  112. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameMonitoringPulse.py +0 -0
  113. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameMonitoringPulse.pyi +0 -0
  114. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameNetworkStatus.py +0 -0
  115. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameNetworkStatus.pyi +0 -0
  116. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FramePowerChange.py +0 -0
  117. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FramePowerChange.pyi +0 -0
  118. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRCAction.py +0 -0
  119. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRCAction.pyi +0 -0
  120. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRCIr.py +0 -0
  121. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRCIr.pyi +0 -0
  122. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRCKey.py +0 -0
  123. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRCKey.pyi +0 -0
  124. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRCSettings.py +0 -0
  125. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRCSettings.pyi +0 -0
  126. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameReboot.py +0 -0
  127. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameReboot.pyi +0 -0
  128. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRoutingChange.py +0 -0
  129. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameRoutingChange.pyi +0 -0
  130. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSetInstaller.py +0 -0
  131. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSetInstaller.pyi +0 -0
  132. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSetName.py +0 -0
  133. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSetName.pyi +0 -0
  134. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSetRoute.py +0 -0
  135. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSetRoute.pyi +0 -0
  136. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSetupStatus.py +0 -0
  137. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSetupStatus.pyi +0 -0
  138. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSignalStatus.py +0 -0
  139. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSignalStatus.pyi +0 -0
  140. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSignalStatusNew.py +0 -0
  141. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSignalStatusNew.pyi +0 -0
  142. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSysTemperature.py +0 -0
  143. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameSysTemperature.pyi +0 -0
  144. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameTXRCAction.py +0 -0
  145. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameTXRCAction.pyi +0 -0
  146. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameTXRCKey.py +0 -0
  147. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameTXRCKey.pyi +0 -0
  148. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameTopology.py +0 -0
  149. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameTopology.pyi +0 -0
  150. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameTxIR.py +0 -0
  151. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameTxIR.pyi +0 -0
  152. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameUpgradeFPGA.py +0 -0
  153. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameUpgradeFPGA.pyi +0 -0
  154. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPDetectBays.py +0 -0
  155. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPDetectBays.pyi +0 -0
  156. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPDeviceConfiguration.py +0 -0
  157. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPDeviceConfiguration.pyi +0 -0
  158. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPLink.py +0 -0
  159. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPLink.pyi +0 -0
  160. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPManualSourceSwitch.py +0 -0
  161. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPManualSourceSwitch.pyi +0 -0
  162. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPPowerSave.py +0 -0
  163. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPPowerSave.pyi +0 -0
  164. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPSetMaster.py +0 -0
  165. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPSetMaster.pyi +0 -0
  166. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPSourceSwitch.py +0 -0
  167. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPSourceSwitch.pyi +0 -0
  168. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPSources.py +0 -0
  169. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPSources.pyi +0 -0
  170. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPStats.py +0 -0
  171. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPStats.pyi +0 -0
  172. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPTiling.py +0 -0
  173. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPTiling.pyi +0 -0
  174. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameV2IPVideoWall.pyi +0 -0
  175. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameVolume.py +0 -0
  176. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameVolume.pyi +0 -0
  177. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameVolumeDown.py +0 -0
  178. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameVolumeDown.pyi +0 -0
  179. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameVolumeSet.py +0 -0
  180. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameVolumeSet.pyi +0 -0
  181. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameVolumeUp.py +0 -0
  182. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/FrameVolumeUp.pyi +0 -0
  183. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/LinkConfig.py +0 -0
  184. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/LinkConfig.pyi +0 -0
  185. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Multiviewer.py +0 -0
  186. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Multiviewer.pyi +0 -0
  187. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Svd.py +0 -0
  188. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/Svd.pyi +0 -0
  189. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/V2IPStats.pyi +0 -0
  190. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/__init__.py +0 -0
  191. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/__init__.pyi +0 -0
  192. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/proto/svd.csv +0 -0
  193. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/ConnectionAsync.pyi +0 -0
  194. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/Link.py +0 -0
  195. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/Link.pyi +0 -0
  196. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/State.py +0 -0
  197. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/State.pyi +0 -0
  198. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/V2IP.py +0 -0
  199. {mx_remote-5.4.0 → mx_remote-5.5.1}/mx_remote/remote/V2IP.pyi +0 -0
  200. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/audio_ir.py +0 -0
  201. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/e2e.py +0 -0
  202. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/entry.py +0 -0
  203. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/handlers.py +0 -0
  204. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/handlers_cover.py +0 -0
  205. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/idempotent.py +0 -0
  206. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/merge.py +0 -0
  207. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/newops.py +0 -0
  208. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/offsets.py +0 -0
  209. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/proto_stamp.py +0 -0
  210. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/protogate.py +0 -0
  211. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/rcsettings.py +0 -0
  212. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/roundtrip.py +0 -0
  213. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/run.py +0 -0
  214. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/smoke.py +0 -0
  215. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/sources.py +0 -0
  216. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/stats.py +0 -0
  217. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/structs.py +0 -0
  218. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/txresult.py +0 -0
  219. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/unknowns.py +0 -0
  220. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/vdetails.py +0 -0
  221. {mx_remote-5.4.0 → mx_remote-5.5.1}/tests/wirefix.py +0 -0
@@ -73,6 +73,13 @@ A client's uid is persisted at `~/.mxr-uid`, one file per account, and
73
73
  account are a single identity to the mesh and each discards everything the other
74
74
  sends, so a second one needs its own `uid_path`.
75
75
 
76
+ ### Python versions
77
+ `requires-python` is 3.11, and `.github/workflows/tests.yml` runs the suites on
78
+ 3.11, 3.12 and 3.13 so that floor is checked rather than assumed. A name that
79
+ only exists on a newer version goes through `mx_remote/compat.py`, the one place
80
+ that tests `sys.version_info`, and its fallback needs a dependency marked
81
+ `python_version < '<the version that added it>'` in `pyproject.toml`.
82
+
76
83
  ### Versioning
77
84
  Version is single-sourced in `mx_remote/const.py` (`VERSION = '...'`); `pyproject.toml`
78
85
  reads it via regex, so bump it there only. Release commits follow the convention
@@ -83,6 +90,21 @@ reads it via regex, so bump it there only. Release commits follow the convention
83
90
  force-includes them in the wheel (they are gitignored). `mx_remote` ships as typed
84
91
  (`py.typed`). If stubgen produces nothing the build fails by design.
85
92
 
93
+ ### Documentation
94
+ `docs/` is both the GitHub-readable guide set and the Sphinx source for
95
+ [the published site](https://opdenkamp.github.io/mx-remote/), which
96
+ `.github/workflows/docs.yml` rebuilds on every push to master. Build it the way
97
+ the workflow does:
98
+
99
+ ```sh
100
+ pip install . -r docs/requirements.txt
101
+ sphinx-build -b html -W --keep-going docs site
102
+ ```
103
+
104
+ Autodoc emits reStructuredText, so a directive belongs in an ```` ```{eval-rst} ````
105
+ block. Outside one it renders as its own source and the build still reports
106
+ success — the workflow greps the output for that.
107
+
86
108
  ## Architecture
87
109
 
88
110
  Three layers, decoupled by abstract base classes:
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: mx_remote
3
- Version: 5.4.0
3
+ Version: 5.5.1
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
- Project-URL: Documentation, https://github.com/opdenkamp/mx-remote/
6
+ Project-URL: Documentation, https://opdenkamp.github.io/mx-remote/
7
7
  Project-URL: Repository, https://github.com/opdenkamp/mx-remote.git
8
8
  Project-URL: Bug Tracker, https://github.com/opdenkamp/mx-remote/issues
9
9
  Author-email: Lars Op den Kamp <lars@opdenkamp-it.nl>
@@ -28,6 +28,7 @@ Requires-Python: >=3.11
28
28
  Requires-Dist: aiofiles>=24.1.0
29
29
  Requires-Dist: aiohttp>=3.10.5
30
30
  Requires-Dist: netifaces>=0.11.0
31
+ Requires-Dist: typing-extensions>=4.4; python_version < '3.12'
31
32
  Description-Content-Type: text/markdown
32
33
 
33
34
  # MX Remote - Python Client for Pulse-Eight MatrixOS devices
@@ -41,6 +42,8 @@ streaming, multiviewer control, and more.
41
42
  If you are looking to integrate Pulse-Eight **neo**, **OneIP**, or **ProAmp8** devices into
42
43
  your own software or home-automation system, this is the library for it.
43
44
 
45
+ **Documentation:** [opdenkamp.github.io/mx-remote](https://opdenkamp.github.io/mx-remote/)
46
+
44
47
  ## What is MX Remote?
45
48
 
46
49
  MX Remote is the network protocol these Pulse-Eight devices use to discover and control one
@@ -97,18 +100,21 @@ asyncio.run(main())
97
100
 
98
101
  ## Documentation
99
102
 
100
- The full API reference lives in [docs/](docs/README.md).
103
+ The guides below are published at
104
+ **[opdenkamp.github.io/mx-remote](https://opdenkamp.github.io/mx-remote/)** alongside an
105
+ API reference generated from the docstrings, and are readable here in
106
+ [docs/](docs/README.md).
101
107
 
102
108
  | Page | Covers |
103
109
  | --- | --- |
104
- | [Configuration](configuration.md) | Opening a connection and keeping it in step with the mesh. |
105
- | [Devices and bays](devices-and-bays.md) | Naming, hiding, EDID and the device registry. |
106
- | [Routing](routing.md) | Selecting video and audio sources for an output. |
107
- | [Callbacks](callbacks.md) | Reacting to state changes rather than polling for them. |
108
- | [Audio](audio.md) | Volume, mute and remote-control passthrough. |
109
- | [OneIP and V2IP](oneip.md) | Streaming endpoints, stream sources and statistics. |
110
- | [Multiviewer](multiviewer.md) | Layout, sources and output configuration. |
111
- | [Diagnostics](diagnostics.md) | Network status, the mxr console app and capture replay. |
110
+ | [Configuration](docs/configuration.md) | Opening a connection and keeping it in step with the mesh. |
111
+ | [Devices and bays](docs/devices-and-bays.md) | Naming, hiding, EDID and the device registry. |
112
+ | [Routing](docs/routing.md) | Selecting video and audio sources for an output. |
113
+ | [Callbacks](docs/callbacks.md) | Reacting to state changes rather than polling for them. |
114
+ | [Audio](docs/audio.md) | Volume, mute and remote-control passthrough. |
115
+ | [OneIP and V2IP](docs/oneip.md) | Streaming endpoints, stream sources and statistics. |
116
+ | [Multiviewer](docs/multiviewer.md) | Layout, sources and output configuration. |
117
+ | [Diagnostics](docs/diagnostics.md) | Network status, the mxr console app and capture replay. |
112
118
 
113
119
  ## Other languages
114
120
 
@@ -9,6 +9,8 @@ streaming, multiviewer control, and more.
9
9
  If you are looking to integrate Pulse-Eight **neo**, **OneIP**, or **ProAmp8** devices into
10
10
  your own software or home-automation system, this is the library for it.
11
11
 
12
+ **Documentation:** [opdenkamp.github.io/mx-remote](https://opdenkamp.github.io/mx-remote/)
13
+
12
14
  ## What is MX Remote?
13
15
 
14
16
  MX Remote is the network protocol these Pulse-Eight devices use to discover and control one
@@ -65,18 +67,21 @@ asyncio.run(main())
65
67
 
66
68
  ## Documentation
67
69
 
68
- The full API reference lives in [docs/](docs/README.md).
70
+ The guides below are published at
71
+ **[opdenkamp.github.io/mx-remote](https://opdenkamp.github.io/mx-remote/)** alongside an
72
+ API reference generated from the docstrings, and are readable here in
73
+ [docs/](docs/README.md).
69
74
 
70
75
  | Page | Covers |
71
76
  | --- | --- |
72
- | [Configuration](configuration.md) | Opening a connection and keeping it in step with the mesh. |
73
- | [Devices and bays](devices-and-bays.md) | Naming, hiding, EDID and the device registry. |
74
- | [Routing](routing.md) | Selecting video and audio sources for an output. |
75
- | [Callbacks](callbacks.md) | Reacting to state changes rather than polling for them. |
76
- | [Audio](audio.md) | Volume, mute and remote-control passthrough. |
77
- | [OneIP and V2IP](oneip.md) | Streaming endpoints, stream sources and statistics. |
78
- | [Multiviewer](multiviewer.md) | Layout, sources and output configuration. |
79
- | [Diagnostics](diagnostics.md) | Network status, the mxr console app and capture replay. |
77
+ | [Configuration](docs/configuration.md) | Opening a connection and keeping it in step with the mesh. |
78
+ | [Devices and bays](docs/devices-and-bays.md) | Naming, hiding, EDID and the device registry. |
79
+ | [Routing](docs/routing.md) | Selecting video and audio sources for an output. |
80
+ | [Callbacks](docs/callbacks.md) | Reacting to state changes rather than polling for them. |
81
+ | [Audio](docs/audio.md) | Volume, mute and remote-control passthrough. |
82
+ | [OneIP and V2IP](docs/oneip.md) | Streaming endpoints, stream sources and statistics. |
83
+ | [Multiviewer](docs/multiviewer.md) | Layout, sources and output configuration. |
84
+ | [Diagnostics](docs/diagnostics.md) | Network status, the mxr console app and capture replay. |
80
85
 
81
86
  ## Other languages
82
87
 
@@ -1,6 +1,6 @@
1
1
  # Documentation
2
2
 
3
- The API reference for `mx_remote`. Start at the [project README](../README.md) for installation and a quick start.
3
+ The API reference for `mx_remote`. Start at the [project README](https://github.com/opdenkamp/mx-remote#readme) for installation and a quick start.
4
4
 
5
5
  | Page | Covers |
6
6
  | --- | --- |
@@ -0,0 +1,34 @@
1
+ /* Shapes Furo to the house style. The palette itself is set in conf.py, where
2
+ Furo wants it; this file holds what a variable cannot express. */
3
+
4
+ /* The mark is portrait, so a width bound keeps it from filling the sidebar. */
5
+ .sidebar-logo {
6
+ max-width: 4.5rem;
7
+ margin: 0 auto 0.5rem;
8
+ }
9
+
10
+ .sidebar-brand-text {
11
+ font-weight: 600;
12
+ letter-spacing: -0.025em;
13
+ }
14
+
15
+ h1, h2, h3, h4 {
16
+ letter-spacing: -0.025em;
17
+ }
18
+
19
+ /* Furo underlines links only on hover; the guides lean on them heavily enough
20
+ that a reader should see where they are while scanning. */
21
+ article a.reference.internal,
22
+ article a.reference.external {
23
+ text-decoration-color: var(--color-brand-content);
24
+ text-decoration-line: underline;
25
+ text-decoration-thickness: 1px;
26
+ text-underline-offset: 0.15em;
27
+ }
28
+
29
+ /* Signatures are the spine of the API reference: give them the brand rule so
30
+ they read as landmarks rather than as another grey block. */
31
+ dl.py > dt {
32
+ border-left: 3px solid var(--color-brand-content);
33
+ padding-left: 0.6rem;
34
+ }
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="27 7 86 86" width="86" height="86" role="img" aria-label="Op den Kamp IT Solutions">
2
+ <circle cx="70" cy="50" r="30" fill="none" stroke="#0588c4" stroke-width="26"/>
3
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="20 0 120 190" width="120" height="190" role="img" aria-label="Op den Kamp IT Solutions">
2
+ <circle cx="70" cy="50" r="30" fill="none" stroke="#0588c4" stroke-width="26"/>
3
+ <g fill="#5aafc0">
4
+ <rect x="27" y="117" width="16" height="66"/>
5
+ <rect x="57" y="117" width="76" height="16"/>
6
+ <rect x="87" y="117" width="16" height="66"/>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="20 0 120 190" width="120" height="190" role="img" aria-label="Op den Kamp IT Solutions">
2
+ <circle cx="70" cy="50" r="30" fill="none" stroke="#0588c4" stroke-width="26"/>
3
+ <g fill="#117a8b">
4
+ <rect x="27" y="117" width="16" height="66"/>
5
+ <rect x="57" y="117" width="76" height="16"/>
6
+ <rect x="87" y="117" width="16" height="66"/>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,59 @@
1
+ # API reference
2
+
3
+ Generated from the docstrings in the package. The guides cover how these fit
4
+ together; this page is the exhaustive list.
5
+
6
+ Autodoc emits reStructuredText, which the markdown parser does not read, so
7
+ every directive below sits in an `eval-rst` block. Without it the page renders
8
+ the directive source as prose and the build still succeeds.
9
+
10
+ ```{eval-rst}
11
+ .. automodule:: mx_remote
12
+ ```
13
+
14
+ ## Client
15
+
16
+ `Remote` owns the socket, the device registry and the background probe that
17
+ keeps both in step with the mesh.
18
+
19
+ ```{eval-rst}
20
+ .. automodule:: mx_remote.remote.Remote
21
+ :members:
22
+ ```
23
+
24
+ ## Devices, bays and callbacks
25
+
26
+ A client works against these types rather than the classes implementing them:
27
+ they are what the registry hands out and what a callback receives.
28
+
29
+ ```{eval-rst}
30
+ .. automodule:: mx_remote.Interface
31
+ :members:
32
+ ```
33
+
34
+ ## Device identity
35
+
36
+ ```{eval-rst}
37
+ .. automodule:: mx_remote.Uid
38
+ :members:
39
+ ```
40
+
41
+ ## Remote-control keys and actions
42
+
43
+ The key and action codes a bay reports, and the target a key was aimed at.
44
+
45
+ ```{eval-rst}
46
+ .. autoclass:: mx_remote.proto.Constants.RCKey
47
+ :members:
48
+ :undoc-members:
49
+
50
+ .. autoclass:: mx_remote.proto.Constants.RCAction
51
+ :members:
52
+ :undoc-members:
53
+
54
+ .. autoclass:: mx_remote.proto.Constants.RCType
55
+ :members:
56
+ :undoc-members:
57
+
58
+ .. autodata:: mx_remote.proto.Constants.MXR_PROTOCOL_VERSION
59
+ ```
@@ -33,4 +33,4 @@ await bay.tx_action(RCAction.ACTION_VOLUME_DOWN)
33
33
 
34
34
  ---
35
35
 
36
- [Documentation index](README.md) | [Project README](../README.md)
36
+ [Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
@@ -87,4 +87,4 @@ bay.unregister_callback(on_bay_changed)
87
87
 
88
88
  ---
89
89
 
90
- [Documentation index](README.md) | [Project README](../README.md)
90
+ [Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
@@ -0,0 +1,102 @@
1
+ ######################################################
2
+ ## MX Remote Python Interface ##
3
+ ## ##
4
+ ## author: Lars Op den Kamp (lars@opdenkamp-it.nl) ##
5
+ ## copyright (c) 2021-2026 Op den Kamp IT Solutions ##
6
+ ######################################################
7
+ '''Sphinx configuration for the mx_remote documentation site.
8
+
9
+ The guides in this directory are the prose; the API reference is generated from
10
+ the package's own docstrings, so `mx_remote` must be importable when this runs.
11
+ The workflow installs it rather than mocking it: a reference built against
12
+ mocks documents the mocks on the day an import breaks.
13
+ '''
14
+
15
+ import pathlib
16
+ import re
17
+
18
+ _ROOT = pathlib.Path(__file__).resolve().parent.parent
19
+
20
+ project = 'mx_remote'
21
+ author = 'Lars Op den Kamp'
22
+ copyright = '2021-2026 Op den Kamp IT Solutions'
23
+
24
+ # Read from the package the same way pyproject.toml does, so the site cannot
25
+ # report a version the package does not carry.
26
+ release = re.search(r"VERSION = '([^']+)'",
27
+ (_ROOT / 'mx_remote' / 'const.py').read_text(encoding='utf-8')).group(1)
28
+ version = release
29
+
30
+ extensions = [
31
+ 'myst_parser', # the guides are markdown, and stay readable on GitHub
32
+ 'sphinx.ext.autodoc',
33
+ 'sphinx.ext.napoleon',
34
+ 'sphinx.ext.viewcode',
35
+ 'sphinx.ext.intersphinx',
36
+ ]
37
+
38
+ # Anchors for the '#section' links the guides use between each other.
39
+ myst_heading_anchors = 3
40
+
41
+ exclude_patterns = ['_build', 'requirements.txt']
42
+
43
+ autodoc_default_options = {
44
+ 'members': True,
45
+ 'show-inheritance': True,
46
+ 'member-order': 'bysource',
47
+ }
48
+ # A member with no docstring says nothing a reader cannot get from the
49
+ # signature, and there are enough of them to bury the ones that do.
50
+ autodoc_typehints = 'description'
51
+ autodoc_class_signature = 'separated'
52
+
53
+ intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
54
+
55
+ html_theme = 'furo'
56
+ html_title = f'mx_remote {release}'
57
+ html_static_path = ['_static']
58
+ html_css_files = ['brand.css']
59
+ # The ring alone, because the full mark is portrait and would letterbox down
60
+ # to a few unreadable pixels in a tab.
61
+ html_favicon = '_static/favicon.svg'
62
+
63
+ # The palette is the one opdenkamp-it.nl uses, so the site and the docs read as
64
+ # one place: slate text, teal accents, and a near-black teal ground when dark.
65
+ # Furo derives the rest of its colours from these, and applies the light set to
66
+ # both themes, so the dark set only names what differs.
67
+ html_theme_options = {
68
+ 'light_logo': 'logo.svg',
69
+ 'dark_logo': 'logo-dark.svg',
70
+ 'light_css_variables': {
71
+ 'font-stack': '"Inter Variable", Inter, system-ui, -apple-system, sans-serif',
72
+ 'font-stack--monospace': '"JetBrains Mono Variable", "JetBrains Mono", ui-monospace, monospace',
73
+ 'color-brand-primary': '#0f4c5c',
74
+ 'color-brand-content': '#117a8b',
75
+ 'color-brand-visited': '#0f4c5c',
76
+ 'color-foreground-primary': '#0f172a',
77
+ 'color-foreground-secondary': '#475569',
78
+ 'color-foreground-muted': '#64748b',
79
+ 'color-foreground-border': '#e2e8f0',
80
+ 'color-background-primary': '#ffffff',
81
+ 'color-background-secondary': '#f8fafc',
82
+ 'color-background-border': '#e2e8f0',
83
+ 'color-inline-code-background': '#f1f5f9',
84
+ 'color-api-name': '#0f4c5c',
85
+ 'color-api-pre-name': '#117a8b',
86
+ },
87
+ 'dark_css_variables': {
88
+ 'color-brand-primary': '#5aafc0',
89
+ 'color-brand-content': '#5aafc0',
90
+ 'color-brand-visited': '#8fc9d5',
91
+ 'color-foreground-primary': '#e2e8f0',
92
+ 'color-foreground-secondary': '#94a3b8',
93
+ 'color-foreground-muted': '#7d8ea0',
94
+ 'color-foreground-border': '#1c414d',
95
+ 'color-background-primary': '#0a1f26',
96
+ 'color-background-secondary': '#0d2b34',
97
+ 'color-background-border': '#1c414d',
98
+ 'color-inline-code-background': '#12333d',
99
+ 'color-api-name': '#5aafc0',
100
+ 'color-api-pre-name': '#8fc9d5',
101
+ },
102
+ }
@@ -130,4 +130,4 @@ await mx.update_config(
130
130
 
131
131
  ---
132
132
 
133
- [Documentation index](README.md) | [Project README](../README.md)
133
+ [Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
@@ -44,4 +44,4 @@ await bay.select_edid_profile(EdidProfile.LOWEST_COMMON_DENOMINATOR)
44
44
 
45
45
  ---
46
46
 
47
- [Documentation index](README.md) | [Project README](../README.md)
47
+ [Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
@@ -86,4 +86,4 @@ help(mx_remote.MxrCallbacks)
86
86
 
87
87
  ---
88
88
 
89
- [Documentation index](README.md) | [Project README](../README.md)
89
+ [Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
@@ -0,0 +1,34 @@
1
+ # mx_remote
2
+
3
+ Python 3 library for discovering and controlling [Pulse-Eight](https://www.pulse-eight.com/)
4
+ AV distribution hardware — neo matrices, OneIP HDMI-over-IP units, multiviewers and
5
+ ProAmp8 amplifiers — over the MX Remote protocol they share.
6
+
7
+ ```sh
8
+ pip install mx_remote
9
+ ```
10
+
11
+ ```python
12
+ import mx_remote
13
+
14
+ mx = mx_remote.Remote()
15
+ await mx.start_async()
16
+ ```
17
+
18
+ The guides below cover the library task by task. The [API reference](api.md) is
19
+ generated from the package's docstrings and lists everything.
20
+
21
+ ```{toctree}
22
+ :maxdepth: 2
23
+
24
+ README
25
+ configuration
26
+ devices-and-bays
27
+ routing
28
+ callbacks
29
+ audio
30
+ oneip
31
+ multiviewer
32
+ diagnostics
33
+ api
34
+ ```
@@ -49,4 +49,4 @@ await mv.auto_route()
49
49
 
50
50
  ---
51
51
 
52
- [Documentation index](README.md) | [Project README](../README.md)
52
+ [Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
@@ -40,4 +40,4 @@ if device.v2ip_firmware_versions:
40
40
 
41
41
  ---
42
42
 
43
- [Documentation index](README.md) | [Project README](../README.md)
43
+ [Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
@@ -0,0 +1,3 @@
1
+ sphinx>=7.2
2
+ furo>=2024.1.29
3
+ myst-parser>=2.0
@@ -21,4 +21,4 @@ await output.select_audio_source(source=0)
21
21
 
22
22
  ---
23
23
 
24
- [Documentation index](README.md) | [Project README](../README.md)
24
+ [Documentation index](README.md) | [Project README](https://github.com/opdenkamp/mx-remote#readme)
@@ -1394,7 +1394,7 @@ def v2ip_stream_valid(stream:'V2IPStreamSource|None') -> bool:
1394
1394
  """
1395
1395
  True when a stream source carries an address a frame actually meant to send.
1396
1396
 
1397
- Mirrors mxr_v2ip_stream_valid(): a multicast ip and a non-zero port. A
1397
+ Mirrors the firmware's own test: a multicast ip and a non-zero port. A
1398
1398
  controller write that offers no addresses leaves the block zeroed, which
1399
1399
  fails both tests.
1400
1400
  """
@@ -1409,7 +1409,7 @@ def v2ip_av_source_valid(video:'V2IPStreamSource|None', anc:'V2IPStreamSource|No
1409
1409
  """
1410
1410
  True when an av source block carries addresses a frame meant to send.
1411
1411
 
1412
- Mirrors mxr_v2ip_av_source_valid(): video and anc must both be valid, audio
1412
+ Mirrors the firmware's own test: video and anc must both be valid, audio
1413
1413
  is optional and is carried along with them.
1414
1414
  """
1415
1415
  return v2ip_stream_valid(video) and v2ip_stream_valid(anc)
@@ -0,0 +1,22 @@
1
+ ######################################################
2
+ ## MX Remote Python Interface ##
3
+ ## ##
4
+ ## author: Lars Op den Kamp (lars@opdenkamp-it.nl) ##
5
+ ## copyright (c) 2021-2026 Op den Kamp IT Solutions ##
6
+ ######################################################
7
+
8
+ """
9
+ Names that live in different modules across the Python versions this package
10
+ supports. Import them from here so the version test is written once.
11
+ """
12
+
13
+ import sys
14
+
15
+ if sys.version_info >= (3, 12):
16
+ from typing import override
17
+ else:
18
+ # typing.override arrived in 3.12; typing_extensions carries the same
19
+ # decorator further back, and is a dependency only below that version.
20
+ from typing_extensions import override
21
+
22
+ __all__ = ['override']
@@ -14,7 +14,7 @@ Default communication modes:
14
14
  """
15
15
  import os
16
16
 
17
- VERSION = '5.4.0'
17
+ VERSION = '5.5.1'
18
18
  __version__ = VERSION
19
19
 
20
20
  MX_BCAST_UDP_PORT = 8811
@@ -113,7 +113,7 @@ MXR_DEVICE_NAME_LEN = 16
113
113
 
114
114
  The field carries no terminator of its own when the value fills it, so read
115
115
  exactly this many bytes and only then cut at a NUL - scanning on runs into the
116
- neighbouring struct member (firmware V2IP#349)."""
116
+ neighbouring struct member."""
117
117
 
118
118
  MXR_FW_VERSION_LEN = 128
119
119
  """Width of the fixed-size firmware version name field (mxr_fw_version.name)."""
@@ -341,8 +341,8 @@ class BayStatusMask(IntFlag):
341
341
  return "none"
342
342
 
343
343
 
344
- # Bay status bit-field accessors (not flag bits). Mirrors MXR_BAY_STATUS_RC_TYPE
345
- # and MXR_BAY_STATUS_HDCP_STATUS in mx_remote_proto.h.
344
+ # Bay status bit-field accessors (not flag bits), mirroring the firmware's
345
+ # MXR_BAY_STATUS_RC_TYPE and MXR_BAY_STATUS_HDCP_STATUS.
346
346
  BAY_STATUS_RC_TYPE_SHIFT = 16
347
347
  BAY_STATUS_RC_TYPE_MASK = (0xF << BAY_STATUS_RC_TYPE_SHIFT)
348
348
  BAY_STATUS_HDCP_STATUS_SHIFT = 22
@@ -369,7 +369,7 @@ _MXR_SIG_BPP_VALUES: dict[int, int] = {
369
369
  def mxr_sig_bpp_get(bpp: int) -> int:
370
370
  '''Map an mxr_signal_type bpp *index* to the bit depth it stands for.
371
371
 
372
- Mirrors mxr_sig_bpp_get() in mxr_bay.c. The field is an index, not a value:
372
+ The field is an index, not a value:
373
373
  1=8, 2=10, 3=12, 4=16, 0=unknown and 5 the unset sentinel - reading it as a
374
374
  bit depth is a common trap. Returns 0 for both unknown and unset.'''
375
375
  return _MXR_SIG_BPP_VALUES.get(bpp, MXR_SIG_BPP_UNKNOWN)
@@ -441,8 +441,7 @@ class MxrSignalType:
441
441
  class VideoWallOperation(IntEnum):
442
442
  '''What a V2IP_VIDEOWALL frame asks the addressed sink to do with its window.
443
443
 
444
- Mirrors enum vw_mesh_op in the v2ipwall module
445
- (github.com/opdenkamp/mod-v2ip-videowall, src/v2ip_videowall.h).'''
444
+ Mirrors vw_mesh_op in the v2ipwall module, which owns this opcode.'''
446
445
  PREVIEW = 0
447
446
  '''Show the window without storing it, so it dies on reboot or revert.'''
448
447
 
@@ -17,7 +17,7 @@ class FrameBayConfig(FrameBase):
17
17
  '''Bay configuration for the bays a remote device advertises.
18
18
 
19
19
  A device pages its bays across several of these frames: firmware sizes each
20
- page against mxr_max_payload_len() and shrinks it further on OOM, so the
20
+ page against its own maximum payload length and shrinks it further on OOM, so the
21
21
  record count varies from frame to frame and no single frame holds the whole
22
22
  list. Each page is a valid stand-alone frame with the same per-record
23
23
  format - the receiver merges records into its cache and must never treat
@@ -7,7 +7,7 @@
7
7
  '''Protocol frame for SYS_FACTORY_RESET (opcode 0x3A).
8
8
 
9
9
  A mesh controller or management app broadcasts this to factory-reset peers.
10
- Payload variants accepted by the firmware (see _mxr_check_mng_payload):
10
+ Payload variants the firmware accepts:
11
11
  empty controller-only target (just the sender)
12
12
  1 byte = 0xFF broadcast to all peers (controller/management only)
13
13
  16 bytes single target uid
@@ -15,7 +15,7 @@ class FrameLinks(FrameBase):
15
15
  '''Configured links for the device that sent this frame.
16
16
 
17
17
  Paged the same way as the bay config: a device with many bays splits its
18
- links across several frames sized against mxr_max_payload_len(), so the
18
+ links across several frames sized against its own maximum payload, so the
19
19
  record count varies per frame and the receiver merges records into its
20
20
  cache rather than replacing it.'''
21
21
  @cached_property
@@ -6,7 +6,7 @@
6
6
  ######################################################
7
7
  '''Protocol frame for device system status notifications.'''
8
8
 
9
- from typing import override
9
+ from ..compat import override
10
10
  from .FrameBase import FrameBase
11
11
 
12
12
  class FrameSystemStatus(FrameBase):
@@ -1,5 +1,5 @@
1
+ from ..compat import override as override
1
2
  from .FrameBase import FrameBase as FrameBase
2
- from typing import override
3
3
 
4
4
  class FrameSystemStatus(FrameBase):
5
5
  @override
@@ -10,7 +10,7 @@ from enum import IntEnum
10
10
  from functools import cached_property
11
11
  import logging
12
12
  import struct
13
- from typing import override
13
+ from ..compat import override
14
14
 
15
15
  from .FrameHeader import FrameHeader
16
16
  from .FrameBase import FrameBase
@@ -646,7 +646,7 @@ def _pack_audio_entry_route_in(ep_id: int, supported: int, active: int) -> bytes
646
646
  def pack_audio_features(dev: AudioDeviceData) -> bytes:
647
647
  '''Pack the mxr_v2ip_audio_dev FEATURES body.
648
648
 
649
- Entry order matches aud_dev_serialise in mod-v2ip-audio/src/device.c:
649
+ Entry order matches the audio module's own serialiser:
650
650
  optional device control address first, then for each endpoint the
651
651
  ENDPOINT entry, optional ADDRESS, optional PARENT, optional ROUTE_IN.
652
652
  '''
@@ -1,10 +1,10 @@
1
1
  from ..Interface import AudioChangeSource as AudioChangeSource, AudioEndpoint as AudioEndpoint, AudioEndpoints as AudioEndpoints, AudioFeatures as AudioFeatures, AudioLink as AudioLink, AudioLinks as AudioLinks, DeviceRegistry as DeviceRegistry, MxrDeviceUid as MxrDeviceUid, V2IPStreamSource as V2IPStreamSource
2
+ from ..compat import override as override
2
3
  from .FrameBase import FrameBase as FrameBase
3
4
  from .FrameHeader import FrameHeader as FrameHeader
4
5
  from _typeshed import Incomplete
5
6
  from enum import IntEnum
6
7
  from functools import cached_property
7
- from typing import override
8
8
 
9
9
  V2IP_AUDIO_EP_ID_NONE: int
10
10
 
@@ -7,7 +7,7 @@
7
7
  '''Protocol frame for V2IP bay-to-device UID mapping.'''
8
8
 
9
9
  from functools import cached_property
10
- from typing import override
10
+ from ..compat import override
11
11
  from ..Interface import MxrDeviceUid
12
12
  from .FrameBase import FrameBase
13
13