Merge pull request #21 from lrusak/major-rework
Cleanup add-on for building with LibreELEC
This commit is contained in:
commit
c371ff8652
|
@ -9,7 +9,7 @@ import urlparse
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from resources.moonlight import LibGameStream
|
from lib.moonlight import LibGameStream
|
||||||
|
|
||||||
base_url = sys.argv[0]
|
base_url = sys.argv[0]
|
||||||
addon_handle = int(sys.argv[1])
|
addon_handle = int(sys.argv[1])
|
||||||
|
@ -25,22 +25,22 @@ def build_url(query):
|
||||||
|
|
||||||
def index():
|
def index():
|
||||||
gs = LibGameStream(addon.getAddonInfo("path") + "/lib")
|
gs = LibGameStream(addon.getAddonInfo("path") + "/lib")
|
||||||
|
|
||||||
address = addon.getSetting("MOON_SERVER_IP")
|
address = addon.getSetting("MOON_SERVER_IP")
|
||||||
if address == "0.0.0.0":
|
if address == "0.0.0.0":
|
||||||
address = gs.discover_server()
|
address = gs.discover_server()
|
||||||
|
|
||||||
if not gs.connect_server(address, os.path.join(addon_base_path, "keys")):
|
if not gs.connect_server(address, os.path.join(addon_base_path, "keys")):
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
dialog.ok("Error", "Failed connect to server (%s)" % (address))
|
dialog.ok("Error", "Failed connect to server (%s)" % (address))
|
||||||
return
|
return
|
||||||
|
|
||||||
if not gs.isPaired():
|
if not gs.isPaired():
|
||||||
pin = "%d%d%d%d" % (random.randint(0,9), random.randint(0,9), random.randint(0,9), random.randint(0,9))
|
pin = "%d%d%d%d" % (random.randint(0,9), random.randint(0,9), random.randint(0,9), random.randint(0,9))
|
||||||
|
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
dialog.notification("PIN code", "Insert the pin code in server: %s" % pin, xbmcgui.NOTIFICATION_INFO, 10000)
|
dialog.notification("PIN code", "Insert the pin code in server: %s" % pin, xbmcgui.NOTIFICATION_INFO, 10000)
|
||||||
|
|
||||||
if gs.pair(pin):
|
if gs.pair(pin):
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
dialog.ok("Paired", "Succesfully paired")
|
dialog.ok("Paired", "Succesfully paired")
|
||||||
|
@ -48,24 +48,24 @@ def index():
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
dialog.ok("Error", "Failed to pair to server, try again")
|
dialog.ok("Error", "Failed to pair to server, try again")
|
||||||
return
|
return
|
||||||
|
|
||||||
for appId, name in gs.applist():
|
for appId, name in gs.applist():
|
||||||
base_path = os.path.join(addon_base_path, "images")
|
base_path = os.path.join(addon_base_path, "images")
|
||||||
|
|
||||||
if not os.path.exists(base_path):
|
if not os.path.exists(base_path):
|
||||||
os.makedirs(base_path)
|
os.makedirs(base_path)
|
||||||
|
|
||||||
poster_path = os.path.join(base_path, str(appId) + ".png")
|
poster_path = os.path.join(base_path, str(appId) + ".png")
|
||||||
|
|
||||||
if not os.path.isfile(poster_path):
|
if not os.path.isfile(poster_path):
|
||||||
gs.poster(appId, base_path)
|
gs.poster(appId, base_path)
|
||||||
xbmc.sleep(100)
|
xbmc.sleep(100)
|
||||||
|
|
||||||
xbmcplugin.addDirectoryItem(handle=addon_handle,
|
xbmcplugin.addDirectoryItem(handle=addon_handle,
|
||||||
url=build_url({"mode": "stream", "app": name}),
|
url=build_url({"mode": "stream", "app": name}),
|
||||||
listitem=xbmcgui.ListItem(label=name, thumbnailImage=poster_path),
|
listitem=xbmcgui.ListItem(label=name, thumbnailImage=poster_path),
|
||||||
isFolder=False)
|
isFolder=False)
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(addon_handle)
|
xbmcplugin.endOfDirectory(addon_handle)
|
||||||
|
|
||||||
def stream(app = None):
|
def stream(app = None):
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
abs_x = 0
|
|
||||||
abs_y = 1
|
|
||||||
abs_z = 2
|
|
||||||
abs_rx = 3
|
|
||||||
abs_ry = 4
|
|
||||||
abs_rz = 5
|
|
||||||
abs_deadzone = 0
|
|
||||||
abs_dpad_y = 16
|
|
||||||
abs_dpad_x = 17
|
|
||||||
reverse_x = false
|
|
||||||
reverse_y = true
|
|
||||||
reverse_rx = false
|
|
||||||
reverse_ry = true
|
|
||||||
reverse_dpad_y = false
|
|
||||||
reverse_dpad_x = false
|
|
||||||
btn_south = 304
|
|
||||||
btn_east = 305
|
|
||||||
btn_north = 307
|
|
||||||
btn_west = 308
|
|
||||||
btn_select = 314
|
|
||||||
btn_start = 315
|
|
||||||
btn_mode = 316
|
|
||||||
btn_thumbl = 317
|
|
||||||
btn_thumbr = 318
|
|
||||||
btn_tl = 310
|
|
||||||
btn_tr = 311
|
|
||||||
btn_tl2 = 312
|
|
||||||
btn_tr2 = 313
|
|
||||||
btn_dpad_up = 544
|
|
||||||
btn_dpad_down = 545
|
|
||||||
btn_dpad_left = 546
|
|
||||||
btn_dpad_right = 547
|
|
|
@ -1,32 +0,0 @@
|
||||||
abs_x = 0
|
|
||||||
abs_y = 1
|
|
||||||
abs_z = -1
|
|
||||||
abs_rx = 2
|
|
||||||
abs_ry = 3
|
|
||||||
abs_rz = -1
|
|
||||||
abs_deadzone = 0
|
|
||||||
abs_dpad_x = -1
|
|
||||||
abs_dpad_y = -1
|
|
||||||
reverse_x = false
|
|
||||||
reverse_y = false
|
|
||||||
reverse_rx = false
|
|
||||||
reverse_ry = false
|
|
||||||
reverse_dpad_x = false
|
|
||||||
reverse_dpad_y = false
|
|
||||||
btn_west = 303
|
|
||||||
btn_south = 302
|
|
||||||
btn_north = 300
|
|
||||||
btn_east = 301
|
|
||||||
btn_select = 288
|
|
||||||
btn_start = 291
|
|
||||||
btn_mode = 304
|
|
||||||
btn_thumbl = 289
|
|
||||||
btn_thumbr = 290
|
|
||||||
btn_tl = 298
|
|
||||||
btn_tr = 299
|
|
||||||
btn_tl2 = 296
|
|
||||||
btn_tr2 = 297
|
|
||||||
btn_dpad_up = 292
|
|
||||||
btn_dpad_down = 294
|
|
||||||
btn_dpad_left = 295
|
|
||||||
btn_dpad_right = 293
|
|
|
@ -1,32 +0,0 @@
|
||||||
abs_x = 0
|
|
||||||
abs_y = 1
|
|
||||||
abs_z = 48
|
|
||||||
abs_rx = 2
|
|
||||||
abs_ry = 5
|
|
||||||
abs_rz = 49
|
|
||||||
abs_deadzone = 0
|
|
||||||
abs_dpad_x = -1
|
|
||||||
abs_dpad_y = -1
|
|
||||||
reverse_x = false
|
|
||||||
reverse_y = true
|
|
||||||
reverse_rx = false
|
|
||||||
reverse_ry = true
|
|
||||||
reverse_dpad_x = false
|
|
||||||
reverse_dpad_y = false
|
|
||||||
btn_west = 303
|
|
||||||
btn_south = 302
|
|
||||||
btn_north = 300
|
|
||||||
btn_east = 301
|
|
||||||
btn_select = 288
|
|
||||||
btn_start = 291
|
|
||||||
btn_mode = 304
|
|
||||||
btn_thumbl = 289
|
|
||||||
btn_thumbr = 290
|
|
||||||
btn_tl = 298
|
|
||||||
btn_tr = 299
|
|
||||||
btn_tl2 = 296
|
|
||||||
btn_tr2 = 297
|
|
||||||
btn_dpad_up = 292
|
|
||||||
btn_dpad_down = 294
|
|
||||||
btn_dpad_left = 295
|
|
||||||
btn_dpad_right = 293
|
|
|
@ -1,32 +0,0 @@
|
||||||
abs_x = 0
|
|
||||||
abs_y = 1
|
|
||||||
abs_z = 3
|
|
||||||
abs_rx = 2
|
|
||||||
abs_ry = 5
|
|
||||||
abs_rz = 4
|
|
||||||
abs_deadzone = 0
|
|
||||||
abs_dpad_x = 16
|
|
||||||
abs_dpad_y = 17
|
|
||||||
reverse_x = false
|
|
||||||
reverse_y = true
|
|
||||||
reverse_rx = false
|
|
||||||
reverse_ry = true
|
|
||||||
reverse_dpad_x = false
|
|
||||||
reverse_dpad_y = false
|
|
||||||
btn_west = 304
|
|
||||||
btn_south = 305
|
|
||||||
btn_north = 307
|
|
||||||
btn_east = 306
|
|
||||||
btn_select = 312
|
|
||||||
btn_start = 313
|
|
||||||
btn_mode = 316
|
|
||||||
btn_thumbl = 314
|
|
||||||
btn_thumbr = 315
|
|
||||||
btn_tl = 308
|
|
||||||
btn_tr = 309
|
|
||||||
btn_tl2 = 310
|
|
||||||
btn_tr2 = 311
|
|
||||||
btn_dpad_up = -1
|
|
||||||
btn_dpad_down = -1
|
|
||||||
btn_dpad_left = -1
|
|
||||||
btn_dpad_right = -1
|
|
|
@ -1,31 +0,0 @@
|
||||||
abs_x = 0
|
|
||||||
abs_y = 1
|
|
||||||
abs_z = -1
|
|
||||||
reverse_x = false
|
|
||||||
reverse_y = true
|
|
||||||
abs_rx = 2
|
|
||||||
abs_ry = 5
|
|
||||||
abs_rz = -1
|
|
||||||
reverse_rx = false
|
|
||||||
reverse_ry = true
|
|
||||||
abs_dpad_x = 16
|
|
||||||
abs_dpad_y = 17
|
|
||||||
reverse_dpad_x = false
|
|
||||||
reverse_dpad_y = false
|
|
||||||
btn_north = 291
|
|
||||||
btn_east = 290
|
|
||||||
btn_south = 289
|
|
||||||
btn_west = 288
|
|
||||||
btn_select = 297
|
|
||||||
btn_start = 296
|
|
||||||
btn_mode = 0
|
|
||||||
btn_thumbl = 298
|
|
||||||
btn_thumbr = 299
|
|
||||||
btn_tl = 292
|
|
||||||
btn_tr = 293
|
|
||||||
btn_tl2 = 294
|
|
||||||
btn_tr2 = 295
|
|
||||||
btn_dpad_up = -1
|
|
||||||
btn_dpad_down = -1
|
|
||||||
btn_dpad_left = -1
|
|
||||||
btn_dpad_right = -1
|
|
|
@ -1,32 +0,0 @@
|
||||||
abs_x = 0
|
|
||||||
abs_y = 1
|
|
||||||
abs_z = 2
|
|
||||||
abs_rx = 3
|
|
||||||
abs_ry = 4
|
|
||||||
abs_rz = 5
|
|
||||||
abs_deadzone = 0
|
|
||||||
abs_dpad_x = 16
|
|
||||||
abs_dpad_y = 17
|
|
||||||
reverse_x = false
|
|
||||||
reverse_y = true
|
|
||||||
reverse_rx = false
|
|
||||||
reverse_ry = true
|
|
||||||
reverse_dpad_x = false
|
|
||||||
reverse_dpad_y = false
|
|
||||||
btn_east = 305
|
|
||||||
btn_south = 304
|
|
||||||
btn_north = 308
|
|
||||||
btn_west = 307
|
|
||||||
btn_select = 314
|
|
||||||
btn_start = 315
|
|
||||||
btn_mode = 316
|
|
||||||
btn_thumbl = 317
|
|
||||||
btn_thumbr = 318
|
|
||||||
btn_tl = 310
|
|
||||||
btn_tr = 311
|
|
||||||
btn_tl2 = -1
|
|
||||||
btn_tr2 = -1
|
|
||||||
btn_dpad_up = -1
|
|
||||||
btn_dpad_down = -1
|
|
||||||
btn_dpad_left = -1
|
|
||||||
btn_dpad_right = -1
|
|
Binary file not shown.
|
@ -4,18 +4,13 @@
|
||||||
|
|
||||||
oe_setup_addon script.moonlight
|
oe_setup_addon script.moonlight
|
||||||
|
|
||||||
chmod a+x $ADDON_DIR/bin/*
|
while [ 1 ]; do
|
||||||
|
if [ -f $ADDON_DIR/start_moonlight.tmp ]; then
|
||||||
|
|
||||||
while [ 1 ]
|
|
||||||
do
|
|
||||||
if [ -f $ADDON_DIR/start_moonlight.tmp ]
|
|
||||||
then
|
|
||||||
oe_setup_addon script.moonlight
|
|
||||||
|
|
||||||
MOONLIGHT_APP=`cat $ADDON_DIR/start_moonlight.tmp`
|
MOONLIGHT_APP=`cat $ADDON_DIR/start_moonlight.tmp`
|
||||||
|
|
||||||
rm $ADDON_DIR/start_moonlight.tmp
|
rm $ADDON_DIR/start_moonlight.tmp
|
||||||
|
|
||||||
MOONLIGHT_ARG="stream"
|
MOONLIGHT_ARG="stream"
|
||||||
|
|
||||||
if [ "$MOON_PACKETSIZE" != "0" ]; then
|
if [ "$MOON_PACKETSIZE" != "0" ]; then
|
||||||
|
@ -59,36 +54,34 @@ do
|
||||||
if [ "$MOON_REMOTE" = "true" ]; then
|
if [ "$MOON_REMOTE" = "true" ]; then
|
||||||
MOONLIGHT_ARG="$MOONLIGHT_ARG -remote"
|
MOONLIGHT_ARG="$MOONLIGHT_ARG -remote"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$MOON_AUDIO" != "sysdefault" ]; then
|
if [ "$MOON_AUDIO" != "sysdefault" ]; then
|
||||||
MOONLIGHT_ARG="$MOONLIGHT_ARG -audio $MOON_AUDIO"
|
MOONLIGHT_ARG="$MOONLIGHT_ARG -audio $MOON_AUDIO"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$MOON_MAPPING" != "" ]; then
|
if [ "$MOON_MAPPING" != "" ]; then
|
||||||
MOONLIGHT_ARG="$MOONLIGHT_ARG -mapping \"${ADDON_DIR}/bin/mappings/${MOON_MAPPING}.conf\""
|
MOONLIGHT_ARG="$MOONLIGHT_ARG -mapping \"${ADDON_DIR}/share/moonlight/mappings/${MOON_MAPPING}.conf\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$MOONLIGHT_APP" != "" ]; then
|
if [ "$MOONLIGHT_APP" != "" ]; then
|
||||||
MOONLIGHT_ARG="$MOONLIGHT_ARG -app \"${MOONLIGHT_APP}\""
|
MOONLIGHT_ARG="$MOONLIGHT_ARG -app \"${MOONLIGHT_APP}\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MOONLIGHT_ARG="$MOONLIGHT_ARG -keydir \"${ADDON_HOME}/keys\""
|
MOONLIGHT_ARG="$MOONLIGHT_ARG -keydir \"${ADDON_HOME}/keys\""
|
||||||
|
|
||||||
if [ "$MOON_SERVER_IP" != "0.0.0.0" ]; then
|
if [ "$MOON_SERVER_IP" != "0.0.0.0" ]; then
|
||||||
MOONLIGHT_ARG="$MOONLIGHT_ARG $MOON_SERVER_IP"
|
MOONLIGHT_ARG="$MOONLIGHT_ARG $MOON_SERVER_IP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if pgrep "kodi.bin" > /dev/null
|
if pgrep "kodi.bin" > /dev/null; then
|
||||||
then
|
|
||||||
systemctl stop kodi
|
systemctl stop kodi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
modprobe snd_bcm2835
|
modprobe snd_bcm2835 || :
|
||||||
echo $MOONLIGHT_ARG >> $ADDON_LOG_FILE
|
echo $MOONLIGHT_ARG >> $ADDON_LOG_FILE
|
||||||
/bin/sh -c "${ADDON_DIR}/bin/moonlight ${MOONLIGHT_ARG} > ${ADDON_LOG_FILE} 2>&1"
|
/bin/sh -c "${ADDON_DIR}/bin/moonlight ${MOONLIGHT_ARG} > ${ADDON_LOG_FILE} 2>&1"
|
||||||
rmmod snd_bcm2835
|
rmmod snd_bcm2835 || :
|
||||||
systemctl start kodi
|
systemctl start kodi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -38,76 +38,75 @@ class LibGameStream:
|
||||||
self.connected = False
|
self.connected = False
|
||||||
self.address = ""
|
self.address = ""
|
||||||
self.key_dir = ""
|
self.key_dir = ""
|
||||||
|
|
||||||
def discover_server(self):
|
def discover_server(self):
|
||||||
addr = ctypes.create_string_buffer('\000' * 40)
|
addr = ctypes.create_string_buffer('\000' * 40)
|
||||||
self.gslib.gs_discover_server(addr)
|
self.gslib.gs_discover_server(addr)
|
||||||
return addr.value
|
return addr.value
|
||||||
|
|
||||||
def connect_server(self, address, key_dir = ""):
|
def connect_server(self, address, key_dir = ""):
|
||||||
self.server = ctypes.pointer(SERVER_DATA(address, False, False, 0, 0))
|
self.server = ctypes.pointer(SERVER_DATA(address, False, False, 0, 0))
|
||||||
self.address = address
|
self.address = address
|
||||||
|
|
||||||
if key_dir == "":
|
if key_dir == "":
|
||||||
if "XDG_CONFIG_DIR" in os.environ:
|
if "XDG_CONFIG_DIR" in os.environ:
|
||||||
key_dir = os.path.join(os.environ["XDG_CONFIG_DIR"], "moonlight")
|
key_dir = os.path.join(os.environ["XDG_CONFIG_DIR"], "moonlight")
|
||||||
else:
|
else:
|
||||||
key_dir = os.path.join(os.environ["HOME"], ".cache", "moonlight")
|
key_dir = os.path.join(os.environ["HOME"], ".cache", "moonlight")
|
||||||
|
|
||||||
self.key_dir = key_dir
|
self.key_dir = key_dir
|
||||||
ret = self.gslib.gs_init(self.server, ctypes.c_char_p(key_dir))
|
ret = self.gslib.gs_init(self.server, ctypes.c_char_p(key_dir))
|
||||||
if ret == GS_OK:
|
if ret == GS_OK:
|
||||||
self.connected = True
|
self.connected = True
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def isPaired(self):
|
def isPaired(self):
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return self.server[0].paired
|
return self.server[0].paired
|
||||||
|
|
||||||
def applist(self):
|
def applist(self):
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
lst = []
|
lst = []
|
||||||
applst_ptr = ctypes.POINTER(APP_LIST)
|
applst_ptr = ctypes.POINTER(APP_LIST)
|
||||||
applst = applst_ptr()
|
applst = applst_ptr()
|
||||||
|
|
||||||
ret = self.gslib.gs_applist(self.server, ctypes.byref(applst))
|
ret = self.gslib.gs_applist(self.server, ctypes.byref(applst))
|
||||||
if ret != GS_OK:
|
if ret != GS_OK:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
while applst:
|
while applst:
|
||||||
lst.append((applst[0].id, applst[0].name))
|
lst.append((applst[0].id, applst[0].name))
|
||||||
applst = applst[0].next
|
applst = applst[0].next
|
||||||
|
|
||||||
return lst
|
return lst
|
||||||
|
|
||||||
def poster(self, appId, toFolder):
|
def poster(self, appId, toFolder):
|
||||||
unique_id = ""
|
unique_id = ""
|
||||||
with open(os.path.join(self.key_dir, "uniqueid.dat"), "r") as f:
|
with open(os.path.join(self.key_dir, "uniqueid.dat"), "r") as f:
|
||||||
unique_id = f.read()
|
unique_id = f.read()
|
||||||
|
|
||||||
uid = uuid4()
|
uid = uuid4()
|
||||||
url = "https://%s:47984/appasset?uniqueid=%s&uuid=%s&appid=%d&AssetType=2&AssetIdx=0" % (self.address, unique_id, str(uid), appId)
|
url = "https://%s:47984/appasset?uniqueid=%s&uuid=%s&appid=%d&AssetType=2&AssetIdx=0" % (self.address, unique_id, str(uid), appId)
|
||||||
|
|
||||||
self.gslib.http_create_data.restype = ctypes.POINTER(_HTTP_DATA)
|
self.gslib.http_create_data.restype = ctypes.POINTER(_HTTP_DATA)
|
||||||
data = self.gslib.http_create_data();
|
data = self.gslib.http_create_data();
|
||||||
self.gslib.http_request(ctypes.c_char_p(url), data)
|
self.gslib.http_request(ctypes.c_char_p(url), data)
|
||||||
|
|
||||||
barray = bytearray(data[0].memory[0:data[0].size])
|
barray = bytearray(data[0].memory[0:data[0].size])
|
||||||
|
|
||||||
with open(os.path.join(toFolder, str(appId) + ".png"), "wb") as f:
|
with open(os.path.join(toFolder, str(appId) + ".png"), "wb") as f:
|
||||||
f.write(barray)
|
f.write(barray)
|
||||||
|
|
||||||
self.gslib.http_free_data(data);
|
self.gslib.http_free_data(data);
|
||||||
|
|
||||||
def pair(self, pin):
|
def pair(self, pin):
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ret = self.gslib.gs_pair(self.server, ctypes.c_char_p(pin))
|
ret = self.gslib.gs_pair(self.server, ctypes.c_char_p(pin))
|
||||||
return ret == GS_OK
|
return ret == GS_OK
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#
|
|
|
@ -4,11 +4,11 @@ After=graphical.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=idle
|
Type=idle
|
||||||
ExecStart=/bin/sh -c "exec sh /storage/.kodi/addons/script.moonlight/bin/service.sh"
|
ExecStart=/bin/sh -c "exec sh /storage/.kodi/addons/script.moonlight/bin/moonlight.sh"
|
||||||
TimeoutStopSec=1
|
TimeoutStopSec=1
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=2
|
RestartSec=2
|
||||||
StartLimitInterval=0
|
StartLimitInterval=0
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=kodi.target
|
WantedBy=kodi.target
|
||||||
|
|
Loading…
Reference in a new issue