mx-remote 5.4.0__tar.gz → 5.5.0__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 (219) hide show
  1. {mx_remote-5.4.0 → mx_remote-5.5.0}/AGENTS.md +15 -0
  2. {mx_remote-5.4.0 → mx_remote-5.5.0}/PKG-INFO +16 -11
  3. {mx_remote-5.4.0 → mx_remote-5.5.0}/README.md +14 -9
  4. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/README.md +1 -1
  5. mx_remote-5.5.0/docs/_static/brand.css +34 -0
  6. mx_remote-5.5.0/docs/_static/favicon.svg +3 -0
  7. mx_remote-5.5.0/docs/_static/logo-dark.svg +8 -0
  8. mx_remote-5.5.0/docs/_static/logo.svg +8 -0
  9. mx_remote-5.5.0/docs/api.md +59 -0
  10. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/audio.md +1 -1
  11. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/callbacks.md +1 -1
  12. mx_remote-5.5.0/docs/conf.py +102 -0
  13. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/configuration.md +1 -1
  14. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/devices-and-bays.md +1 -1
  15. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/diagnostics.md +1 -1
  16. mx_remote-5.5.0/docs/index.md +34 -0
  17. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/multiviewer.md +1 -1
  18. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/oneip.md +1 -1
  19. mx_remote-5.5.0/docs/requirements.txt +3 -0
  20. {mx_remote-5.4.0 → mx_remote-5.5.0}/docs/routing.md +1 -1
  21. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/Interface.py +2 -2
  22. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/const.py +1 -1
  23. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Constants.py +5 -6
  24. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBayConfig.py +1 -1
  25. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameFactoryReset.py +1 -1
  26. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameLinks.py +1 -1
  27. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPAudio.py +1 -1
  28. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPVideoWall.py +2 -3
  29. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/V2IPStats.py +3 -3
  30. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/ConnectionAsync.py +2 -2
  31. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/Remote.py +2 -2
  32. {mx_remote-5.4.0 → mx_remote-5.5.0}/pyproject.toml +1 -1
  33. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/capture.py +2 -3
  34. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/hello.py +2 -2
  35. {mx_remote-5.4.0 → mx_remote-5.5.0}/.gitignore +0 -0
  36. {mx_remote-5.4.0 → mx_remote-5.5.0}/CLAUDE.md +0 -0
  37. {mx_remote-5.4.0 → mx_remote-5.5.0}/LICENSE +0 -0
  38. {mx_remote-5.4.0 → mx_remote-5.5.0}/hatch_build.py +0 -0
  39. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/Interface.pyi +0 -0
  40. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/Uid.py +0 -0
  41. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/Uid.pyi +0 -0
  42. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/__init__.py +0 -0
  43. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/__init__.pyi +0 -0
  44. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/const.pyi +0 -0
  45. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/main.py +0 -0
  46. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/main.pyi +0 -0
  47. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/BayConfig.py +0 -0
  48. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/BayConfig.pyi +0 -0
  49. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Constants.pyi +0 -0
  50. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Data.py +0 -0
  51. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Data.pyi +0 -0
  52. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Factory.py +0 -0
  53. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Factory.pyi +0 -0
  54. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameAmpDolbySettings.py +0 -0
  55. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameAmpDolbySettings.pyi +0 -0
  56. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameAmpZoneSettings.py +0 -0
  57. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameAmpZoneSettings.pyi +0 -0
  58. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameAudioClip.py +0 -0
  59. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameAudioClip.pyi +0 -0
  60. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameAudioSetRoute.py +0 -0
  61. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameAudioSetRoute.pyi +0 -0
  62. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBase.py +0 -0
  63. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBase.pyi +0 -0
  64. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBayConfig.pyi +0 -0
  65. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBayConfigSecondary.py +0 -0
  66. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBayConfigSecondary.pyi +0 -0
  67. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBayHide.py +0 -0
  68. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBayHide.pyi +0 -0
  69. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBayStatus.py +0 -0
  70. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameBayStatus.pyi +0 -0
  71. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameConnectStatus.py +0 -0
  72. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameConnectStatus.pyi +0 -0
  73. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameDebug.py +0 -0
  74. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameDebug.pyi +0 -0
  75. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameDiscover.py +0 -0
  76. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameDiscover.pyi +0 -0
  77. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameEDID.py +0 -0
  78. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameEDID.pyi +0 -0
  79. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameEDIDProfile.py +0 -0
  80. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameEDIDProfile.pyi +0 -0
  81. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameFactoryReset.pyi +0 -0
  82. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameFilterStatus.py +0 -0
  83. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameFilterStatus.pyi +0 -0
  84. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameFirmwareVersion.py +0 -0
  85. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameFirmwareVersion.pyi +0 -0
  86. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameHeader.py +0 -0
  87. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameHeader.pyi +0 -0
  88. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameHello.py +0 -0
  89. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameHello.pyi +0 -0
  90. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameLinks.pyi +0 -0
  91. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameMeshOperation.py +0 -0
  92. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameMeshOperation.pyi +0 -0
  93. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameMirrorStatus.py +0 -0
  94. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameMirrorStatus.pyi +0 -0
  95. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameMonitoringPulse.py +0 -0
  96. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameMonitoringPulse.pyi +0 -0
  97. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameNetworkStatus.py +0 -0
  98. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameNetworkStatus.pyi +0 -0
  99. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FramePowerChange.py +0 -0
  100. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FramePowerChange.pyi +0 -0
  101. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRCAction.py +0 -0
  102. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRCAction.pyi +0 -0
  103. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRCIr.py +0 -0
  104. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRCIr.pyi +0 -0
  105. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRCKey.py +0 -0
  106. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRCKey.pyi +0 -0
  107. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRCSettings.py +0 -0
  108. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRCSettings.pyi +0 -0
  109. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameReboot.py +0 -0
  110. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameReboot.pyi +0 -0
  111. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRoutingChange.py +0 -0
  112. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameRoutingChange.pyi +0 -0
  113. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSetInstaller.py +0 -0
  114. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSetInstaller.pyi +0 -0
  115. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSetName.py +0 -0
  116. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSetName.pyi +0 -0
  117. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSetRoute.py +0 -0
  118. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSetRoute.pyi +0 -0
  119. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSetupStatus.py +0 -0
  120. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSetupStatus.pyi +0 -0
  121. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSignalStatus.py +0 -0
  122. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSignalStatus.pyi +0 -0
  123. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSignalStatusNew.py +0 -0
  124. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSignalStatusNew.pyi +0 -0
  125. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSysTemperature.py +0 -0
  126. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSysTemperature.pyi +0 -0
  127. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSystemStatus.py +0 -0
  128. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameSystemStatus.pyi +0 -0
  129. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameTXRCAction.py +0 -0
  130. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameTXRCAction.pyi +0 -0
  131. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameTXRCKey.py +0 -0
  132. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameTXRCKey.pyi +0 -0
  133. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameTopology.py +0 -0
  134. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameTopology.pyi +0 -0
  135. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameTxIR.py +0 -0
  136. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameTxIR.pyi +0 -0
  137. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameUpgradeFPGA.py +0 -0
  138. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameUpgradeFPGA.pyi +0 -0
  139. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPAudio.pyi +0 -0
  140. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPBayMapping.py +0 -0
  141. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPBayMapping.pyi +0 -0
  142. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPDetectBays.py +0 -0
  143. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPDetectBays.pyi +0 -0
  144. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPDeviceConfiguration.py +0 -0
  145. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPDeviceConfiguration.pyi +0 -0
  146. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPLink.py +0 -0
  147. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPLink.pyi +0 -0
  148. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPManualSourceSwitch.py +0 -0
  149. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPManualSourceSwitch.pyi +0 -0
  150. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPMultiviewer.py +0 -0
  151. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPMultiviewer.pyi +0 -0
  152. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPPowerSave.py +0 -0
  153. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPPowerSave.pyi +0 -0
  154. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPSetMaster.py +0 -0
  155. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPSetMaster.pyi +0 -0
  156. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPSourceSwitch.py +0 -0
  157. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPSourceSwitch.pyi +0 -0
  158. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPSources.py +0 -0
  159. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPSources.pyi +0 -0
  160. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPStats.py +0 -0
  161. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPStats.pyi +0 -0
  162. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPTiling.py +0 -0
  163. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPTiling.pyi +0 -0
  164. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameV2IPVideoWall.pyi +0 -0
  165. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameVolume.py +0 -0
  166. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameVolume.pyi +0 -0
  167. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameVolumeDown.py +0 -0
  168. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameVolumeDown.pyi +0 -0
  169. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameVolumeSet.py +0 -0
  170. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameVolumeSet.pyi +0 -0
  171. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameVolumeUp.py +0 -0
  172. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/FrameVolumeUp.pyi +0 -0
  173. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/LinkConfig.py +0 -0
  174. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/LinkConfig.pyi +0 -0
  175. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Multiviewer.py +0 -0
  176. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Multiviewer.pyi +0 -0
  177. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Svd.py +0 -0
  178. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/Svd.pyi +0 -0
  179. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/V2IPConfig.py +0 -0
  180. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/V2IPConfig.pyi +0 -0
  181. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/V2IPStats.pyi +0 -0
  182. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/__init__.py +0 -0
  183. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/__init__.pyi +0 -0
  184. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/proto/svd.csv +0 -0
  185. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/py.typed +0 -0
  186. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/Bay.py +0 -0
  187. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/Bay.pyi +0 -0
  188. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/ConnectionAsync.pyi +0 -0
  189. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/Device.py +0 -0
  190. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/Device.pyi +0 -0
  191. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/Link.py +0 -0
  192. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/Link.pyi +0 -0
  193. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/Remote.pyi +0 -0
  194. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/State.py +0 -0
  195. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/State.pyi +0 -0
  196. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/V2IP.py +0 -0
  197. {mx_remote-5.4.0 → mx_remote-5.5.0}/mx_remote/remote/V2IP.pyi +0 -0
  198. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/audio_ir.py +0 -0
  199. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/e2e.py +0 -0
  200. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/entry.py +0 -0
  201. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/handlers.py +0 -0
  202. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/handlers_cover.py +0 -0
  203. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/idempotent.py +0 -0
  204. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/merge.py +0 -0
  205. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/newops.py +0 -0
  206. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/offsets.py +0 -0
  207. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/proto_stamp.py +0 -0
  208. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/protogate.py +0 -0
  209. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/rcsettings.py +0 -0
  210. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/roundtrip.py +0 -0
  211. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/run.py +0 -0
  212. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/smoke.py +0 -0
  213. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/sources.py +0 -0
  214. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/stats.py +0 -0
  215. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/structs.py +0 -0
  216. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/txresult.py +0 -0
  217. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/unknowns.py +0 -0
  218. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/vdetails.py +0 -0
  219. {mx_remote-5.4.0 → mx_remote-5.5.0}/tests/wirefix.py +0 -0
