Skip to content

Commit 6c0554f

Browse files
authored
Some refactorings (#51)
* feat: borrow things from hyperion control - use GuiHandler, Logger and align Settings to SettingsManager from hyperion control - remove "needs_reconnection" check - upgrade pil dependency * build: fix check script
1 parent 26cc319 commit 6c0554f

File tree

8 files changed

+115
-89
lines changed

8 files changed

+115
-89
lines changed

Pipfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ python_version = "3.11"
1515
[scripts]
1616
pre-commit = "pre-commit install"
1717
lint = "pre-commit run --all"
18-
check = "kodi-addon-checker --branch nexus --allow-folder-id-mismatch script.service.hyperion-control"
18+
check = "kodi-addon-checker --branch nexus --allow-folder-id-mismatch script.service.hyperion"

script.service.hyperion/addon.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<requires>
44
<import addon="xbmc.addon" version="20.0.0"/>
55
<import addon="xbmc.python" version="3.0.1"/>
6-
<import addon="script.module.pil" version="1.1.7"/>
6+
<import addon="script.module.pil" version="5.1.0"/>
77
<import addon="script.module.protobuf" version="4.23.2"/>
88
</requires>
99
<extension point="xbmc.service" library="service.py"/>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Kodi GUI handler."""
2+
from __future__ import annotations
3+
4+
import xbmcaddon
5+
import xbmcgui
6+
from resources.lib.settings import SettingsManager
7+
8+
9+
class GuiHandler:
10+
"""Kodi GUI handler."""
11+
12+
def __init__(
13+
self, addon: xbmcaddon.Addon, settings_manager: SettingsManager
14+
) -> None:
15+
self._addon = addon
16+
self._settings = settings_manager
17+
self._dialog = xbmcgui.Dialog() # TODO: DI with embedded getlocalizedstring
18+
self._addon_name = addon.getAddonInfo("name")
19+
self._addon_icon = addon.getAddonInfo("icon")
20+
21+
def _get_localized_string(self, label_id: int) -> str:
22+
"""Returns the localized string of a label ID."""
23+
return self._addon.getLocalizedString(label_id)
24+
25+
def notify_label(self, label_id: int) -> None:
26+
"""Displays a notification with the localized message."""
27+
message = self._get_localized_string(label_id)
28+
self.notify_text(message, time=1000, icon=self._addon_icon)
29+
30+
def notify_text(
31+
self, message: str, time: int = 3000, icon: str = xbmcgui.NOTIFICATION_INFO
32+
) -> None:
33+
"""Displays a notification."""
34+
self._dialog.notification(self._addon_name, message, icon, time)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""Logging facility."""
2+
import xbmc
3+
4+
5+
class Logger:
6+
"""Logging facility for Kodi add-ons."""
7+
8+
def __init__(self, addon_name: str) -> None:
9+
self._addon_name = addon_name
10+
11+
def log(self, message: str, level: int = xbmc.LOGDEBUG) -> None:
12+
"""Writes the message to the logger with the addon name as prefix."""
13+
xbmc.log(f"[{self._addon_name}] - {message}", level=level)
14+
15+
def debug(self, message: str) -> None:
16+
"""Writes a debug message to the log."""
17+
self.log(message)
18+
19+
def info(self, message: str) -> None:
20+
"""Writes an info message to the log."""
21+
self.log(message, level=xbmc.LOGINFO)
22+
23+
def error(self, message: str) -> None:
24+
"""Writes an error message to the log."""
25+
self.log(message, level=xbmc.LOGERROR)

script.service.hyperion/resources/lib/misc.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

script.service.hyperion/resources/lib/monitor.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@
2626
import xbmc
2727
from PIL import Image
2828

29+
from resources.lib.gui import GuiHandler
2930
from resources.lib.hyperion.hyperion import Hyperion
30-
from resources.lib.misc import MessageHandler
31-
from resources.lib.settings import Settings
31+
from resources.lib.logger import Logger
32+
from resources.lib.settings import SettingsManager
3233

3334
State = Callable[[], "State"]
3435

@@ -37,11 +38,16 @@ class HyperionMonitor(xbmc.Monitor):
3738
"""Class to capture changes in settings and screensaver state."""
3839

3940
def __init__(
40-
self, settings: Settings, player: xbmc.Player, output_handler: MessageHandler
41+
self,
42+
settings: SettingsManager,
43+
player: xbmc.Player,
44+
output_handler: GuiHandler,
45+
logger: Logger,
4146
) -> None:
4247
super().__init__()
4348
self.settings = settings
4449
self.output_handler = output_handler
50+
self._logger = logger
4551
self._screensaver = xbmc.getCondVisibility("System.ScreenSaverActive")
4652
self._player = player
4753
self.show_error_message = True
@@ -50,7 +56,7 @@ def __init__(
5056

5157
def onSettingsChanged(self) -> None:
5258
self.settings.read_settings()
53-
if self.settings.needs_reconnection and self.grabbing:
59+
if self.grabbing:
5460
self.connect()
5561

5662
def onScreensaverDeactivated(self) -> None:
@@ -72,7 +78,7 @@ def grabbing(self) -> bool:
7278

7379
def notify_error(self, label_id: int) -> None:
7480
if self.show_error_message:
75-
self.output_handler.notify(label_id)
81+
self.output_handler.notify_label(label_id)
7682
self.show_error_message = False
7783

7884
def main_loop(self) -> None:
@@ -101,8 +107,10 @@ def error_state(self) -> State:
101107
return self.disconnected_state
102108

103109
def connect(self) -> None:
104-
self.output_handler.log("Establishing connection to hyperion")
105110
settings = self.settings
111+
self._logger.info(
112+
f"Establishing connection to hyperion at {settings.address}:{settings.port}"
113+
)
106114
self._hyperion = Hyperion(settings.address, settings.port)
107115
self._capture = xbmc.RenderCapture()
108116

@@ -123,7 +131,7 @@ def connected_state(self) -> State:
123131
self._capture.capture(*capture_size)
124132
cap_image = self._capture.getImage(self.settings.sleep_time)
125133
if cap_image is None or len(cap_image) < expected_capture_size:
126-
self.output_handler.log(
134+
self._logger.debug(
127135
f"Captured image is none or < expected. "
128136
f"captured: {len(cap_image) if cap_image is not None else 'None'}, "
129137
f"expected: {expected_capture_size}"
@@ -145,7 +153,7 @@ def connected_state(self) -> State:
145153
)
146154
except Exception:
147155
# unable to send image. notify and go to the error state
148-
self.output_handler.notify(32101)
156+
self.output_handler.notify_label(32101)
149157
return self.error_state
150158

151159
return self.connected_state

script.service.hyperion/resources/lib/settings.py

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,41 +25,30 @@
2525

2626
from typing import TYPE_CHECKING
2727

28+
from resources.lib.logger import Logger
29+
2830
if TYPE_CHECKING:
2931
import xbmcaddon
3032

3133

32-
class Settings:
34+
class SettingsManager:
3335
"""Class which contains all addon settings."""
3436

35-
def __init__(self, settings: xbmcaddon.Settings) -> None:
37+
def __init__(self, settings: xbmcaddon.Settings, logger: Logger) -> None:
38+
self._logger = logger
3639
self.rev = 0
3740
self._settings = settings
38-
self.needs_reconnection = False
39-
self._address = "localhost"
40-
self._port = 19445
41-
self.read_settings()
42-
43-
@property
44-
def address(self) -> str:
45-
"""Hyperion server's hostname or IP-address."""
46-
return self._address
47-
48-
@address.setter
49-
def address(self, value: str) -> None:
50-
"""Hyperion server's hostname or IP-address."""
51-
self.needs_reconnection = self._address != value
52-
self._address = value
41+
self.address = "localhost"
42+
self.port = 19445
43+
self.enable: bool
44+
self.enable_screensaver: bool
45+
self.priority: int
46+
self.timeout: int
47+
self.capture_width: int
48+
self.framerate: int
49+
self.sleep_time: int
5350

54-
@property
55-
def port(self) -> int:
56-
"""Hyperion server port."""
57-
return self._port
58-
59-
@port.setter
60-
def port(self, value: int) -> None:
61-
self.needs_reconnection = self._port != value
62-
self._port = value
51+
self.read_settings()
6352

6453
def read_settings(self) -> None:
6554
"""Read all settings."""
@@ -74,3 +63,16 @@ def read_settings(self) -> None:
7463
self.address = settings.getString("hyperion_ip")
7564
self.port = settings.getInt("hyperion_port")
7665
self.rev += 1
66+
self._log_settings()
67+
68+
def _log_settings(self) -> None:
69+
log = self._logger.debug
70+
log("Settings updated!")
71+
log(f"Hyperion ip: {self.address}")
72+
log(f"Hyperion port: {self.port}")
73+
log(f"enabled: {self.enable}")
74+
log(f"enabled on screensaver: {self.enable_screensaver}")
75+
log(f"priority: {self.priority}")
76+
log(f"timeout: {self.timeout}")
77+
log(f"capture width: {self.capture_width}")
78+
log(f"framerate: {self.framerate}")

script.service.hyperion/service.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,21 @@
2424

2525
import xbmc
2626
import xbmcaddon
27-
from resources.lib.misc import MessageHandler
27+
from resources.lib.gui import GuiHandler
28+
from resources.lib.logger import Logger
2829
from resources.lib.monitor import HyperionMonitor
29-
from resources.lib.settings import Settings
30+
from resources.lib.settings import SettingsManager
31+
32+
ADDON_NAME = "script.service.hyperion"
3033

3134

3235
def main() -> None:
33-
addon = xbmcaddon.Addon()
36+
addon = xbmcaddon.Addon(ADDON_NAME)
37+
logger = Logger(addon.getAddonInfo("name"))
38+
settings_manager = SettingsManager(addon.getSettings(), logger)
3439
player = xbmc.Player()
35-
settings = Settings(addon.getSettings())
36-
output_handler = MessageHandler(addon)
37-
monitor = HyperionMonitor(settings, player, output_handler)
40+
output_handler = GuiHandler(addon, settings_manager)
41+
monitor = HyperionMonitor(settings_manager, player, output_handler, logger)
3842
monitor.main_loop()
3943

4044

0 commit comments

Comments
 (0)