import json import threading import xbmc import xbmcaddon ADDON = xbmcaddon.Addon() ADDON_ID = ADDON.getAddonInfo("id") VIEW_MODE = "stretch4x3" def log(message, level=xbmc.LOGINFO): xbmc.log(f"[{ADDON_ID}] {message}", level) def jsonrpc(method, params=None): payload = { "jsonrpc": "2.0", "id": 1, "method": method, } if params is not None: payload["params"] = params request = json.dumps(payload) response = xbmc.executeJSONRPC(request) try: data = json.loads(response) except ValueError: log(f"Invalid JSON-RPC response from {method}: {response}", xbmc.LOGERROR) return None if "error" in data: log(f"JSON-RPC {method} failed: {data['error']}", xbmc.LOGWARNING) return None return data.get("result") def get_active_video_player_id(): result = jsonrpc("Player.GetActivePlayers") if not isinstance(result, list): return None for player in result: if player.get("type") == "video": return player.get("playerid") return None def get_current_item(player_id): result = jsonrpc( "Player.GetItem", { "playerid": player_id, "properties": ["file"], }, ) if not isinstance(result, dict): return None item = result.get("item") if not isinstance(item, dict): return None return item class PvrStretchPlayer(xbmc.Player): def __init__(self, monitor): super().__init__() self.monitor = monitor def onPlayBackStarted(self): threading.Thread(target=self._apply, daemon=True).start() def _apply(self): item = None for _ in range(100): if self.monitor.abortRequested(): return player_id = get_active_video_player_id() if player_id is not None: item = get_current_item(player_id) if item: break if self.monitor.waitForAbort(0.1): return if not item: log("No player item found after playback start", xbmc.LOGWARNING) return item_type = (item or {}).get("type") if item_type != "channel": return log(f"Applying {VIEW_MODE}: type={item_type}") result = jsonrpc("Player.SetViewMode", {"viewmode": VIEW_MODE}) if result is None: log(f"Failed to apply {VIEW_MODE}", xbmc.LOGWARNING) return log(f"Applied {VIEW_MODE}: result={result}") def run(): monitor = xbmc.Monitor() player = PvrStretchPlayer(monitor) log("Service started") while not monitor.abortRequested(): monitor.waitForAbort(1) del player log("Service stopped") if __name__ == "__main__": run()