@@ -83,6 +83,21 @@ reads it via regex, so bump it there only. Release commits follow the convention
83
83
  force-includes them in the wheel (they are gitignored). `mx_remote` ships as typed
84
84
  (`py.typed`). If stubgen produces nothing the build fails by design.
85
85
 
86
+ ### Documentation
87
+ `docs/` is both the GitHub-readable guide set and the Sphinx source for
88
+ [the published site](https://opdenkamp.github.io/mx-remote/), which
89
+ `.github/workflows/docs.yml` rebuilds on every push to master. Build it the way
90
+ the workflow does:
91
+
92
+ ```sh
93
+ pip install . -r docs/requirements.txt
94
+ sphinx-build -b html -W --keep-going docs site
95
+ ```
96
+
97
+ Autodoc emits reStructuredText, so a directive belongs in an ```` ```{eval-rst} ````
98
+ block. Outside one it renders as its own source and the build still reports
99
+ success — the workflow greps the output for that.
100
+
86
101
  ## Architecture
87
102
 
88
103
  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.0
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>
@@ -41,6 +41,8 @@ streaming, multiviewer control, and more.
41
41
  If you are looking to integrate Pulse-Eight **neo**, **OneIP**, or **ProAmp8** devices into
42
42
  your own software or home-automation system, this is the library for it.
43
43
 
44
+ **Documentation:** [opdenkamp.github.io/mx-remote](https://opdenkamp.github.io/mx-remote/)
45
+
44
46
  ## What is MX Remote?
45
47
 
46
48
  MX Remote is the network protocol these Pulse-Eight devices use to discover and control one
@@ -97,18 +99,21 @@ asyncio.run(main())
97
99
 
98
100
  ## Documentation
99
101
 
100
- The full API reference lives in [docs/](docs/README.md).
102
+ The guides below are published at
103
+ **[opdenkamp.github.io/mx-remote](https://opdenkamp.github.io/mx-remote/)** alongside an
104
+ API reference generated from the docstrings, and are readable here in
105
+ [docs/](docs/README.md).
101
106
 
102
107
  | Page | Covers |
103
108
  | --- | --- |
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. |
109
+ | [Configuration](docs/configuration.md) | Opening a connection and keeping it in step with the mesh. |
110
+ | [Devices and bays](docs/devices-and-bays.md) | Naming, hiding, EDID and the device registry. |
111
+ | [Routing](docs/routing.md) | Selecting video and audio sources for an output. |
112
+ | [Callbacks](docs/callbacks.md) | Reacting to state changes rather than polling for them. |
113
+ | [Audio](docs/audio.md) | Volume, mute and remote-control passthrough. |
114
+ | [OneIP and V2IP](docs/oneip.md) | Streaming endpoints, stream sources and statistics. |
115
+ | [Multiviewer](docs/multiviewer.md) | Layout, sources and output configuration. |
116
+ | [Diagnostics](docs/diagnostics.md) | Network status, the mxr console app and capture replay. |
112
117
 
113
118
  ## Other languages
114
119
 
@@ -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)
@@ -14,7 +14,7 @@ Default communication modes:
14
14
  """
15
15
  import os
16
16
 
17
- VERSION = '5.4.0'
17
+ VERSION = '5.5.0'
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
@@ -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
  '''
@@ -23,9 +23,8 @@ from ..Uid import MxrDeviceUid
23
23
  # 28..29 u8 op vw_mesh_op
24
24
  # 29..32 padding, zeroed
25
25
  #
26
- # Defined by the v2ipwall module (github.com/opdenkamp/mod-v2ip-videowall,
27
- # src/v2ip_videowall.h), which MatrixOS does not carry - it reserves only the
28
- # opcode number. The receiver accepts 32 bytes or more and ignores the rest.
26
+ # Defined by the v2ipwall module, which MatrixOS does not carry - it reserves
27
+ # only the opcode number. The receiver accepts 32 bytes or more and ignores the rest.
29
28
  #
30
29
  # A wrong offset here is quiet at `op` and loud everywhere else. A shifted
31
30
  # window is visibly in the wrong place; a misread op is still a valid op, so a
@@ -154,9 +154,9 @@ class V2IPRxStats:
154
154
  # ONE byte at 40, with three of padding after it: it is a plain enum and
155
155
  # Cortex-M builds with -fshort-enums.
156
156
  #
157
- # This sender does zero that padding - mxr_bsp_v2ip_tx_v2ip_stats()
158
- # writes through pointers into an already-zeroed pbuf rather than
159
- # copying a stack struct, so unlike 0x45 there is no stack content here.
157
+ # This sender does zero that padding: it writes through pointers into
158
+ # an already-zeroed buffer rather than copying a stack struct, so unlike
159
+ # 0x45 there is no stack content here.
160
160
  # Keep the read one byte anyway: that is a property of one sender's
161
161
  # implementation, not of the protocol, and the 0x45 sender demonstrates
162
162
  # what the other approach puts on the wire. A width that is only correct
@@ -22,8 +22,8 @@ _LOGGER = logging.getLogger(__name__)
22
22
  #
23
23
  # Delivery is currently to a group: a device has two endpoints, the multicast
24
24
  # group and the interface broadcast address, and nothing resolves a per-device
25
- # address. Do not build on that. mxr_transmit() threads a device through its
26
- # endpoint selection so directed sends can be added later.
25
+ # address. Do not build on that: the firmware threads a device through its own
26
+ # endpoint selection, so directed sends can be added later.
27
27
  #
28
28
  # Two things keep this correct if they are:
29
29
  #
@@ -409,8 +409,8 @@ class Remote(DeviceRegistry, ConnectionCallbacks):
409
409
  if (sent > 0):
410
410
  # Only a hello that went out buys the next interval. A send that wrote
411
411
  # nothing leaves _hello_due where it was, so the next probe tick tries
412
- # again, which is what firmware does - it resets hello_timeout only in
413
- # the success branch of mxr_transmit. Arming here on failure instead
412
+ # again, which is what firmware does - it re-arms its own timer only
413
+ # after a send succeeds. Arming here on failure instead
414
414
  # would silence a client for a full interval every time a write failed,
415
415
  # and on an interface that never writes, permanently.
416
416
  self._arm_hello()
@@ -51,7 +51,7 @@ pattern = "VERSION = '(?P<version>[^']+)'"
51
51
 
52
52
  [project.urls]
53
53
  Homepage = "https://github.com/opdenkamp/mx-remote/"
54
- Documentation = "https://github.com/opdenkamp/mx-remote/"
54
+ Documentation = "https://opdenkamp.github.io/mx-remote/"
55
55
  Repository = "https://github.com/opdenkamp/mx-remote.git"
56
56
  "Bug Tracker" = "https://github.com/opdenkamp/mx-remote/issues"
57
57
 
@@ -1,6 +1,5 @@
1
- # Real 0x45 frames off a live mesh, captured by the MatrixOS session. Every unit
2
- # on that mesh was CEC-configured, so _v2ip_rc_fill_proto_status() writes
3
- # status_name[0] = 0 and returns - the string must be empty in all three. That is
1
+ # Real 0x45 frames captured off a live mesh. Every unit on that mesh was
2
+ # CEC-configured, so the sender leaves status_name empty and returns - the string must be empty in all three. That is
4
3
  # what makes them a usable fixture: the expected value is known from firmware
5
4
  # behaviour rather than from our own decoder.
6
5
  import os, sys, time, logging
@@ -53,8 +53,8 @@ print('silent network, 3.5s: %d hellos' % len(hellos))
53
53
  assert len(hellos) >= 2, 'a client must keep announcing with no traffic arriving'
54
54
 
55
55
  # ---- arriving datagrams must not announce, asserted by behaviour rather than by
56
- # name. Checking that "tx_hello" is absent from on_datagram_received passes the
57
- # moment the method is renamed, while the receipt-driven path is back in place.
56
+ # name: checking that "tx_hello" is absent from on_datagram_received passes as
57
+ # soon as the announce is called under another name.
58
58
  def announces_on_receipt():
59
59
  mx = mx_remote.Remote(open_connection=False)
60
60
  mx._uid = bytes(range(0x20, 0x30))
File without changes