- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
775 lines
27 KiB
Python
775 lines
27 KiB
Python
"""
|
|
Android HDMI API — HdmiControlManager, HdmiDeviceInfo, HdmiPortInfo, etc.
|
|
方法签名完全对齐 Android SDK
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
import uuid
|
|
import threading
|
|
from typing import Any, Dict, List, Optional, Set, Tuple, Callable
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
from ..java.lang import RuntimeException
|
|
|
|
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 常量
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
# DEVICE_* 常量
|
|
DEVICE_TYPE_TV = 0
|
|
DEVICE_TYPE_RECORDER = 1
|
|
DEVICE_TYPE_TUNER = 2
|
|
DEVICE_TYPE_PLAYBACK = 3
|
|
DEVICE_TYPE_AUDIO_SYSTEM = 4
|
|
DEVICE_TYPE_PURE_CEC_SWITCH = 5
|
|
DEVICE_TYPE_VIDEO_PROCESSOR = 6
|
|
DEVICE_TYPE_RESERVED = 7
|
|
DEVICE_TYPE_INACTIVE = 15
|
|
DEVICE_TYPE_CEC_AUTO = 16
|
|
|
|
# CONTROL_* 常量
|
|
CONTROL_STATE_CHANGED_REASON_UNKNOWN = 0
|
|
CONTROL_STATE_CHANGED_REASON_ENABLED = 1
|
|
CONTROL_STATE_CHANGED_REASON_DISABLED = 2
|
|
CONTROL_STATE_CHANGED_REASON_WAKE_UP = 3
|
|
CONTROL_STATE_CHANGED_REASON_SLEEP = 4
|
|
CONTROL_STATE_CHANGED_REASON_STANDBY = 5
|
|
CONTROL_STATE_CHANGED_REASON_HDMI_CEC_ENABLED = 6
|
|
CONTROL_STATE_CHANGED_REASON_HDMI_CEC_DISABLED = 7
|
|
CONTROL_STATE_CHANGED_REASON_HDMI_MHL_ENABLED = 8
|
|
CONTROL_STATE_CHANGED_REASON_HDMI_MHL_DISABLED = 9
|
|
CONTROL_STATE_CHANGED_REASON_INVALID = -1
|
|
|
|
# CEC_* 常量
|
|
CEC_VERSION_1_1 = 0x11
|
|
CEC_VERSION_1_2 = 0x12
|
|
CEC_VERSION_1_3 = 0x13
|
|
CEC_VERSION_1_4 = 0x14
|
|
CEC_VERSION_2_0 = 0x20
|
|
CEC_VERSION_UNKNOWN = 0x00
|
|
|
|
# POWER_STATUS 常量
|
|
POWER_STATUS_ON = 0
|
|
POWER_STATUS_STANDBY = 1
|
|
POWER_STATUS_TO_ON = 2
|
|
POWER_STATUS_TO_STANDBY = 3
|
|
POWER_STATUS_UNKNOWN = -1
|
|
|
|
# PORT_TYPE 常量
|
|
PORT_TYPE_INPUT = 0
|
|
PORT_TYPE_OUTPUT = 1
|
|
PORT_TYPE_BIDIRECTIONAL = 2
|
|
PORT_TYPE_ARC = 3
|
|
PORT_TYPE_EARC = 4
|
|
|
|
# RESULT 常量
|
|
RESULT_SUCCESS = 0
|
|
RESULT_FAILURE = -1
|
|
RESULT_TIMEOUT = -2
|
|
RESULT_NOT_SUPPORTED = -3
|
|
RESULT_BUSY = -4
|
|
RESULT_ALREADY_IN_PROGRESS = -5
|
|
|
|
# CEC_MESSAGE_TYPE 常量
|
|
CEC_MESSAGE_TYPE_FEATURE_ABORT = 0x00
|
|
CEC_MESSAGE_TYPE_ACTIVE_SOURCE = 0x82
|
|
CEC_MESSAGE_TYPE_IMAGE_VIEW_ON = 0x04
|
|
CEC_MESSAGE_TYPE_TEXT_VIEW_ON = 0x0D
|
|
CEC_MESSAGE_TYPE_INACTIVE_SOURCE = 0x9D
|
|
CEC_MESSAGE_TYPE_REQUEST_ACTIVE_SOURCE = 0x85
|
|
CEC_MESSAGE_TYPE_STANDBY = 0x36
|
|
CEC_MESSAGE_TYPE_SET_MENU_LANGUAGE = 0x32
|
|
CEC_MESSAGE_TYPE_USER_CONTROL_PRESSED = 0x44
|
|
CEC_MESSAGE_TYPE_USER_CONTROL_RELEASED = 0x45
|
|
CEC_MESSAGE_TYPE_GIVE_PHYSICAL_ADDRESS = 0x83
|
|
CEC_MESSAGE_TYPE_REPORT_PHYSICAL_ADDRESS = 0x84
|
|
CEC_MESSAGE_TYPE_GIVE_DEVICE_VENDOR_ID = 0x8C
|
|
CEC_MESSAGE_TYPE_DEVICE_VENDOR_ID = 0x87
|
|
CEC_MESSAGE_TYPE_GIVE_OSD_NAME = 0x46
|
|
CEC_MESSAGE_TYPE_SET_OSD_NAME = 0x47
|
|
CEC_MESSAGE_TYPE_GIVE_FEATURES = 0x88
|
|
CEC_MESSAGE_TYPE_REPORT_FEATURES = 0x89
|
|
CEC_MESSAGE_TYPE_VENDOR_COMMAND = 0x89
|
|
CEC_MESSAGE_TYPE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A
|
|
CEC_MESSAGE_TYPE_VENDOR_REMOTE_BUTTON_UP = 0x8B
|
|
|
|
# HDMI_RECORD_SOURCE 常量
|
|
RECORD_SOURCE_OWN_SOURCE = 1
|
|
RECORD_SOURCE_DIGITAL_SERVICE = 2
|
|
RECORD_SOURCE_ANALOGUE_SERVICE = 3
|
|
RECORD_SOURCE_EXTERNAL_PHYSICAL_ADDRESS = 4
|
|
RECORD_SOURCE_EXTERNAL_PLUG = 5
|
|
RECORD_SOURCE_PROGRAM_NUMBER = 6
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiDeviceInfo
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiDeviceInfo(Stub):
|
|
"""HdmiDeviceInfo — HDMI 设备信息"""
|
|
|
|
def __init__(
|
|
self,
|
|
logicalAddress: int = -1,
|
|
physicalAddress: int = 0xFFFF,
|
|
portId: int = -1,
|
|
deviceType: int = DEVICE_TYPE_INACTIVE,
|
|
vendorId: int = 0,
|
|
displayName: str = "",
|
|
):
|
|
super().__init__()
|
|
self._logical_address = logicalAddress
|
|
self._physical_address = physicalAddress
|
|
self._port_id = portId
|
|
self._device_type = deviceType
|
|
self._vendor_id = vendorId
|
|
self._display_name = displayName
|
|
self._device_id = str(uuid.uuid4())
|
|
self._osd_name: Optional[str] = None
|
|
self._cec_version = CEC_VERSION_2_0
|
|
self._power_status = POWER_STATUS_ON
|
|
self._is_cec_device = True
|
|
self._is_mhl_device = False
|
|
self._is_arc_supported = False
|
|
self._is_earc_supported = False
|
|
self._is_audio_return_channel = False
|
|
self._physical_address_str: Optional[str] = None
|
|
self._adopter_id = 0
|
|
self._logical_addresses: List[int] = []
|
|
self._supports_cec = True
|
|
self._vendor_name: Optional[str] = None
|
|
self._menu_language: Optional[str] = None
|
|
self._features: List[int] = []
|
|
self._is_active_source = False
|
|
self._discovery_time = time.time()
|
|
|
|
def getLogicalAddress(self) -> int:
|
|
return self._logical_address
|
|
|
|
def getPhysicalAddress(self) -> int:
|
|
return self._physical_address
|
|
|
|
def getPhysicalAddressString(self) -> str:
|
|
if self._physical_address_str:
|
|
return self._physical_address_str
|
|
pa = self._physical_address
|
|
return f"{(pa >> 12) & 0xF}.{(pa >> 8) & 0xF}.{(pa >> 4) & 0xF}.{pa & 0xF}"
|
|
|
|
def getPortId(self) -> int:
|
|
return self._port_id
|
|
|
|
def getDeviceType(self) -> int:
|
|
return self._device_type
|
|
|
|
def getDeviceTypeString(self) -> str:
|
|
type_names = {
|
|
DEVICE_TYPE_TV: "TV",
|
|
DEVICE_TYPE_RECORDER: "Recorder",
|
|
DEVICE_TYPE_TUNER: "Tuner",
|
|
DEVICE_TYPE_PLAYBACK: "Playback",
|
|
DEVICE_TYPE_AUDIO_SYSTEM: "AudioSystem",
|
|
DEVICE_TYPE_PURE_CEC_SWITCH: "Switch",
|
|
DEVICE_TYPE_VIDEO_PROCESSOR: "VideoProcessor",
|
|
DEVICE_TYPE_INACTIVE: "Inactive",
|
|
}
|
|
return type_names.get(self._device_type, "Unknown")
|
|
|
|
def getVendorId(self) -> int:
|
|
return self._vendor_id
|
|
|
|
def getDisplayName(self) -> str:
|
|
return self._display_name
|
|
|
|
def getOsdName(self) -> Optional[str]:
|
|
return self._osd_name
|
|
|
|
def setOsdName(self, name: str) -> None:
|
|
self._osd_name = name
|
|
|
|
def getCecVersion(self) -> int:
|
|
return self._cec_version
|
|
|
|
def getPowerStatus(self) -> int:
|
|
return self._power_status
|
|
|
|
def setPowerStatus(self, status: int) -> None:
|
|
self._power_status = status
|
|
|
|
def isCecDevice(self) -> bool:
|
|
return self._is_cec_device
|
|
|
|
def isMhlDevice(self) -> bool:
|
|
return self._is_mhl_device
|
|
|
|
def isArcSupported(self) -> bool:
|
|
return self._is_arc_supported
|
|
|
|
def isEarcSupported(self) -> bool:
|
|
return self._is_earc_supported
|
|
|
|
def isActiveSource(self) -> bool:
|
|
return self._is_active_source
|
|
|
|
def setActiveSource(self, active: bool) -> None:
|
|
self._is_active_source = active
|
|
|
|
def toString(self) -> str:
|
|
return (
|
|
f"HdmiDeviceInfo(logical={self._logical_address}, "
|
|
f"physical={self.getPhysicalAddressString()}, "
|
|
f"type={self.getDeviceTypeString()}, "
|
|
f"name={self._display_name})"
|
|
)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiPortInfo
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiPortInfo(Stub):
|
|
"""HdmiPortInfo — HDMI 端口信息"""
|
|
|
|
def __init__(self, id: int = 0, type: int = PORT_TYPE_INPUT, address: int = 0x0000):
|
|
super().__init__()
|
|
self._id = id
|
|
self._type = type
|
|
self._physical_address = address
|
|
self._is_cec_supported = True
|
|
self._is_arc_supported = False
|
|
self._is_earc_supported = False
|
|
self._is_mhl_supported = False
|
|
self._supports_4k = False
|
|
self._supports_hdr = False
|
|
self._supports_dolby_vision = False
|
|
self._max_tmds_character_rate = 6000
|
|
self._num_edid_blocks = 0
|
|
self._edid: Optional[bytes] = None
|
|
self._port_name: Optional[str] = None
|
|
self._connected_device: Optional[HdmiDeviceInfo] = None
|
|
self._is_connected = False
|
|
|
|
def getId(self) -> int:
|
|
return self._id
|
|
|
|
def getType(self) -> int:
|
|
return self._type
|
|
|
|
def getPhysicalAddress(self) -> int:
|
|
return self._physical_address
|
|
|
|
def isCecSupported(self) -> bool:
|
|
return self._is_cec_supported
|
|
|
|
def setCecSupported(self, supported: bool) -> None:
|
|
self._is_cec_supported = supported
|
|
|
|
def isArcSupported(self) -> bool:
|
|
return self._is_arc_supported
|
|
|
|
def setArcSupported(self, supported: bool) -> None:
|
|
self._is_arc_supported = supported
|
|
|
|
def isEarcSupported(self) -> bool:
|
|
return self._is_earc_supported
|
|
|
|
def setEarcSupported(self, supported: bool) -> None:
|
|
self._is_earc_supported = supported
|
|
|
|
def isMhlSupported(self) -> bool:
|
|
return self._is_mhl_supported
|
|
|
|
def supports4k(self) -> bool:
|
|
return self._supports_4k
|
|
|
|
def setSupports4k(self, supported: bool) -> None:
|
|
self._supports_4k = supported
|
|
|
|
def supportsHdr(self) -> bool:
|
|
return self._supports_hdr
|
|
|
|
def supportsDolbyVision(self) -> bool:
|
|
return self._supports_dolby_vision
|
|
|
|
def getMaxTmdsCharacterRate(self) -> int:
|
|
return self._max_tmds_character_rate
|
|
|
|
def getPortName(self) -> Optional[str]:
|
|
return self._port_name
|
|
|
|
def setPortName(self, name: str) -> None:
|
|
self._port_name = name
|
|
|
|
def isConnected(self) -> bool:
|
|
return self._is_connected
|
|
|
|
def setConnected(self, connected: bool, device: Optional[HdmiDeviceInfo] = None) -> None:
|
|
self._is_connected = connected
|
|
self._connected_device = device
|
|
|
|
def getConnectedDevice(self) -> Optional[HdmiDeviceInfo]:
|
|
return self._connected_device
|
|
|
|
def toString(self) -> str:
|
|
return (
|
|
f"HdmiPortInfo(id={self._id}, type={self._type}, "
|
|
f"cec={self._is_cec_supported}, arc={self._is_arc_supported}, "
|
|
f"connected={self._is_connected})"
|
|
)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiCecDeviceInfo
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiCecDeviceInfo(Stub):
|
|
"""HdmiCecDeviceInfo — CEC 设备信息"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._logical_address = -1
|
|
self._physical_address = 0xFFFF
|
|
self._device_type = DEVICE_TYPE_INACTIVE
|
|
self._vendor_id = 0
|
|
self._osd_name: Optional[str] = None
|
|
self._cec_version = CEC_VERSION_2_0
|
|
self._language: Optional[str] = None
|
|
self._features: List[int] = []
|
|
self._is_active = False
|
|
|
|
def getLogicalAddress(self) -> int:
|
|
return self._logical_address
|
|
|
|
def getPhysicalAddress(self) -> int:
|
|
return self._physical_address
|
|
|
|
def getDeviceType(self) -> int:
|
|
return self._device_type
|
|
|
|
def getVendorId(self) -> int:
|
|
return self._vendor_id
|
|
|
|
def getOsdName(self) -> Optional[str]:
|
|
return self._osd_name
|
|
|
|
def getCecVersion(self) -> int:
|
|
return self._cec_version
|
|
|
|
def getLanguage(self) -> Optional[str]:
|
|
return self._language
|
|
|
|
def getFeatures(self) -> List[int]:
|
|
return list(self._features)
|
|
|
|
def isActive(self) -> bool:
|
|
return self._is_active
|
|
|
|
def toString(self) -> str:
|
|
return (
|
|
f"HdmiCecDeviceInfo(logical={self._logical_address}, "
|
|
f"type={self._device_type}, name={self._osd_name})"
|
|
)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiRecordSources
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiRecordSources(Stub):
|
|
"""HdmiRecordSources — HDMI 录制源"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
@staticmethod
|
|
def createDigitalSource(serviceId: int, source: int) -> Any:
|
|
return {"type": "digital", "serviceId": serviceId, "source": source}
|
|
|
|
@staticmethod
|
|
def createAnalogueSource(serviceType: int, frequency: int, system: int) -> Any:
|
|
return {"type": "analogue", "serviceType": serviceType, "frequency": frequency, "system": system}
|
|
|
|
@staticmethod
|
|
def createExternalPlug(plugNumber: int) -> Any:
|
|
return {"type": "external_plug", "plugNumber": plugNumber}
|
|
|
|
@staticmethod
|
|
def createExternalPhysicalAddress(physicalAddress: int) -> Any:
|
|
return {"type": "external_physical", "physicalAddress": physicalAddress}
|
|
|
|
@staticmethod
|
|
def createOwnSource() -> Any:
|
|
return {"type": "own"}
|
|
|
|
@staticmethod
|
|
def createProgramNumber(programNumber: int) -> Any:
|
|
return {"type": "program", "programNumber": programNumber}
|
|
|
|
def toString(self) -> str:
|
|
return "HdmiRecordSources"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiRecordListener
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiRecordListener(Stub):
|
|
"""HdmiRecordListener — HDMI 录制监听器"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
def onRecordStarted(self, source: Any, result: int) -> None:
|
|
pass
|
|
|
|
def onRecordStopped(self, source: Any) -> None:
|
|
pass
|
|
|
|
def onRecordScheduleStarted(self, source: Any, result: int) -> None:
|
|
pass
|
|
|
|
def onRecordScheduleStopped(self, source: Any) -> None:
|
|
pass
|
|
|
|
def onClearTimerStarted(self, source: Any, result: int) -> None:
|
|
pass
|
|
|
|
def onClearTimerStopped(self, source: Any) -> None:
|
|
pass
|
|
|
|
def onOneTouchRecordStarted(self, source: Any) -> None:
|
|
pass
|
|
|
|
def onOneTouchRecordStopped(self, source: Any) -> None:
|
|
pass
|
|
|
|
def onTimerRecordStarted(self, source: Any, result: int) -> None:
|
|
pass
|
|
|
|
def onTimerRecordStopped(self, source: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return "HdmiRecordListener"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiPlaybackClient
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiPlaybackClient(Stub):
|
|
"""HdmiPlaybackClient — HDMI 播放客户端"""
|
|
|
|
def __init__(self, manager: "HdmiControlManager"):
|
|
super().__init__()
|
|
self._manager = manager
|
|
self._callback: Optional[Callable] = None
|
|
|
|
def sendKeyEvent(self, keyCode: int, isPressed: bool) -> None:
|
|
pass
|
|
|
|
def oneTouchPlay(self, callback: Optional[Callable] = None) -> None:
|
|
if callback:
|
|
callback(RESULT_SUCCESS)
|
|
|
|
def queryDeviceType(self, callback: Optional[Callable] = None) -> None:
|
|
if callback:
|
|
callback(DEVICE_TYPE_PLAYBACK)
|
|
|
|
def setCallback(self, callback: Callable) -> None:
|
|
self._callback = callback
|
|
|
|
def clearCallback(self) -> None:
|
|
self._callback = None
|
|
|
|
def toString(self) -> str:
|
|
return "HdmiPlaybackClient"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiSwitchClient
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiSwitchClient(Stub):
|
|
"""HdmiSwitchClient — HDMI 切换客户端"""
|
|
|
|
def __init__(self, manager: "HdmiControlManager"):
|
|
super().__init__()
|
|
self._manager = manager
|
|
self._callback: Optional[Callable] = None
|
|
|
|
def selectDevice(self, logicalAddress: int, callback: Optional[Callable] = None) -> None:
|
|
if callback:
|
|
callback(RESULT_SUCCESS)
|
|
|
|
def setCallback(self, callback: Callable) -> None:
|
|
self._callback = callback
|
|
|
|
def clearCallback(self) -> None:
|
|
self._callback = None
|
|
|
|
def getDeviceList(self) -> List[HdmiDeviceInfo]:
|
|
return self._manager.getDeviceList()
|
|
|
|
def toString(self) -> str:
|
|
return "HdmiSwitchClient"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiTvClient
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiTvClient(Stub):
|
|
"""HdmiTvClient — HDMI TV 客户端"""
|
|
|
|
def __init__(self, manager: "HdmiControlManager"):
|
|
super().__init__()
|
|
self._manager = manager
|
|
self._callback: Optional[Callable] = None
|
|
self._record_listener: Optional[HdmiRecordListener] = None
|
|
|
|
def deviceSelect(self, logicalAddress: int, callback: Optional[Callable] = None) -> None:
|
|
if callback:
|
|
callback(RESULT_SUCCESS)
|
|
|
|
def sendStandby(self, deviceId: int, callback: Optional[Callable] = None) -> None:
|
|
if callback:
|
|
callback(RESULT_SUCCESS)
|
|
|
|
def setSystemAudioMode(self, enabled: bool, callback: Optional[Callable] = None) -> None:
|
|
if callback:
|
|
callback(RESULT_SUCCESS)
|
|
|
|
def setArcEnabled(self, enabled: bool) -> None:
|
|
pass
|
|
|
|
def setEarcEnabled(self, enabled: bool) -> None:
|
|
pass
|
|
|
|
def startOneTouchRecord(self, address: int, source: Any) -> None:
|
|
if self._record_listener:
|
|
self._record_listener.onOneTouchRecordStarted(source)
|
|
|
|
def stopOneTouchRecord(self, address: int) -> None:
|
|
if self._record_listener:
|
|
self._record_listener.onOneTouchRecordStopped(address)
|
|
|
|
def startTimerRecording(self, address: int, source: Any, duration: int) -> None:
|
|
if self._record_listener:
|
|
self._record_listener.onTimerRecordStarted(source, RESULT_SUCCESS)
|
|
|
|
def clearTimerRecording(self, address: int, source: Any) -> None:
|
|
if self._record_listener:
|
|
self._record_listener.onClearTimerStarted(source, RESULT_SUCCESS)
|
|
|
|
def setRecordListener(self, listener: HdmiRecordListener) -> None:
|
|
self._record_listener = listener
|
|
|
|
def setCallback(self, callback: Callable) -> None:
|
|
self._callback = callback
|
|
|
|
def clearCallback(self) -> None:
|
|
self._callback = None
|
|
|
|
def startPlayback(self, address: int) -> None:
|
|
pass
|
|
|
|
def stopPlayback(self, address: int) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return "HdmiTvClient"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# HdmiControlManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class HdmiControlManager(Stub):
|
|
"""HdmiControlManager — HDMI 控制管理器 (桌面存根)"""
|
|
|
|
DEVICE_TYPE_TV = DEVICE_TYPE_TV
|
|
DEVICE_TYPE_RECORDER = DEVICE_TYPE_RECORDER
|
|
DEVICE_TYPE_TUNER = DEVICE_TYPE_TUNER
|
|
DEVICE_TYPE_PLAYBACK = DEVICE_TYPE_PLAYBACK
|
|
DEVICE_TYPE_AUDIO_SYSTEM = DEVICE_TYPE_AUDIO_SYSTEM
|
|
DEVICE_TYPE_PURE_CEC_SWITCH = DEVICE_TYPE_PURE_CEC_SWITCH
|
|
DEVICE_TYPE_VIDEO_PROCESSOR = DEVICE_TYPE_VIDEO_PROCESSOR
|
|
DEVICE_TYPE_RESERVED = DEVICE_TYPE_RESERVED
|
|
DEVICE_TYPE_INACTIVE = DEVICE_TYPE_INACTIVE
|
|
|
|
CONTROL_STATE_CHANGED_REASON_UNKNOWN = CONTROL_STATE_CHANGED_REASON_UNKNOWN
|
|
CONTROL_STATE_CHANGED_REASON_ENABLED = CONTROL_STATE_CHANGED_REASON_ENABLED
|
|
CONTROL_STATE_CHANGED_REASON_DISABLED = CONTROL_STATE_CHANGED_REASON_DISABLED
|
|
CONTROL_STATE_CHANGED_REASON_WAKE_UP = CONTROL_STATE_CHANGED_REASON_WAKE_UP
|
|
CONTROL_STATE_CHANGED_REASON_SLEEP = CONTROL_STATE_CHANGED_REASON_SLEEP
|
|
CONTROL_STATE_CHANGED_REASON_STANDBY = CONTROL_STATE_CHANGED_REASON_STANDBY
|
|
|
|
POWER_STATUS_ON = POWER_STATUS_ON
|
|
POWER_STATUS_STANDBY = POWER_STATUS_STANDBY
|
|
POWER_STATUS_TO_ON = POWER_STATUS_TO_ON
|
|
POWER_STATUS_TO_STANDBY = POWER_STATUS_TO_STANDBY
|
|
POWER_STATUS_UNKNOWN = POWER_STATUS_UNKNOWN
|
|
|
|
RESULT_SUCCESS = RESULT_SUCCESS
|
|
RESULT_FAILURE = RESULT_FAILURE
|
|
RESULT_TIMEOUT = RESULT_TIMEOUT
|
|
RESULT_NOT_SUPPORTED = RESULT_NOT_SUPPORTED
|
|
RESULT_BUSY = RESULT_BUSY
|
|
|
|
CEC_VERSION_1_4 = CEC_VERSION_1_4
|
|
CEC_VERSION_2_0 = CEC_VERSION_2_0
|
|
|
|
_instance: Optional["HdmiControlManager"] = None
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._lock = threading.Lock()
|
|
self._devices: Dict[int, HdmiDeviceInfo] = {}
|
|
self._ports: Dict[int, HdmiPortInfo] = {}
|
|
self._is_available = True
|
|
self._hdmi_cec_enabled = True
|
|
self._hdmi_mhl_enabled = True
|
|
self._system_audio_mode = False
|
|
self._arc_enabled = False
|
|
self._earc_enabled = False
|
|
self._active_source: Optional[HdmiDeviceInfo] = None
|
|
self._playback_client: Optional[HdmiPlaybackClient] = None
|
|
self._tv_client: Optional[HdmiTvClient] = None
|
|
self._switch_client: Optional[HdmiSwitchClient] = None
|
|
self._hotplug_listeners: List[Callable] = []
|
|
self._cec_message_listeners: List[Callable] = []
|
|
self._control_state_listeners: List[Callable] = []
|
|
|
|
def getPlaybackClient(self) -> Optional[HdmiPlaybackClient]:
|
|
if self._playback_client is None:
|
|
self._playback_client = HdmiPlaybackClient(self)
|
|
return self._playback_client
|
|
|
|
def getTvClient(self) -> Optional[HdmiTvClient]:
|
|
if self._tv_client is None:
|
|
self._tv_client = HdmiTvClient(self)
|
|
return self._tv_client
|
|
|
|
def getSwitchClient(self) -> Optional[HdmiSwitchClient]:
|
|
if self._switch_client is None:
|
|
self._switch_client = HdmiSwitchClient(self)
|
|
return self._switch_client
|
|
|
|
def getDeviceList(self) -> List[HdmiDeviceInfo]:
|
|
with self._lock:
|
|
return list(self._devices.values())
|
|
|
|
def getDeviceInfo(self, logicalAddress: int) -> Optional[HdmiDeviceInfo]:
|
|
with self._lock:
|
|
return self._devices.get(logicalAddress)
|
|
|
|
def getPortInfo(self, portId: int) -> Optional[HdmiPortInfo]:
|
|
with self._lock:
|
|
return self._ports.get(portId)
|
|
|
|
def getPorts(self) -> List[HdmiPortInfo]:
|
|
with self._lock:
|
|
return list(self._ports.values())
|
|
|
|
def addDevice(self, device: HdmiDeviceInfo) -> None:
|
|
with self._lock:
|
|
self._devices[device.getLogicalAddress()] = device
|
|
if device.isActiveSource():
|
|
self._active_source = device
|
|
|
|
def removeDevice(self, logicalAddress: int) -> Optional[HdmiDeviceInfo]:
|
|
with self._lock:
|
|
device = self._devices.pop(logicalAddress, None)
|
|
if device and self._active_source is device:
|
|
self._active_source = None
|
|
return device
|
|
|
|
def clearDevices(self) -> None:
|
|
with self._lock:
|
|
self._devices.clear()
|
|
self._active_source = None
|
|
|
|
def isCecEnabled(self) -> bool:
|
|
return self._hdmi_cec_enabled
|
|
|
|
def setCecEnabled(self, enabled: bool) -> None:
|
|
self._hdmi_cec_enabled = enabled
|
|
|
|
def isMhlEnabled(self) -> bool:
|
|
return self._hdmi_mhl_enabled
|
|
|
|
def setMhlEnabled(self, enabled: bool) -> None:
|
|
self._hdmi_mhl_enabled = enabled
|
|
|
|
def isSystemAudioMode(self) -> bool:
|
|
return self._system_audio_mode
|
|
|
|
def setSystemAudioMode(self, mode: bool) -> None:
|
|
self._system_audio_mode = mode
|
|
|
|
def isArcEnabled(self) -> bool:
|
|
return self._arc_enabled
|
|
|
|
def setArcEnabled(self, enabled: bool) -> None:
|
|
self._arc_enabled = enabled
|
|
|
|
def isEarcEnabled(self) -> bool:
|
|
return self._earc_enabled
|
|
|
|
def setEarcEnabled(self, enabled: bool) -> None:
|
|
self._earc_enabled = enabled
|
|
|
|
def getActiveSource(self) -> Optional[HdmiDeviceInfo]:
|
|
with self._lock:
|
|
return self._active_source
|
|
|
|
def setActiveSource(self, device: HdmiDeviceInfo) -> None:
|
|
with self._lock:
|
|
self._active_source = device
|
|
|
|
def addHotplugEventListener(self, listener: Callable) -> None:
|
|
if listener not in self._hotplug_listeners:
|
|
self._hotplug_listeners.append(listener)
|
|
|
|
def removeHotplugEventListener(self, listener: Callable) -> None:
|
|
if listener in self._hotplug_listeners:
|
|
self._hotplug_listeners.remove(listener)
|
|
|
|
def addCecMessageListener(self, listener: Callable) -> None:
|
|
if listener not in self._cec_message_listeners:
|
|
self._cec_message_listeners.append(listener)
|
|
|
|
def removeCecMessageListener(self, listener: Callable) -> None:
|
|
if listener in self._cec_message_listeners:
|
|
self._cec_message_listeners.remove(listener)
|
|
|
|
def addControlStateChangeListener(self, listener: Callable) -> None:
|
|
if listener not in self._control_state_listeners:
|
|
self._control_state_listeners.append(listener)
|
|
|
|
def removeControlStateChangeListener(self, listener: Callable) -> None:
|
|
if listener in self._control_state_listeners:
|
|
self._control_state_listeners.remove(listener)
|
|
|
|
def isAvailable(self) -> bool:
|
|
return self._is_available
|
|
|
|
def sendCecMessage(self, message: Any) -> int:
|
|
return RESULT_SUCCESS
|
|
|
|
def toString(self) -> str:
|
|
with self._lock:
|
|
return (
|
|
f"HdmiControlManager(devices={len(self._devices)}, "
|
|
f"ports={len(self._ports)}, "
|
|
f"cec={self._hdmi_cec_enabled})"
|
|
) |