@bharper/atv-js 0.2.6 → 0.3.4
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.
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +89 -9
- package/dist/index.js.map +1 -1
- package/dist/mdns.d.ts.map +1 -1
- package/dist/mdns.js +96 -11
- package/dist/mdns.js.map +1 -1
- package/examples/print-device-json.js +22 -0
- package/package.json +2 -3
- package/pyatv/.codecov.yml +38 -0
- package/pyatv/.github/FUNDING.yml +3 -0
- package/pyatv/.github/ISSUE_TEMPLATE/bug_report.yml +80 -0
- package/pyatv/.github/ISSUE_TEMPLATE/config.yml +1 -0
- package/pyatv/.github/ISSUE_TEMPLATE/feature_request.yml +22 -0
- package/pyatv/.github/ISSUE_TEMPLATE/implementation-proposal.yml +29 -0
- package/pyatv/.github/ISSUE_TEMPLATE/investigation.yml +16 -0
- package/pyatv/.github/ISSUE_TEMPLATE/minor-change.yml +10 -0
- package/pyatv/.github/ISSUE_TEMPLATE/question-or-idea.yml +11 -0
- package/pyatv/.github/dependabot.yml +26 -0
- package/pyatv/.github/workflows/codeql-analysis.yml +71 -0
- package/pyatv/.github/workflows/release.yml +160 -0
- package/pyatv/.github/workflows/tests.yml +104 -0
- package/pyatv/.gitpod.yml +23 -0
- package/pyatv/CHANGES.md +3708 -0
- package/pyatv/CODE_OF_CONDUCT.md +76 -0
- package/pyatv/CONTRIBUTING.md +72 -0
- package/pyatv/CONTRIBUTORS.md +3 -0
- package/pyatv/Dockerfile +15 -0
- package/pyatv/LICENSE.md +9 -0
- package/pyatv/MANIFEST.in +14 -0
- package/pyatv/README.md +111 -0
- package/pyatv/base_versions.txt +13 -0
- package/pyatv/chickn.yaml +75 -0
- package/pyatv/docs/404.html +24 -0
- package/pyatv/docs/CNAME +1 -0
- package/pyatv/docs/Gemfile +31 -0
- package/pyatv/docs/_config.yml +121 -0
- package/pyatv/docs/_includes/api +10 -0
- package/pyatv/docs/_includes/atvremote_scan +32 -0
- package/pyatv/docs/_includes/code +6 -0
- package/pyatv/docs/_includes/issue +14 -0
- package/pyatv/docs/_includes/pypi +5 -0
- package/pyatv/docs/_layouts/template.html +109 -0
- package/pyatv/docs/api/pyatv.conf.html +312 -0
- package/pyatv/docs/api/pyatv.const.html +974 -0
- package/pyatv/docs/api/pyatv.convert.html +106 -0
- package/pyatv/docs/api/pyatv.exceptions.html +489 -0
- package/pyatv/docs/api/pyatv.helpers.html +102 -0
- package/pyatv/docs/api/pyatv.html +120 -0
- package/pyatv/docs/api/pyatv.interface.html +2369 -0
- package/pyatv/docs/api/pyatv.settings.html +484 -0
- package/pyatv/docs/api/pyatv.storage.file_storage.html +102 -0
- package/pyatv/docs/api/pyatv.storage.html +186 -0
- package/pyatv/docs/api/pyatv.storage.memory_storage.html +83 -0
- package/pyatv/docs/assets/css/custom.css +19 -0
- package/pyatv/docs/assets/css/hljs.css +1 -0
- package/pyatv/docs/assets/css/normalize.css +349 -0
- package/pyatv/docs/assets/css/pdoc.css +287 -0
- package/pyatv/docs/assets/css/sanitize.css +566 -0
- package/pyatv/docs/assets/css/style.scss +9 -0
- package/pyatv/docs/assets/img/logo.svg +63 -0
- package/pyatv/docs/assets/js/highlight.9.12.0.min.js +3 -0
- package/pyatv/docs/assets/js/mermaid.8.9.2.min.js +32 -0
- package/pyatv/docs/assets/js/mermaid.min.js.map +1 -0
- package/pyatv/docs/development/apps.md +81 -0
- package/pyatv/docs/development/audio.md +42 -0
- package/pyatv/docs/development/control.md +56 -0
- package/pyatv/docs/development/development.md +15 -0
- package/pyatv/docs/development/device_info.md +36 -0
- package/pyatv/docs/development/examples.md +44 -0
- package/pyatv/docs/development/features.md +70 -0
- package/pyatv/docs/development/keyboard.md +51 -0
- package/pyatv/docs/development/listeners.md +144 -0
- package/pyatv/docs/development/logging.md +55 -0
- package/pyatv/docs/development/metadata.md +115 -0
- package/pyatv/docs/development/power_management.md +53 -0
- package/pyatv/docs/development/scan_pair_and_connect.md +331 -0
- package/pyatv/docs/development/services.md +9 -0
- package/pyatv/docs/development/storage.md +259 -0
- package/pyatv/docs/development/stream.md +241 -0
- package/pyatv/docs/development/testing.md +9 -0
- package/pyatv/docs/documentation/atvlog.md +64 -0
- package/pyatv/docs/documentation/atvproxy.md +244 -0
- package/pyatv/docs/documentation/atvremote.md +639 -0
- package/pyatv/docs/documentation/atvscript.md +275 -0
- package/pyatv/docs/documentation/concepts.md +168 -0
- package/pyatv/docs/documentation/documentation.md +130 -0
- package/pyatv/docs/documentation/getting_started.md +248 -0
- package/pyatv/docs/documentation/protocols.md +1959 -0
- package/pyatv/docs/documentation/supported_features.md +246 -0
- package/pyatv/docs/documentation/tutorial.md +1062 -0
- package/pyatv/docs/documentation/workspace.code-workspace +7 -0
- package/pyatv/docs/favicon.ico +0 -0
- package/pyatv/docs/index.md +109 -0
- package/pyatv/docs/internals/design.md +354 -0
- package/pyatv/docs/internals/documentation.md +84 -0
- package/pyatv/docs/internals/interfaces.md +95 -0
- package/pyatv/docs/internals/internals.md +157 -0
- package/pyatv/docs/internals/submit_pr.md +56 -0
- package/pyatv/docs/internals/testing.md +176 -0
- package/pyatv/docs/internals/tools.md +574 -0
- package/pyatv/docs/pdoc_templates/config.mako +46 -0
- package/pyatv/docs/pdoc_templates/html.mako +454 -0
- package/pyatv/docs/support/acknowledgements.md +87 -0
- package/pyatv/docs/support/faq.md +214 -0
- package/pyatv/docs/support/migration.md +138 -0
- package/pyatv/docs/support/scanning_issues.md +110 -0
- package/pyatv/docs/support/support.md +18 -0
- package/pyatv/docs/support/troubleshooting.md +83 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/AudioFadeMessage.proto +13 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/AudioFadeMessage_pb2.pyi +37 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/AudioFadeResponseMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/AudioFadeResponseMessage_pb2.pyi +32 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/AudioFormatSettingsMessage.proto +5 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/AudioFormatSettingsMessage_pb2.pyi +27 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ClientUpdatesConfigMessage.proto +16 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ClientUpdatesConfigMessage_pb2.pyi +44 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/CommandInfo.proto +117 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/CommandInfo_pb2.pyi +325 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/CommandOptions.proto +36 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/CommandOptions_pb2.pyi +115 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/Common.proto +79 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/Common_pb2.pyi +228 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ConfigureConnectionMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ConfigureConnectionMessage_pb2.pyi +32 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ContentItem.proto +27 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ContentItemMetadata.proto +213 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ContentItemMetadata_pb2.pyi +630 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ContentItem_pb2.pyi +94 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/CryptoPairingMessage.proto +15 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/CryptoPairingMessage_pb2.pyi +46 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/DeviceInfoMessage.proto +69 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/DeviceInfoMessage_pb2.pyi +226 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GenericMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GenericMessage_pb2.pyi +35 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GetKeyboardSessionMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GetKeyboardSessionMessage_pb2.pyi +26 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GetRemoteTextInputSessionMessage.proto +10 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GetRemoteTextInputSessionMessage_pb2.pyi +26 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GetVolumeMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GetVolumeMessage_pb2.pyi +32 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GetVolumeResultMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/GetVolumeResultMessage_pb2.pyi +32 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/KeyboardMessage.proto +88 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/KeyboardMessage_pb2.pyi +261 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/LanguageOption.proto +9 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/LanguageOption_pb2.pyi +42 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ModifyOutputContextRequestMessage.proto +23 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ModifyOutputContextRequestMessage_pb2.pyi +86 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/NotificationMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/NotificationMessage_pb2.pyi +38 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/NowPlayingClient.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/NowPlayingClient_pb2.pyi +49 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/NowPlayingInfo.proto +24 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/NowPlayingInfo_pb2.pyi +79 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/NowPlayingPlayer.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/NowPlayingPlayer_pb2.pyi +45 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/Origin.proto +17 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/OriginClientPropertiesMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/OriginClientPropertiesMessage_pb2.pyi +32 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/Origin_pb2.pyi +63 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlaybackQueue.proto +15 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlaybackQueueCapabilities.proto +7 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlaybackQueueCapabilities_pb2.pyi +33 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlaybackQueueContext.proto +5 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlaybackQueueContext_pb2.pyi +27 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlaybackQueueRequestMessage.proto +29 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlaybackQueueRequestMessage_pb2.pyi +87 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlaybackQueue_pb2.pyi +53 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlayerClientPropertiesMessage.proto +13 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlayerClientPropertiesMessage_pb2.pyi +37 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlayerPath.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/PlayerPath_pb2.pyi +39 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ProtocolMessage.proto +171 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/ProtocolMessage_pb2.pyi +377 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterForGameControllerEventsMessage.proto +18 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterForGameControllerEventsMessage_pb2.pyi +54 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterHIDDeviceMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterHIDDeviceMessage_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterHIDDeviceResultMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterHIDDeviceResultMessage_pb2.pyi +35 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterVoiceInputDeviceMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterVoiceInputDeviceMessage_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterVoiceInputDeviceResponseMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RegisterVoiceInputDeviceResponseMessage_pb2.pyi +35 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemoteTextInputMessage.proto +13 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemoteTextInputMessage_pb2.pyi +38 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemoveClientMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemoveClientMessage_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemoveEndpointsMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemoveEndpointsMessage_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemoveOutputDevicesMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemoveOutputDevicesMessage_pb2.pyi +38 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemovePlayerMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/RemovePlayerMessage_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendButtonEventMessage.proto +13 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendButtonEventMessage_pb2.pyi +38 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendCommandMessage.proto +16 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendCommandMessage_pb2.pyi +43 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendCommandResultMessage.proto +100 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendCommandResultMessage_pb2.pyi +286 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendHIDEventMessage.proto +41 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendHIDEventMessage_pb2.pyi +63 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendPackedVirtualTouchEventMessage.proto +24 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendPackedVirtualTouchEventMessage_pb2.pyi +64 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendVoiceInputMessage.proto +38 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SendVoiceInputMessage_pb2.pyi +134 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetArtworkMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetArtworkMessage_pb2.pyi +32 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetConnectionStateMessage.proto +18 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetConnectionStateMessage_pb2.pyi +54 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetDefaultSupportedCommandsMessage.proto +28 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetDefaultSupportedCommandsMessage_pb2.pyi +74 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetDiscoveryModeMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetDiscoveryModeMessage_pb2.pyi +35 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetHiliteModeMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetHiliteModeMessage_pb2.pyi +32 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetNowPlayingClientMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetNowPlayingClientMessage_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetNowPlayingPlayerMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetNowPlayingPlayerMessage_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetRecordingStateMessage.proto +17 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetRecordingStateMessage_pb2.pyi +54 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetStateMessage.proto +27 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetStateMessage_pb2.pyi +72 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetVolumeMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SetVolumeMessage_pb2.pyi +35 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SupportedCommands.proto +7 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/SupportedCommands_pb2.pyi +30 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TextInputMessage.proto +23 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TextInputMessage_pb2.pyi +76 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TransactionKey.proto +6 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TransactionKey_pb2.pyi +30 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TransactionMessage.proto +15 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TransactionMessage_pb2.pyi +42 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TransactionPacket.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TransactionPacket_pb2.pyi +41 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TransactionPackets.proto +7 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/TransactionPackets_pb2.pyi +30 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateClientMessage.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateClientMessage_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateContentItemArtworkMessage.proto +14 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateContentItemArtworkMessage_pb2.pyi +41 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateContentItemMessage.proto +14 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateContentItemMessage_pb2.pyi +41 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateEndPointsMessage.proto +25 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateEndPointsMessage_pb2.pyi +74 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateOutputDeviceMessage.proto +88 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdateOutputDeviceMessage_pb2.pyi +277 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdatePlayerPath.proto +12 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/UpdatePlayerPath_pb2.pyi +34 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VirtualTouchDeviceDescriptorMessage.proto +8 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VirtualTouchDeviceDescriptorMessage_pb2.pyi +36 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VoiceInputDeviceDescriptorMessage.proto +8 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VoiceInputDeviceDescriptorMessage_pb2.pyi +35 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VolumeControlAvailabilityMessage.proto +23 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VolumeControlAvailabilityMessage_pb2.pyi +71 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VolumeControlCapabilitiesDidChangeMessage.proto +14 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VolumeControlCapabilitiesDidChangeMessage_pb2.pyi +40 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VolumeDidChangeMessage.proto +13 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/VolumeDidChangeMessage_pb2.pyi +38 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/WakeDeviceMessage.proto +11 -0
- package/pyatv/pyatv/protocols/mrp/protobuf/WakeDeviceMessage_pb2.pyi +26 -0
- package/pyatv/pyatv/py.typed +0 -0
- package/pyatv/pylintrc +49 -0
- package/pyatv/pyproject.toml +74 -0
- package/pyatv/requirements/requirements.txt +14 -0
- package/pyatv/requirements/requirements_docs.txt +2 -0
- package/pyatv/requirements/requirements_test.txt +20 -0
- package/pyatv/scripts/build_docs.sh +17 -0
- package/pyatv/scripts/setup_dev_env.sh +83 -0
- package/pyatv/setup.cfg +14 -0
- package/pyatv/tests/data/README +23 -0
- package/pyatv/tests/data/audio_10_frames.wav +0 -0
- package/pyatv/tests/data/audio_1_packet_metadata.wav +0 -0
- package/pyatv/tests/data/audio_3_packets.wav +0 -0
- package/pyatv/tests/data/only_metadata.wav +0 -0
- package/pyatv/tests/data/only_title.wav +0 -0
- package/pyatv/tests/data/static_3sec.ogg +0 -0
- package/pyatv/tests/data/testfile.txt +1 -0
- package/pyatv/tests/support/pyatv.code-workspace +14 -0
- package/src/index.ts +122 -8
- package/src/mdns.ts +64 -11
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Apps
|
|
4
|
+
permalink: /development/apps/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
# Apps
|
|
8
|
+
|
|
9
|
+
It is possible to launch and list installed apps via the Apps interface.
|
|
10
|
+
To use this interface, the Companion protocol must be available.
|
|
11
|
+
|
|
12
|
+
## Using the Apps API
|
|
13
|
+
|
|
14
|
+
After connecting to a device, you get the apps interface via {% include api i="interface.AppleTV.apps" %}:
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
atv = await pyatv.connect(config, ...)
|
|
18
|
+
apps = atv.apps
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
To retrieve a list of installed apps, use {% include api i="interface.Apps.app_list" %}
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
app_list = await apps.app_list()
|
|
25
|
+
|
|
26
|
+
for app in app_list:
|
|
27
|
+
print(f"Name: {app.name}, Bundle Identifier: {app.identifier}")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
To launch an app, use its bundle identifier when calling {% include api i="interface.Apps.launch_app" %}
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
await apps.launch_app("com.netflix.Netflix")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
To launch an app with a URL, pass the URL when calling {% include api i="interface.Apps.launch_app" %}
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
await apps.launch_app("https://tv.apple.com/show/marvels-spidey-and-his-amazing-friends/umc.cmc.3ambs8tqwzphbn0u8e9g76x7m?profile=kids&action=play")
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### App deep links
|
|
43
|
+
|
|
44
|
+
tvOS, allows deep linking into apps. So the {% include api i="interface.Apps.launch_app" %} API is very powerful for
|
|
45
|
+
navigating content on the Apple TV.
|
|
46
|
+
|
|
47
|
+
Here are some known working examples:
|
|
48
|
+
* https://tv.apple.com/show/severance/umc.cmc.1srk2goyh2q2zdxcx605w8vtx
|
|
49
|
+
* https://www.disneyplus.com/series/the-beatles-get-back/7DcWEeWVqrkE
|
|
50
|
+
* https://play.hbomax.com/page/urn:hbo:page:GXkRjxwjR68PDwwEAABKJ:type:series
|
|
51
|
+
* https://www.netflix.com/title/80234304
|
|
52
|
+
|
|
53
|
+
The simplest way to find useful deep links is to use the "Share" feature in iOS or macOS versions of the App. Share
|
|
54
|
+
sheets will often have a "Copy" or "Copy link" feature. For apps that have a web accessible version, links copied from
|
|
55
|
+
the browser usually work too (this is how iOS handles linking into apps from web links).
|
|
56
|
+
|
|
57
|
+
Sometimes a link copied this way will not work, but can be made to work with a slight modification, e.g. removing a
|
|
58
|
+
country code from the URL.
|
|
59
|
+
|
|
60
|
+
If this approach fails, you can inspect the app to discover insights about supported URLs. The recommended way to
|
|
61
|
+
support [app links](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content)
|
|
62
|
+
is by defining
|
|
63
|
+
[associated domains](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content).
|
|
64
|
+
|
|
65
|
+
To discover domains associated with an app, list the app entitlements, then search for `associated-domains` within
|
|
66
|
+
the output. You can do this using the `codesign` tool on macOS.
|
|
67
|
+
```bash
|
|
68
|
+
$ codesign -d --entitlements - "/path/to/Interesting.app/"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Once potential domains are identified you can check the content of the file hosted at
|
|
72
|
+
`https://<domain>/.well-known/apple-app-site-association`. This is a file that is required to be hosted to support
|
|
73
|
+
associated domains, and contains patterns matching URLs that the app claims to support. Check out some examples from
|
|
74
|
+
[Disney+](https://www.disneyplus.com/.well-known/apple-app-site-association) and
|
|
75
|
+
[Netflix](https://www.netflix.com/.well-known/apple-app-site-association).
|
|
76
|
+
|
|
77
|
+
Some apps also define a
|
|
78
|
+
[custom URL scheme](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app), which
|
|
79
|
+
is an alternative API for supporting app links. These can be inspected by looking at
|
|
80
|
+
`/path/to/Interesting.app/Info.plist` or
|
|
81
|
+
`/path/to/Interesting.app/Contents/Info.plist` and searching for CFBundleURLSchemes.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Audio
|
|
4
|
+
permalink: /development/audio/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
# Audio
|
|
8
|
+
|
|
9
|
+
Protocols supporting volume controls can be controlled via the audio interface.
|
|
10
|
+
|
|
11
|
+
## Using the Audio API
|
|
12
|
+
|
|
13
|
+
After connecting to a device, you get the apps interface via {% include api i="interface.AppleTV.audio" %}:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
atv = await pyatv.connect(config, ...)
|
|
17
|
+
audio = atv.audio
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
To get current volume level, use {% include api i="interface.Audio.volume" %}:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
print("Volume:", audio.volume)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
To change current volume, use {% include api i="interface.Audio.set_volume" %}:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
await audio.set_volume(20.0)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The volume level is normalized in the interval 0.0-100.0, where 0.0 means
|
|
33
|
+
the audio is muted.
|
|
34
|
+
|
|
35
|
+
You can also step volume up or down using step level provided from the device (if available):
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
await audio.volume_up()
|
|
39
|
+
await audio.volume_down()
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The audio API supports push updates via a listener, as described [here](../listeners#audio-updates).
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Control
|
|
4
|
+
permalink: /development/control/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
# Control
|
|
8
|
+
|
|
9
|
+
Controlling a device is done with the remote control interface,
|
|
10
|
+
{% include api i="interface.RemoteControl" %}. It allows you navigate the menus and
|
|
11
|
+
change playback (play, pause, etc.).
|
|
12
|
+
|
|
13
|
+
## Using the Remote Control API
|
|
14
|
+
|
|
15
|
+
After connecting to a device, you get the remote control via {% include api i="interface.AppleTV.remote_control" %}:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
atv = await pyatv.connect(config, ...)
|
|
19
|
+
rc = atv.remote_control
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
You can then control via the available functions:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
await rc.up()
|
|
26
|
+
await rc.select()
|
|
27
|
+
await rc.volume_up()
|
|
28
|
+
await rc.set_position(100)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
All available actions can be found in {% include api i="interface.RemoteControl" %}.
|
|
32
|
+
|
|
33
|
+
## Input Actions
|
|
34
|
+
|
|
35
|
+
Currently three types of input actions are supported:
|
|
36
|
+
|
|
37
|
+
* Single tap ("click")
|
|
38
|
+
* Double tap ("double click")
|
|
39
|
+
* Hold
|
|
40
|
+
|
|
41
|
+
These actions are supported by the following buttons:
|
|
42
|
+
|
|
43
|
+
* Arrow keys (up, down, left, right)
|
|
44
|
+
* Select
|
|
45
|
+
* Menu
|
|
46
|
+
* Home
|
|
47
|
+
|
|
48
|
+
By default, {% include api i="const.InputAction.SingleTap" %} are used. Pass another `action`
|
|
49
|
+
to use another input action:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
await rc.menu(action=InputAction.Hold)
|
|
53
|
+
await rc.home(action=InputAction.DoubleTap)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
All input actions are specified in {% include api i="const.InputAction" %}.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Development
|
|
4
|
+
permalink: /development/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
# :construction_worker: Development
|
|
8
|
+
|
|
9
|
+
These sections cover the basics on how you develop with pyatv.
|
|
10
|
+
So if you are a developer and want to create some software that
|
|
11
|
+
controls an Apple TV, you are in the right place.
|
|
12
|
+
|
|
13
|
+
If you instead want develop pyatv itself, there are details for
|
|
14
|
+
that over at the GitHub wiki. Click
|
|
15
|
+
[here](https://github.com/postlund/pyatv/wiki) to go there.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Device Information
|
|
4
|
+
permalink: /development/device_info/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
# Device Information
|
|
8
|
+
|
|
9
|
+
pyatv can extract various information about a device, e.g. which
|
|
10
|
+
operating system (and version) it runs or its hardware model (3, 4K, etc.).
|
|
11
|
+
This information is exposed via the interface {% include api i="interface.DeviceInfo" %}.
|
|
12
|
+
|
|
13
|
+
## Using the Device Information API
|
|
14
|
+
|
|
15
|
+
After connecting to a device, you get device info via {% include api i="interface.AppleTV.device_info" %}:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
atv = await pyatv.connect(config, ...)
|
|
19
|
+
devinfo = atv.device_info
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
You can then access the actual information via properties:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
print(devinfo.operating_system)
|
|
26
|
+
print(devinfo.version)
|
|
27
|
+
print(devinfo.mac)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Just printing `devinfo` will produce a summary of the device information
|
|
31
|
+
(MAC-address is not included here):
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
>>> print(devinfo)
|
|
35
|
+
4K tvOS 13.3.1 build 17K795
|
|
36
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Examples
|
|
4
|
+
permalink: /development/examples/
|
|
5
|
+
link_group: development
|
|
6
|
+
|
|
7
|
+
files:
|
|
8
|
+
- name: auto_connect.py
|
|
9
|
+
description: Demonstrates the simple `auto_connect` helper.
|
|
10
|
+
- name: connect_with_credentials.py
|
|
11
|
+
description: Restores credentials for a device before connecting.
|
|
12
|
+
- name: manual_connect.py
|
|
13
|
+
description: Manual creation of a configuration used to connect to a device.
|
|
14
|
+
- name: pairing.py
|
|
15
|
+
description: Generic example demonstrating the pairing API.
|
|
16
|
+
- name: play_url.py
|
|
17
|
+
description: Play a video from URL using AirPlay.
|
|
18
|
+
- name: scan_and_connect.py
|
|
19
|
+
description: Scans for devices, picks the first one and connects to it.
|
|
20
|
+
- name: storage.py
|
|
21
|
+
description: Connect to a device using storage API.
|
|
22
|
+
- name: stream.py
|
|
23
|
+
description: Stream audio file to an AirPlay/RAOP receiver.
|
|
24
|
+
- name: tutorial.py
|
|
25
|
+
description: Complete source code of [tutorial](../../documentation/tutorial).
|
|
26
|
+
---
|
|
27
|
+
# Examples
|
|
28
|
+
|
|
29
|
+
There are a few example bundled with pyatv in the `examples` subdirectory:
|
|
30
|
+
|
|
31
|
+
| Filename | Description |
|
|
32
|
+
| -------- | ----------- |
|
|
33
|
+
{% for file in page.files -%}
|
|
34
|
+
| [{{ file['name'] | replace: "__", "\_\_" }}]({{ "https://github.com/postlund/pyatv/blob/master/examples/" | append:file['name'] }}) | {{ file['description'] }} |
|
|
35
|
+
{% endfor- %}
|
|
36
|
+
|
|
37
|
+
These scripts that are bundled with pyatv can be used for inspiration as well:
|
|
38
|
+
|
|
39
|
+
* [atvremote](https://github.com/postlund/pyatv/blob/master/pyatv/scripts/atvremote.py)
|
|
40
|
+
* [atvscript](https://github.com/postlund/pyatv/blob/master/pyatv/scripts/atvscript.py)
|
|
41
|
+
|
|
42
|
+
More examples can be added on request, please write an
|
|
43
|
+
[issue](https://github.com/postlund/pyatv/issues/new?assignees=&labels=question&template=question-or-idea.md&title=)
|
|
44
|
+
if you want something more specific.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Features
|
|
4
|
+
permalink: /development/features/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
# Features
|
|
8
|
+
|
|
9
|
+
It is possible to obtain information about available features of a device, e.g. if it supports playback actions or power management, using {% include api i="interface.Features" %}. Supported features are listed in {% include api i="const.FeatureName" %}.
|
|
10
|
+
|
|
11
|
+
## Feature State
|
|
12
|
+
|
|
13
|
+
A feature can at any given time be considered to be in one of the following states:
|
|
14
|
+
|
|
15
|
+
| State | Meaning |
|
|
16
|
+
| ----- | ------- |
|
|
17
|
+
| Unknown | The feature is supported by the device but it is not possible to determine if it is available or not, i.e. if it can be used *now*. All devices for instance supports `Pause`, but it is only possible to pause if something is playing.
|
|
18
|
+
| Unsupported | The feature is not supported by the device at all, e.g. Siri is unsupported on Apple TV 3 *or* none of the configured protocols support this feature.
|
|
19
|
+
| Unavailable | The feature is supported but currently not possible to use, e.g. skip to next track is only possible if a song is playing.
|
|
20
|
+
| Available | The feature is supported and available now, e.g. `Pause` is possible because something is playing.
|
|
21
|
+
|
|
22
|
+
Because of technical reasons, the state of some features are not possible to determine, so pyatv will make an educated guess. If something seems strange, please write an [issue](https://github.com/postlund/pyatv/issues/new?assignees=&labels=bug&template=bug_report.md&title=) about it. Make sure you include full debug logs, otherwise it will be hard to troubleshoot.
|
|
23
|
+
|
|
24
|
+
## Using the Features API
|
|
25
|
+
|
|
26
|
+
After connecting to a device, you get the interface via {% include api i="interface.AppleTV.features" %}:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
atv = await pyatv.connect(config, ...)
|
|
30
|
+
ft = atv.features
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To obtain current state of a feature, e.g. {% include api i="const.FeatureName.Play" %}, use {% include api i="interface.Features.get_feature" %}:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from pyatv.const import FeatureName, FeatureState
|
|
37
|
+
|
|
38
|
+
info = ft.get_feature(FeatureName.Play)
|
|
39
|
+
if info.state == FeatureState.Available:
|
|
40
|
+
await atv.remote_control.play()
|
|
41
|
+
else:
|
|
42
|
+
print("Play is not possible right now")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The state of all features can be obtained via {% include api i="interface.Features.all_features" %}. By default, this method will exclude unsupported features. Pass `include_unsupported=True` when calling to include state of all features:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
all_features = ft.all_features(include_unsupported=unsupported)
|
|
49
|
+
for name, feature in all_features.items():
|
|
50
|
+
print(f"{name} = {feature.state}")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
There's a helper method, {% include api i="interface.Features.in_state" %}, that checks if one or
|
|
54
|
+
more features are in one or several states:
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
# Check if Play is available
|
|
58
|
+
if ft.in_state(FeatureState.Available, FeatureName.Play):
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
# Check if Play is either available or unsupported
|
|
62
|
+
if ft.in_state([FeatureState.Available, FeatureState.Unsupported],
|
|
63
|
+
FeatureName.Play):
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
# Check if Play *and* Pause are supported
|
|
67
|
+
if not ft.in_state(FeatureName.Unsupported, FeatureName.Play, FeatureName.Pause):
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Keyboard
|
|
4
|
+
permalink: /development/keyboard/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
# Keyboard
|
|
8
|
+
|
|
9
|
+
It is possible to interact with the Apple TV virtual keyboard via the Keyboard interface.
|
|
10
|
+
To use this interface, the Companion protocol must be available.
|
|
11
|
+
|
|
12
|
+
## Using the Keyboard API
|
|
13
|
+
|
|
14
|
+
After connecting to a device, you get the keyboard interface via {% include api i="interface.AppleTV.keyboard" %}:
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
atv = await pyatv.connect(config, ...)
|
|
18
|
+
keyboard = atv.keyboard
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
To check whether the virtual keyboard is focused and active, use {% include api i="interface.Keyboard.text_focus_state" %}:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
print("Keyboard focus state:", keyboard.text_focus_state)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
To fetch the current virtual keyboard text content, use {% include api i="interface.Keyboard.text_get" %}:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
print("Keyboard text:", await keyboard.text_get())
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To set (replace) the virtual keyboard text, use {% include api i="interface.Keyboard.text_set" %}:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
await keyboard.text_set("text to set")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
To append to the virtual keyboard text, use {% include api i="interface.Keyboard.text_append" %}:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
await keyboard.text_append("text to append")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Finally, to clear the virtual keyboard text, use {% include api i="interface.Keyboard.text_clear" %}:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
await keyboard.text_clear()
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The keyboard API supports push updates via a listener, as described [here](../listeners#keyboard-updates).
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Listeners
|
|
4
|
+
permalink: /development/listeners/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
Table of Contents
|
|
8
|
+
{:.no_toc}
|
|
9
|
+
* TOC
|
|
10
|
+
{:toc}
|
|
11
|
+
|
|
12
|
+
# Listeners
|
|
13
|
+
|
|
14
|
+
In some cases it's not appropriate to continuously poll the device for information.
|
|
15
|
+
What is currently playing should be updated instantly for instance. This is supported
|
|
16
|
+
via callbacks using a `listener`.
|
|
17
|
+
|
|
18
|
+
## Push Updates
|
|
19
|
+
|
|
20
|
+
The push update API is based on a regular callback interface. When playstatus
|
|
21
|
+
information is available, a method called ``playstatus_update`` is called.
|
|
22
|
+
Similarly, ``playstatus_error`` is called if an error occur. See the
|
|
23
|
+
following example:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
class MyPushListener(interface.PushListener):
|
|
27
|
+
|
|
28
|
+
def playstatus_update(self, updater, playstatus):
|
|
29
|
+
# Currently playing in playstatus
|
|
30
|
+
|
|
31
|
+
def playstatus_error(self, updater, exception):
|
|
32
|
+
# Error in exception
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
listener = MyPushListener()
|
|
36
|
+
atv.push_updater.listener = listener
|
|
37
|
+
atv.push_updater.start()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Assuming the connection to the device is still active, push updates will
|
|
41
|
+
continue to be delivered after an error has happened. The parameter
|
|
42
|
+
`initial_delay` to `start` specifies the delay that should be used before
|
|
43
|
+
"trying to deliver updates again", but it might also be ignored if it is
|
|
44
|
+
deemed not necessary. The reason for its existence is purly to provide a
|
|
45
|
+
way to not hammer the device in case of errors.
|
|
46
|
+
|
|
47
|
+
## Device Updates
|
|
48
|
+
|
|
49
|
+
It is possible to get callbacks whenever a device loses its connection. Two methods
|
|
50
|
+
are used: one for expected loss, e.g. manually disconnecting and one for unexpected
|
|
51
|
+
loss, e.g. a crash or network problem. The API is defined by the
|
|
52
|
+
{% include api i="interface.DeviceListener" %} interface and works similarly to how push updates works.
|
|
53
|
+
|
|
54
|
+
Here is a simple example:
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
class MyDeviceListener(interface.DeviceListener):
|
|
58
|
+
|
|
59
|
+
def connection_lost(self, exception):
|
|
60
|
+
print("Lost connection:", str(exception))
|
|
61
|
+
|
|
62
|
+
def connection_closed(self):
|
|
63
|
+
print("Connection closed!")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
listener = MyDeviceListener()
|
|
67
|
+
atv.listener = listener
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
A small note here about this API. For `MRP` this works fine as that protocol
|
|
71
|
+
is connection oriented. It's another case for `DMAP`, since that protocol is
|
|
72
|
+
request based. For now, this interface is implemented by the push updates
|
|
73
|
+
API (to be clear: for `DMAP`). So when the push updates API fails to establish
|
|
74
|
+
a connection, the callbacks in this interface will be called.
|
|
75
|
+
|
|
76
|
+
## Power State Updates
|
|
77
|
+
|
|
78
|
+
It is possible to get callbacks whenever a device power state is changed,
|
|
79
|
+
e.g. the device turned on or turned off. The API is defined by the
|
|
80
|
+
{% include api i="interface.PowerListener" %} interface and works similarly to how push updates works.
|
|
81
|
+
|
|
82
|
+
Here is a simple example:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
class MyPowerListener(interface.PowerListener):
|
|
86
|
+
|
|
87
|
+
def powerstate_update(self, old_state, new_state):
|
|
88
|
+
print('Power state changed from {0:s} to {1:s}'.format(old_state, new_state))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
listener = MyPowerListener()
|
|
92
|
+
atv.power.listener = listener
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
A small note here about this API. Power state updates are working for `MRP` devices
|
|
96
|
+
only.
|
|
97
|
+
|
|
98
|
+
## Audio Updates
|
|
99
|
+
|
|
100
|
+
It is possible to get callbacks whenever the volume level of a device is changed, or the AirPlay output
|
|
101
|
+
devices are altered.
|
|
102
|
+
The API is defined by the
|
|
103
|
+
{% include api i="interface.AudioListener" %} interface and works similarly to how push updates works.
|
|
104
|
+
|
|
105
|
+
Here is a simple example:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
class MyAudioListener(interface.AudioListener):
|
|
109
|
+
|
|
110
|
+
def volume_update(self, old_level, new_level):
|
|
111
|
+
print('Volume level changed from {0:f} to {1:f}'.format(old_level, new_level))
|
|
112
|
+
|
|
113
|
+
def outputdevices_update(self, old_devices, new_devices):
|
|
114
|
+
print('Output devices changed from {0:s} to {1:s}'.format(old_devices, new_devices))
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
listener = MyAudioListener()
|
|
118
|
+
atv.audio.listener = listener
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Live volume level and output device updates are only sent over the `MRP` protocol.
|
|
122
|
+
If an Apple TV is connected to speakers in a way that doesn't support volume levels,
|
|
123
|
+
it will not send these updates.
|
|
124
|
+
|
|
125
|
+
## Keyboard Updates
|
|
126
|
+
|
|
127
|
+
It is possible to get callbacks whenever the virtual keyboard focus state of a device is changed.
|
|
128
|
+
The API is defined by the
|
|
129
|
+
{% include api i="interface.KeyboardListener" %} interface and works similarly to how push updates works.
|
|
130
|
+
|
|
131
|
+
Here is a simple example:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
class MyKeyboardListener(interface.KeyboardListener):
|
|
135
|
+
|
|
136
|
+
def focusstate_update(self, old_state, new_state):
|
|
137
|
+
print('Focus state changed from {0:s} to {1:s}'.format(old_state, new_state))
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
listener = MyKeyboardListener()
|
|
141
|
+
atv.keyboard.listener = listener
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Keyboard focus state updates are only sent over the `Companion` protocol.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: template
|
|
3
|
+
title: Logging
|
|
4
|
+
permalink: /development/logging/
|
|
5
|
+
link_group: development
|
|
6
|
+
---
|
|
7
|
+
# Logging
|
|
8
|
+
|
|
9
|
+
In case you need to troubleshoot something, you can enable additional log points in pyatv.
|
|
10
|
+
This page describes how you do that.
|
|
11
|
+
|
|
12
|
+
# Log points
|
|
13
|
+
|
|
14
|
+
To enable full logging, use this:
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
logging.basicConfig(
|
|
18
|
+
level=logging.DEBUG,
|
|
19
|
+
datefmt="%Y-%m-%d %H:%M:%S",
|
|
20
|
+
format="%(asctime)s %(levelname)s [%(name)s]: %(message)s",
|
|
21
|
+
)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This output format is preferred as it is compatible with [atvlog](../../documentation/atvlog) and
|
|
25
|
+
contains the most useful information.
|
|
26
|
+
|
|
27
|
+
In case you need to troubleshoot MDNS/Zeroconf traffic, use this:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
logging.getLogger(
|
|
31
|
+
"pyatv.support.mdns"
|
|
32
|
+
).level = logging.TRAFFIC # pylint: disable=no-member
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
*NOTE: This section is WIP for now as most interesting log points are internal. In the future,
|
|
36
|
+
a `log` module will be added to simplify enabling log points.*
|
|
37
|
+
|
|
38
|
+
# Bundled scripts
|
|
39
|
+
|
|
40
|
+
You can enable additional debugging information by specifying either `--verbose` or `--debug.`.
|
|
41
|
+
|
|
42
|
+
# Output line cropping
|
|
43
|
+
|
|
44
|
+
By default pyatv will limit some log points in length, mainly due to an excessive amount of
|
|
45
|
+
data might be logged otherwise. This mainly applies to binary data (raw protocol data) and
|
|
46
|
+
protobuf messages. These limits can be overridden by setting the following environment variables:
|
|
47
|
+
|
|
48
|
+
```shell
|
|
49
|
+
$ export PYATV_BINARY_MAX_LINE=1000
|
|
50
|
+
$ export PYATV_PROTOBUF_MAX_LINE=1000
|
|
51
|
+
$ atvremote --debug ... playing
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
In general, you shouldn't have to change these, but under some cicrumstances the complete
|
|
55
|
+
logs might be deseriable.
|