Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 104 additions & 8 deletions androidtv/basetv/basetv.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,14 @@ class BaseTV(object): # pylint: disable=too-few-public-methods
DEVICE_ENUM = constants.DeviceEnum.BASETV

def __init__(
self, adb, host, port=5555, adbkey="", adb_server_ip="", adb_server_port=5037, state_detection_rules=None
self,
adb,
host,
port=5555,
adbkey="",
adb_server_ip="",
adb_server_port=5037,
state_detection_rules=None,
):
self._adb = adb
self.host = host
Expand Down Expand Up @@ -131,6 +138,14 @@ def _cmd_audio_state(self):
# Is this an Android 11 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
return constants.CMD_AUDIO_STATE11

# Is this an Android 12 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
return constants.CMD_AUDIO_STATE11

# Is this an Android 13 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
return constants.CMD_AUDIO_STATE11
return constants.CMD_AUDIO_STATE

def _cmd_current_app(self):
Expand All @@ -157,6 +172,14 @@ def _cmd_current_app(self):
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
return constants.CMD_CURRENT_APP11

# Is this an Android 12 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
return constants.CMD_CURRENT_APP12

# Is this an Android 13 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
return constants.CMD_CURRENT_APP13

return constants.CMD_CURRENT_APP

def _cmd_current_app_media_session_state(self):
Expand All @@ -183,6 +206,14 @@ def _cmd_current_app_media_session_state(self):
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
return constants.CMD_CURRENT_APP_MEDIA_SESSION_STATE11

# Is this an Android 12 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
return constants.CMD_CURRENT_APP_MEDIA_SESSION_STATE12

# Is this an Android 13 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
return constants.CMD_CURRENT_APP_MEDIA_SESSION_STATE13

return constants.CMD_CURRENT_APP_MEDIA_SESSION_STATE

def _cmd_hdmi_input(self):
Expand All @@ -201,8 +232,39 @@ def _cmd_hdmi_input(self):
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
return constants.CMD_HDMI_INPUT11

# Is this an Android 12 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
return constants.CMD_HDMI_INPUT11

# Is this an Android 13 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
return constants.CMD_HDMI_INPUT11

return constants.CMD_HDMI_INPUT

def _cmd_volume_set(self):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be simpler to take volume_level as a parameter and return the formatted string.

"""Get the command used to set volume for this device.

Returns
-------
str
The device-specific ADB shell command used to set volume

"""
# Is this an Android 11 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
return constants.CMD_VOLUME_SET_COMMAND11

# Is this an Android 12 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
return constants.CMD_VOLUME_SET_COMMAND11

# Is this an Android 13 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
return constants.CMD_VOLUME_SET_COMMAND11

return constants.CMD_VOLUME_SET_COMMAND

def _cmd_launch_app(self, app):
"""Get the command to launch the specified app for this device.

Expand Down Expand Up @@ -235,6 +297,14 @@ def _cmd_launch_app(self, app):
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
return constants.CMD_LAUNCH_APP11.format(app)

# Is this an Android 12 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
return constants.CMD_LAUNCH_APP12.format(app)

# Is this an Android 13 device?
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
return constants.CMD_LAUNCH_APP13.format(app)

return constants.CMD_LAUNCH_APP.format(app)

def _cmd_running_apps(self):
Expand Down Expand Up @@ -339,7 +409,12 @@ def _parse_device_properties(self, properties):
``'serialno'``, ``'manufacturer'``, ``'model'``, and ``'sw_version'``

"""
_LOGGER.debug("%s:%d `get_device_properties` response: %s", self.host, self.port, properties)
_LOGGER.debug(
"%s:%d `get_device_properties` response: %s",
self.host,
self.port,
properties,
)

if not properties:
self.device_properties = {}
Expand All @@ -353,7 +428,12 @@ def _parse_device_properties(self, properties):
manufacturer, model, serialno, version = lines

if not serialno.strip():
_LOGGER.warning("Could not obtain serialno for %s:%d, got: '%s'", self.host, self.port, serialno)
_LOGGER.warning(
"Could not obtain serialno for %s:%d, got: '%s'",
self.host,
self.port,
serialno,
)
serialno = None

