commit ed0c69bc9723bf1a57ae3060daf35b9e1ae29954 Author: Pierre-Olivier Mercier Date: Sun Jun 2 03:30:00 2024 +0200 Initial commit diff --git a/addon.py b/addon.py new file mode 100644 index 0000000..2415db4 --- /dev/null +++ b/addon.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +import xbmc +import xbmcgui +import xbmcaddon +import json +import urllib.request + +# Load the settings +ADDON = xbmcaddon.Addon() +API_URL = ADDON.getSetting('api_url') + +def send_request(endpoint, data): + url = f"{API_URL}/{endpoint}" + data = json.dumps(data).encode('utf-8') + req = urllib.request.Request(url, data, headers={'Content-Type': 'application/json'}) + response = urllib.request.urlopen(req) + return json.loads(response.read().decode('utf-8')) + +class AmplifierControlDialog(xbmcgui.WindowXMLDialog): + def __init__(self, *args, **kwargs): + super(AmplifierControlDialog, self).__init__(*args, **kwargs) + + def onInit(self): + #self.getControl(100).setLabel("Volume") + #self.getControl(200).setLabel("Source") + pass + + def onClick(self, controlId): + if controlId == 100: + volume = self.getControl(101).getValue() + send_request('set_volume', {'volume': volume}) + elif controlId == 200: + source = self.getControl(201).getSelectedItem().getLabel() + send_request('set_source', {'source': source}) + +if __name__ == '__main__': + dialog = AmplifierControlDialog('amplifier_control.xml', ADDON.getAddonInfo('path'), 'default', '720p') + dialog.doModal() + del dialog diff --git a/addon.xml b/addon.xml new file mode 100644 index 0000000..65e313d --- /dev/null +++ b/addon.xml @@ -0,0 +1,14 @@ + + + + + + + executable + + + Control your amplifier through a REST API + Allows you to control volume, source, and other settings of your amplifier via a REST API. + all + + diff --git a/lib/main.py b/lib/main.py new file mode 100644 index 0000000..92437d7 --- /dev/null +++ b/lib/main.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +import xbmc +import xbmcgui +import xbmcaddon +import json +import urllib.request +import logging + +# Initialize the logger +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger(__name__) + +ADDON = xbmcaddon.Addon() +ADDONID = xbmcaddon.Addon().getAddonInfo('id') +CWD = xbmcaddon.Addon().getAddonInfo('path') +API_URL = ADDON.getSetting('api_url') + +CANCEL_DIALOG = (9, 10, 92, 216, 247, 257, 275, 61467, 61448) + +def send_request(endpoint, data=None): + url = f"{API_URL}{endpoint}" + if data is not None: + data = json.dumps(data).encode('utf-8') + req = urllib.request.Request(url, data, headers={'Content-Type': 'application/json'}) + response = urllib.request.urlopen(req) + if response.status > 300: + res = json.loads(response.read().decode('utf-8')) + xbmcgui.Dialog().notification('Error', f"Failed to create dialog: {res['errmsg']}", xbmcgui.NOTIFICATION_ERROR) + raise Exception(res["errmsg"]) + return json.loads(response.read().decode('utf-8')) + + +# Sources ########################################################## + +def get_sources(): + sources = send_request("/sources") + res = [] + for src in sources: + source = sources[src] + source["id"] = src + res.append(source) + return res + +def get_current_source(): + sources = send_request("/sources") + for src in sources: + source = sources[src] + if source["enabled"]: + return sources[src]["name"] + return None + +def enable_source(src): + send_request("/sources/" + src + "/enable", {}) + return True + + +# Mixer ############################################################ + +def get_mixers(): + return send_request("/mixer") + +def mixer_value(mixer): + if mixer["Type"] == "ENUMERATED": + return str(mixer["items"][mixer["values"][0]]) + elif mixer["Type"] == "BOOLEAN": + return "Oui" if mixer["items"][mixer["values"][0]] else "Non" + elif mixer["Type"] == "INTEGER" and "DBScale" in mixer: + return "%0.1f dB" % (mixer["DBScale"]["Min"] + mixer["DBScale"]["Step"] * mixer["values"][0]) + else: + return str(mixer["values"][0]) + +def set_mixer(mixer, value): + val = [] + for v in mixer["values"]: + val.append(value) + send_request("/mixer/%s/values" % mixer["NumID"], val) + return True + + +class AmplifierControlDialog(xbmcgui.WindowXMLDialog): + def __init__(self, *args, **kwargs): + super(AmplifierControlDialog, self).__init__(*args, **kwargs) + self.data = kwargs['optional1'] + + def onInit(self): + self.getControl(2).setLabel("Hathoris") + + self.list = self.getControl(10) + self.list.reset() + self.list.addItem(xbmcgui.ListItem("Source", get_current_source())) + + self.mixers = get_mixers() + for mixer in self.mixers: + self.list.addItem(xbmcgui.ListItem(mixer["Name"], mixer_value(mixer))) + + #self.getControl(100).setLabel("Volume") + #self.getControl(200).setLabel("Source") + return + + def onClick(self, controlId): + if controlId == 10: + if self.list.getSelectedPosition() == 0: + sources = get_sources() + selected = xbmcgui.Dialog().select('Sélectionnez la source à utiliser', [s["name"] for s in sources]) + if selected != -1: + enable_source(sources[selected]["id"]) + self.onInit() + elif self.mixers[self.list.getSelectedPosition() - 1]["Type"] == "ENUMERATED": + items = self.mixers[self.list.getSelectedPosition() - 1]["items"] + selected = xbmcgui.Dialog().select(self.mixers[self.list.getSelectedPosition() - 1]["Name"], items, preselect=self.mixers[self.list.getSelectedPosition() - 1]["values"][0]) + if selected != -1: + set_mixer(self.mixers[self.list.getSelectedPosition() - 1], selected) + self.onInit() + elif self.mixers[self.list.getSelectedPosition() - 1]["Type"] == "BOOLEAN": + items = ["Non", "Oui"] + selected = xbmcgui.Dialog().select(self.mixers[self.list.getSelectedPosition() - 1]["Name"], items, preselect=1 if self.mixers[self.list.getSelectedPosition() - 1]["values"][0] else 0) + if selected != -1: + set_mixer(self.mixers[self.list.getSelectedPosition() - 1], True if selected else False) + self.onInit() + else: + newval = xbmcgui.Dialog().numeric(0, self.mixers[self.list.getSelectedPosition() - 1]["Name"], str(self.mixers[self.list.getSelectedPosition() - 1]["values"][0])) + set_mixer(self.mixers[self.list.getSelectedPosition() - 1], int(newval)) + self.onInit() + elif controlId == 100: + volume = self.getControl(101).getValue() + send_request('set_volume', {'volume': volume}) + elif controlId == 200: + source = self.getControl(201).getSelectedItem().getLabel() + send_request('set_source', {'source': source}) + elif controlId == 18: + self.close() + + def onAction(self, action): + if action.getButtonCode() in CANCEL_DIALOG: + self.close() + +if __name__ == '__main__': + try: + dialog = AmplifierControlDialog('amplifier_control.xml', CWD, 'default', optional1='some data') + dialog.doModal() + del dialog + except Exception as e: + logger.error(f"Failed to create dialog: {e}") + xbmcgui.Dialog().notification('Error', f"Failed to create dialog: {e}", xbmcgui.NOTIFICATION_ERROR) diff --git a/resources/language/resource.language.en_GB/strings.po b/resources/language/resource.language.en_GB/strings.po new file mode 100644 index 0000000..5683e0a --- /dev/null +++ b/resources/language/resource.language.en_GB/strings.po @@ -0,0 +1,110 @@ +# Kodi Media Center language file +# Addon Name: RSS Editor +# Addon id: script.rss.editor +# Addon Provider: Team Kodi +msgid "" +msgstr "" + +"Project-Id-Version: XBMC Addons\n" +"Report-Msgid-Bugs-To: alanwww1@xbmc.org\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (http://www.transifex.com/projects/p/xbmc-addons/language/en/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#32000" +msgid "RSS Editor" +msgstr "" + +msgctxt "#32001" +msgid "Change Set" +msgstr "" + +msgctxt "#32002" +msgid "items" +msgstr "" + +msgctxt "#32003" +msgid "Pages" +msgstr "" + +msgctxt "#32006" +msgid "Edit Attributes" +msgstr "" + +msgctxt "#32012" +msgid "RSS Feed URL" +msgstr "" + +msgctxt "#32013" +msgid "Update Interval" +msgstr "" + +msgctxt "#32014" +msgid "Enter the paths of your RSS feeds %s" +msgstr "" + +msgctxt "#32024" +msgid "Select a Set " +msgstr "" + +msgctxt "#32025" +msgid "Set ID" +msgstr "" + +msgctxt "#32027" +msgid "Enable Right to Left Text for this Set?" +msgstr "" + +msgctxt "#32030" +msgid "Set Editor" +msgstr "" + +msgctxt "#32040" +msgid "Error: " +msgstr "" + +msgctxt "#32041" +msgid "was either not found in the system," +msgstr "" + +msgctxt "#32042" +msgid "or does not contain parsable XML." +msgstr "" + +msgctxt "#32043" +msgid "Try deleting it from your userdata folder and restarting XBMC." +msgstr "" + +msgctxt "#32045" +msgid "Cannot Delete Set 1" +msgstr "" + +msgctxt "#32046" +msgid "Set 1 is required. You cannot delete this." +msgstr "" + +msgctxt "#32047" +msgid "Reset set 1 to default?" +msgstr "" + +msgctxt "#32050" +msgid "Set %s already exists." +msgstr "" + +msgctxt "#32051" +msgid "Your RSSFeeds.xml file is corrupt." +msgstr "" + +msgctxt "#32052" +msgid "Attempt to regenerate" +msgstr "" + +msgctxt "#32053" +msgid "You will loose all previous settings" +msgstr "" diff --git a/resources/settings.xml b/resources/settings.xml new file mode 100644 index 0000000..3b62f24 --- /dev/null +++ b/resources/settings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/skins/default/1080i/amplifier_control.xml b/resources/skins/default/1080i/amplifier_control.xml new file mode 100644 index 0000000..b76f4b2 --- /dev/null +++ b/resources/skins/default/1080i/amplifier_control.xml @@ -0,0 +1,135 @@ + + + 10 + + 350 + 135 + + + + 0 + 0 + 1220 + 712 + hathoris-panel.png + + + 0 + 0 + 1220 + 70 + hathoris-header.png + + + 70 + -30 + 0 + 1220 + 70 + font32_title + left + center + black + + + 20 + 80 + 10 + 10 + 9001 + 9001 + -20 + 200 + + + 0 + 0 + 880 + 2 + hathoris-list-separator.png + + + 0 + 20 + 0 + 880 + 69 + center + grey + + font13 + + + 0 + 20 + 0 + 880 + 69 + center + right + white + + font13 + + + + + 0 + 0 + 880 + 2 + hathoris-list-separator.png + + + 0 + 0 + 880 + 69 + hathoris-list-focus.png + Conditional + + + 0 + 20 + 0 + 880 + 69 + center + + font13 + + + 0 + 20 + 0 + 880 + 69 + right + center + + font13 + + + + + 920 + 80 + 9001 + 9001 + 10 + 10 + -20 + + 300 + 90 + + font12_title + white + 20 + center + hathoris-button-nofocus.png + hathoris-button-focus.png + + + + diff --git a/resources/skins/default/media/hathoris-button-focus.png b/resources/skins/default/media/hathoris-button-focus.png new file mode 100644 index 0000000..1bc84ff Binary files /dev/null and b/resources/skins/default/media/hathoris-button-focus.png differ diff --git a/resources/skins/default/media/hathoris-button-nofocus.png b/resources/skins/default/media/hathoris-button-nofocus.png new file mode 100644 index 0000000..053a149 Binary files /dev/null and b/resources/skins/default/media/hathoris-button-nofocus.png differ diff --git a/resources/skins/default/media/hathoris-header.png b/resources/skins/default/media/hathoris-header.png new file mode 100644 index 0000000..528c66f Binary files /dev/null and b/resources/skins/default/media/hathoris-header.png differ diff --git a/resources/skins/default/media/hathoris-list-focus.png b/resources/skins/default/media/hathoris-list-focus.png new file mode 100644 index 0000000..aa7b0e6 Binary files /dev/null and b/resources/skins/default/media/hathoris-list-focus.png differ diff --git a/resources/skins/default/media/hathoris-list-nofocus.png b/resources/skins/default/media/hathoris-list-nofocus.png new file mode 100644 index 0000000..f199dd1 Binary files /dev/null and b/resources/skins/default/media/hathoris-list-nofocus.png differ diff --git a/resources/skins/default/media/hathoris-panel.png b/resources/skins/default/media/hathoris-panel.png new file mode 100644 index 0000000..e8c13eb Binary files /dev/null and b/resources/skins/default/media/hathoris-panel.png differ diff --git a/resources/skins/default/media/hathoris-radio-off.png b/resources/skins/default/media/hathoris-radio-off.png new file mode 100644 index 0000000..27760ec Binary files /dev/null and b/resources/skins/default/media/hathoris-radio-off.png differ diff --git a/resources/skins/default/media/hathoris-radio-on.png b/resources/skins/default/media/hathoris-radio-on.png new file mode 100644 index 0000000..8e451d5 Binary files /dev/null and b/resources/skins/default/media/hathoris-radio-on.png differ diff --git a/resources/skins/default/media/hathoris-slider-background.png b/resources/skins/default/media/hathoris-slider-background.png new file mode 100644 index 0000000..cbc306e Binary files /dev/null and b/resources/skins/default/media/hathoris-slider-background.png differ diff --git a/resources/skins/default/media/hathoris-slider-nib-focus.png b/resources/skins/default/media/hathoris-slider-nib-focus.png new file mode 100644 index 0000000..0bd8bab Binary files /dev/null and b/resources/skins/default/media/hathoris-slider-nib-focus.png differ diff --git a/resources/skins/default/media/hathoris-slider-nib-nofocus.png b/resources/skins/default/media/hathoris-slider-nib-nofocus.png new file mode 100644 index 0000000..aeb4597 Binary files /dev/null and b/resources/skins/default/media/hathoris-slider-nib-nofocus.png differ