self.device_properties = {
Expand Down Expand Up @@ -393,7 +473,11 @@ def _parse_mac_address(mac_response):
# #
# ======================================================================= #
def _custom_state_detection(
self, current_app=None, media_session_state=None, wake_lock_size=None, audio_state=None
self,
current_app=None,
media_session_state=None,
wake_lock_size=None,
audio_state=None,
):
"""Use the rules in ``self._state_detection_rules`` to determine the state.

Expand Down Expand Up @@ -670,7 +754,11 @@ def _parse_stream_music(stream_music_raw):
if not stream_music_raw:
return None

matches = re.findall(constants.STREAM_MUSIC_REGEX_PATTERN, stream_music_raw, re.DOTALL | re.MULTILINE)
matches = re.findall(
constants.STREAM_MUSIC_REGEX_PATTERN,
stream_music_raw,
re.DOTALL | re.MULTILINE,
)
if matches:
return matches[0]

Expand Down Expand Up @@ -747,15 +835,21 @@ def _volume(self, stream_music, audio_output_device):
return None

if not self.max_volume:
max_volume_matches = re.findall(constants.MAX_VOLUME_REGEX_PATTERN, stream_music, re.DOTALL | re.MULTILINE)
max_volume_matches = re.findall(
constants.MAX_VOLUME_REGEX_PATTERN,
stream_music,
re.DOTALL | re.MULTILINE,
)
if max_volume_matches:
self.max_volume = float(max_volume_matches[0])

if not audio_output_device:
return None

volume_matches = re.findall(
audio_output_device + constants.VOLUME_REGEX_PATTERN, stream_music, re.DOTALL | re.MULTILINE
audio_output_device + constants.VOLUME_REGEX_PATTERN,
stream_music,
re.DOTALL | re.MULTILINE,
)
if volume_matches:
return int(volume_matches[0])
Expand Down Expand Up @@ -899,7 +993,9 @@ def state_detection_rules_validator(rules, exc=KeyError):
if not isinstance(value, constants.VALID_PROPERTIES_TYPES[prop]):
raise exc(
"Conditional value for property '{0}' must be of type {1}, not {2}".format(
prop, constants.VALID_PROPERTIES_TYPES[prop].__name__, type(value).__name__
prop,
constants.VALID_PROPERTIES_TYPES[prop].__name__,
type(value).__name__,
)
)

Expand Down
2 changes: 1 addition & 1 deletion androidtv/basetv/basetv_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ async def set_volume_level(self, volume_level):

new_volume = int(min(max(round(self.max_volume * volume_level), 0.0), self.max_volume))

await self._adb.shell("media volume --show --stream 3 --set {}".format(new_volume))
await self._adb.shell(self._cmd_volume_set().format(new_volume))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change needs to be made in basetv_sync.py, too.


# return the new volume level
return new_volume / self.max_volume
Expand Down
48 changes: 46 additions & 2 deletions androidtv/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ class DeviceEnum(IntEnum):

#: Parse current application for an Android 11 device
CMD_PARSE_CURRENT_APP11 = "CURRENT_APP=${CURRENT_APP%%/*} && CURRENT_APP=${CURRENT_APP##* }"

#: Assign focused application identifier to ``CURRENT_APP`` variable
CMD_DEFINE_CURRENT_APP_VARIABLE = (
"CURRENT_APP=$(dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp') && " + CMD_PARSE_CURRENT_APP
Expand All @@ -99,13 +98,30 @@ class DeviceEnum(IntEnum):
"CURRENT_APP=$(dumpsys window windows | grep -E -m 1 'mInputMethod(Input)?Target') && " + CMD_PARSE_CURRENT_APP11
)

#: Assign focused application identifier to ``CURRENT_APP`` variable for an Android 12 device
CMD_DEFINE_CURRENT_APP_VARIABLE12 = (
"CURRENT_APP=$(dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp|mObscuringWindow') && "
+ CMD_PARSE_CURRENT_APP11
)

#: Assign focused application identifier to ``CURRENT_APP`` variable for an Android 13 device
CMD_DEFINE_CURRENT_APP_VARIABLE13 = (
"CURRENT_APP=$(dumpsys window windows | grep -E -m 1 'imeLayeringTarget|imeInputTarget|imeControlTarget') && "
+ CMD_PARSE_CURRENT_APP11
)

#: Output identifier for current/focused application
CMD_CURRENT_APP = CMD_DEFINE_CURRENT_APP_VARIABLE + " && echo $CURRENT_APP"

#: Output identifier for current/focused application for an Android 11 device
CMD_CURRENT_APP11 = CMD_DEFINE_CURRENT_APP_VARIABLE11 + " && echo $CURRENT_APP"

#: Output identifier for current/focused application for an Android 12 device
CMD_CURRENT_APP12 = CMD_DEFINE_CURRENT_APP_VARIABLE12 + " && echo $CURRENT_APP"

#: Output identifier for current/focused application for an Android 13 device
CMD_CURRENT_APP13 = CMD_DEFINE_CURRENT_APP_VARIABLE13 + " && echo $CURRENT_APP"

#: Assign focused application identifier to ``CURRENT_APP`` variable (for a Google TV device)
CMD_DEFINE_CURRENT_APP_VARIABLE_GOOGLE_TV = (
"CURRENT_APP=$(dumpsys activity a . | grep mResumedActivity) && " + CMD_PARSE_CURRENT_APP
Expand All @@ -114,6 +130,12 @@ class DeviceEnum(IntEnum):
#: Output identifier for current/focused application (for a Google TV device)
CMD_CURRENT_APP_GOOGLE_TV = CMD_DEFINE_CURRENT_APP_VARIABLE_GOOGLE_TV + " && echo $CURRENT_APP"

#: set volume
CMD_VOLUME_SET_COMMAND = "media volume --show --stream 3 --set {}"

#: set volume for an Android 11 & 12 & 13 device
CMD_VOLUME_SET_COMMAND11 = "cmd media_session volume --show --stream 3 --set {}"

#: Get the HDMI input
CMD_HDMI_INPUT = (
"dumpsys activity starter | grep -E -o '(ExternalTv|HDMI)InputService/HW[0-9]' -m 1 | grep -o 'HW[0-9]'"
Expand Down Expand Up @@ -145,6 +167,16 @@ class DeviceEnum(IntEnum):
CMD_DEFINE_CURRENT_APP_VARIABLE11.replace("{", "{{").replace("}", "}}") + " && " + CMD_LAUNCH_APP_CONDITION
)

#: Launch an app if it is not already the current app on an Android 12 device
CMD_LAUNCH_APP12 = (
CMD_DEFINE_CURRENT_APP_VARIABLE12.replace("{", "{{").replace("}", "}}") + " && " + CMD_LAUNCH_APP_CONDITION
)

#: Launch an app if it is not already the current app on an Android 11 device
CMD_LAUNCH_APP13 = (
CMD_DEFINE_CURRENT_APP_VARIABLE13.replace("{", "{{").replace("}", "}}") + " && " + CMD_LAUNCH_APP_CONDITION
)

#: Launch an app on a Fire TV device
CMD_LAUNCH_APP_FIRETV = (
CMD_DEFINE_CURRENT_APP_VARIABLE.replace("{", "{{").replace("}", "}}") + " && " + CMD_LAUNCH_APP_CONDITION_FIRETV
Expand All @@ -164,6 +196,12 @@ class DeviceEnum(IntEnum):
#: Determine the current app and get the state from ``dumpsys media_session`` for an Android 11 device
CMD_CURRENT_APP_MEDIA_SESSION_STATE11 = CMD_CURRENT_APP11 + " && " + CMD_MEDIA_SESSION_STATE

#: Determine the current app and get the state from ``dumpsys media_session`` for an Android 12 device
CMD_CURRENT_APP_MEDIA_SESSION_STATE12 = CMD_CURRENT_APP12 + " && " + CMD_MEDIA_SESSION_STATE

#: Determine the current app and get the state from ``dumpsys media_session`` for an Android 13 device
CMD_CURRENT_APP_MEDIA_SESSION_STATE13 = CMD_CURRENT_APP13 + " && " + CMD_MEDIA_SESSION_STATE

#: Determine the current app and get the state from ``dumpsys media_session`` for a Google TV device
CMD_CURRENT_APP_MEDIA_SESSION_STATE_GOOGLE_TV = CMD_CURRENT_APP_GOOGLE_TV + " && " + CMD_MEDIA_SESSION_STATE

Expand Down Expand Up @@ -381,7 +419,11 @@ class DeviceEnum(IntEnum):
VALID_PROPERTIES = VALID_STATE_PROPERTIES + ("wake_lock_size",)

#: The required type for each entry in :py:const:`VALID_PROPERTIES` (used by :func:`~androidtv.basetv.state_detection_rules_validator`)
VALID_PROPERTIES_TYPES = {"audio_state": str, "media_session_state": int, "wake_lock_size": int}
VALID_PROPERTIES_TYPES = {
"audio_state": str,
"media_session_state": int,
"wake_lock_size": int,
}

# https://developer.android.com/reference/android/media/session/PlaybackState.html
#: States for the :attr:`~androidtv.basetv.basetv.BaseTV.media_session_state` property
Expand Down Expand Up @@ -483,6 +525,7 @@ class DeviceEnum(IntEnum):
APP_TWITCH_FIRETV = "tv.twitch.android.viewer"
APP_VEVO = "com.vevo.tv"
APP_VH1 = "com.mtvn.vh1android"
APP_VIKI = "com.viki.android"
APP_VIMEO = "com.vimeo.android.videoapp"
APP_VLC = "org.videolan.vlc"
APP_VOYO = "com.phonegap.voyo"
Expand Down Expand Up @@ -590,6 +633,7 @@ class DeviceEnum(IntEnum):
APP_TWITCH_FIRETV: "Twitch (FireTV)",
APP_VEVO: "Vevo",
APP_VH1: "VH1",
APP_VIKI: "Rakuten Viki",
APP_VIMEO: "Vimeo",
APP_VLC: "VLC",
APP_VOYO: "VOYO",
Expand Down
4 changes: 4 additions & 0 deletions tests/generate_test_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@
"CMD_SUCCESS1_FAILURE0",
"CMD_PARSE_CURRENT_APP",
"CMD_PARSE_CURRENT_APP11",
"CMD_PARSE_CURRENT_APP12",
"CMD_PARSE_CURRENT_APP13",
"CMD_DEFINE_CURRENT_APP_VARIABLE",
"CMD_DEFINE_CURRENT_APP_VARIABLE11",
"CMD_DEFINE_CURRENT_APP_VARIABLE12",
"CMD_DEFINE_CURRENT_APP_VARIABLE13",
"CMD_DEFINE_CURRENT_APP_VARIABLE_GOOGLE_TV",
"CMD_LAUNCH_APP_CONDITION",
"CMD_LAUNCH_APP_CONDITION_FIRETV",
Expand Down
Loading