From 0470f51bc83f628e68f7bf9d9e2543b381e9d0a3 Mon Sep 17 00:00:00 2001 From: emveepee Date: Fri, 21 Oct 2022 20:04:50 -0400 Subject: [PATCH] nextpvr: initial addon NextPVR 6.1.0 with netcore 6 with configuration --- packages/addons/service/nextpvr/changelog.txt | 2 + packages/addons/service/nextpvr/icon/icon.png | Bin 0 -> 37713 bytes packages/addons/service/nextpvr/package.mk | 28 +++ .../addons/service/nextpvr/source/addon.py | 232 ++++++++++++++++++ .../nextpvr/source/bin/nextpvr-downloader | 76 ++++++ .../service/nextpvr/source/bin/nextpvr.start | 26 ++ .../addons/service/nextpvr/source/default.py | 16 ++ .../resources/Language/English/strings.po | 142 +++++++++++ .../nextpvr/source/resources/settings.xml | 81 ++++++ .../source/system.d/service.nextpvr.service | 13 + 10 files changed, 616 insertions(+) create mode 100644 packages/addons/service/nextpvr/changelog.txt create mode 100644 packages/addons/service/nextpvr/icon/icon.png create mode 100644 packages/addons/service/nextpvr/package.mk create mode 100644 packages/addons/service/nextpvr/source/addon.py create mode 100644 packages/addons/service/nextpvr/source/bin/nextpvr-downloader create mode 100644 packages/addons/service/nextpvr/source/bin/nextpvr.start create mode 100644 packages/addons/service/nextpvr/source/default.py create mode 100644 packages/addons/service/nextpvr/source/resources/Language/English/strings.po create mode 100644 packages/addons/service/nextpvr/source/resources/settings.xml create mode 100644 packages/addons/service/nextpvr/source/system.d/service.nextpvr.service diff --git a/packages/addons/service/nextpvr/changelog.txt b/packages/addons/service/nextpvr/changelog.txt new file mode 100644 index 0000000000..fe01f1b4fe --- /dev/null +++ b/packages/addons/service/nextpvr/changelog.txt @@ -0,0 +1,2 @@ +100 +- Initial release diff --git a/packages/addons/service/nextpvr/icon/icon.png b/packages/addons/service/nextpvr/icon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ebc1f8b5212db9ebd4f44b45b1a3e3d4b2fcb360 GIT binary patch literal 37713 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 aw>IcJs_7_IFW3Tpzg)fbbJ=CrNB;$hu5va2 literal 0 HcmV?d00001 diff --git a/packages/addons/service/nextpvr/package.mk b/packages/addons/service/nextpvr/package.mk new file mode 100644 index 0000000000..c5efc7463f --- /dev/null +++ b/packages/addons/service/nextpvr/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nextpvr" +PKG_VERSION="6.1.0~Nexus" +PKG_ADDON_VERSION="6.1.0" +PKG_REV="100" +PKG_ARCH="any" +PKG_LICENSE="prop." +PKG_SITE="https://nextpvr.com" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="service" +PKG_SHORTDESC="NextPVR Server" +PKG_LONGDESC="NextPVR is a personal video recorder application. It allows to watch or record live TV, provides great features like series recordings and web scheduling." +PKG_TOOLCHAIN="manual" + +PKG_IS_ADDON="yes" +PKG_ADDON_NAME="NextPVR Server" +PKG_ADDON_TYPE="xbmc.service.library" +PKG_ADDON_REQUIRES="tools.ffmpeg-tools:0.0.0 tools.dotnet-runtime:0.0.0 script.module.requests:0.0.0" + +addon() { + : +} + +post_install_addon() { + sed -e "s/@NEXTPVR_VERSION@/${PKG_ADDON_VERSION}/g" -i "${INSTALL}/bin/nextpvr-downloader" +} diff --git a/packages/addons/service/nextpvr/source/addon.py b/packages/addons/service/nextpvr/source/addon.py new file mode 100644 index 0000000000..b1eaaad437 --- /dev/null +++ b/packages/addons/service/nextpvr/source/addon.py @@ -0,0 +1,232 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv) + +import urllib.request, urllib.parse, urllib.error, os, zipfile +from urllib.error import URLError +import urllib.parse as urlparse +import requests +import json +import subprocess + +from urllib.parse import parse_qs +import xbmc, xbmcvfs, xbmcgui, xbmcaddon +import shutil +import sys +import xml.etree.ElementTree as ET + +temp = xbmcvfs.translatePath('special://temp') + +ADDON_NAME = xbmcaddon.Addon().getAddonInfo('name') +LS = xbmcaddon.Addon().getLocalizedString + +# Ignore isbn tables +SCANTABLES = ['atsc', 'dvb-c', 'dvb-s', 'dvb-t'] +GENERIC_URL = 'https://nextpvr.com/stable/linux/NPVR.zip' + +class Controller(): + + def __init__(self): + pass + + def downloadScanTable(self): + # Taken from TVHeadend Addon + try: + url = 'https://github.com/tvheadend/dtv-scan-tables/archive/tvheadend.zip' + archive = os.path.join(temp, 'dtv_scantables.zip') + temp_folder = os.path.join(temp, 'dtv-scan-tables-tvheadend') + dest_folder = os.path.join(xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('path')), 'dtv-scan-tables') + + xbmcgui.Dialog().notification(ADDON_NAME, LS(30042), xbmcgui.NOTIFICATION_INFO) + urllib.request.urlretrieve(url, archive) + zip = zipfile.ZipFile(archive) + if zip.testzip() is not None: raise zipfile.BadZipfile + + if os.path.exists(temp_folder): shutil.rmtree(temp_folder) + if os.path.exists(dest_folder): shutil.rmtree(dest_folder) + + xbmcgui.Dialog().notification(ADDON_NAME, LS(30043), xbmcgui.NOTIFICATION_INFO) + for idx, folder in enumerate(SCANTABLES): + for z in zip.filelist: + if folder in z.filename: zip.extract(z.filename, temp) + + for folder in SCANTABLES: + shutil.copytree(os.path.join(temp_folder, folder), os.path.join(dest_folder, folder)) + + xbmcgui.Dialog().notification(ADDON_NAME, LS(30039), xbmcgui.NOTIFICATION_INFO) + except URLError as e: + xbmc.log('Could not download file: %s' % e.reason, xbmc.LOGERROR) + xbmcgui.Dialog().notification(ADDON_NAME, LS(30040), xbmcgui.NOTIFICATION_ERROR) + except zipfile.BadZipfile: + xbmc.log('Could not extract files from zip, bad zipfile', xbmc.LOGERROR) + xbmcgui.Dialog().notification(ADDON_NAME, LS(30041), xbmcgui.NOTIFICATION_ERROR) + + def updateNextPVR(self): + try: + dest_folder = os.path.join(xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('path')), 'nextpvr-bin') + archive = os.path.join(temp, 'NPVR.zip') + xbmcgui.Dialog().notification(ADDON_NAME, LS(30011), xbmcgui.NOTIFICATION_INFO) + urllib.request.urlretrieve(GENERIC_URL, archive) + xbmcgui.Dialog().notification(ADDON_NAME, LS(30012), xbmcgui.NOTIFICATION_INFO) + zip = zipfile.ZipFile(archive) + if zip.testzip() is not None: raise zipfile.BadZipfile + zip.close() + command = 'unzip -o {0} -d {1} > /dev/null'.format(archive, dest_folder) + xbmc.log('Running: %s' % command, xbmc.LOGDEBUG) + os.system(command) + os.remove(archive) + xbmcgui.Dialog().notification(ADDON_NAME, LS(30039), xbmcgui.NOTIFICATION_INFO) + xbmc.log('NPVR.zip installed', xbmc.LOGDEBUG) + if xbmcgui.Dialog().yesno("NextPVR Server", LS(30020)): + self.id = xbmcaddon.Addon().getAddonInfo('id') + subprocess.call(['systemctl', 'restart', self.id]) + + except URLError as e: + xbmc.log('Could not download file: %s' % e.reason, xbmc.LOGERROR) + xbmcgui.Dialog().notification(ADDON_NAME, LS(30040), xbmcgui.NOTIFICATION_ERROR) + except zipfile.BadZipfile: + xbmc.log('Could not extract files from zip, bad zipfile', xbmc.LOGERROR) + xbmcgui.Dialog().notification(ADDON_NAME, LS(30041), xbmcgui.NOTIFICATION_ERROR) + + def sessionLogin(self): + self.session = requests.session() + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0' + } + response = self.session.get(self.url, headers=headers) + parsed = urlparse.urlparse(response.url) + salt = parse_qs(parsed.query)['salt'][0] + if self.hashedPassword == None: + passwordHash = self.hashMe(self.password) + else: + passwordHash = self.hashedPassword + combined = self.hashMe(salt + ':' + self.username + ':' + passwordHash) + response = self.session.get(self.url + 'login.html?hash='+combined) + if response.status_code != 200 and response.status_code != 302 : + print(response.text, response.status_code) + sys.exit() + for cookie in self.session.cookies: + self.session.cookies[cookie.name] = cookie.value + + def doSessionRequest5(self, method, isJSON = True): + xbmc.log(method, xbmc.LOGDEBUG) + retval = False + getResult = None + url = self.url + 'service?method=' + method + try: + request = self.session.get(url, headers={"Accept" : "application/json"}) + getResult = json.loads(request.text) + if request.status_code == 200 : + if 'stat' in getResult: + retval = getResult['stat'] == 'ok' + else: + retval = True + else: + xbmc.log(getResult, xbmc.LOGERROR) + + except Exception as e: + xbmc.log(str(e), xbmc.LOGERROR) + + return retval, getResult + + def hashMe (self, thedata): + import hashlib + h = hashlib.md5() + h.update(thedata.encode('utf-8')) + return h.hexdigest() + + def loginNextPVR(self): + base = os.path.join(xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('profile')), 'config/config.xml') + tree = ET.parse(base) + root = tree.getroot() + child = root.find("WebServer") + self.port = child.find('Port').text + self.username = child.find('Username').text + self.hashedPIN = child.find('PinMD5').text + self.hashedPassword = child.find('Password').text.lower() + self.ip = '127.0.0.1' + self.url = 'http://{}:{}/'.format(self.ip, self.port) + self.sessionLogin() + + + def showMessage(self, message): + xbmc.log(message, xbmc.LOGDEBUG) + xbmcgui.Dialog().notification(ADDON_NAME, message, xbmcgui.NOTIFICATION_INFO) + + + def updateEpg(self): + self.loginNextPVR() + self.doSessionRequest5('system.epg.update') + self.doSessionRequest5('session.logout') + self.showMessage(LS(30015)) + + def updateM3u(self): + self.loginNextPVR() + self.doSessionRequest5('setting.m3u.update') + self.doSessionRequest5('session.logout') + self.showMessage(LS(30016)) + + def rescanDevices(self): + self.loginNextPVR() + self.doSessionRequest5('setting.devices&refresh=true') + self.doSessionRequest5('session.logout') + self.showMessage(LS(30017)) + + def transcodeHLS(self): + base = os.path.join(xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('profile')), 'config/config.xml') + tree = ET.parse(base) + parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)) + tree = ET.parse(base, parser=parser) + root = tree.getroot() + parent = root.find("WebServer") + child = parent.find('TranscodeHLS') + if child.text == 'default': + child.text = '-y [ANALYZE_DURATION] [SEEK] -i [SOURCE] -map_metadata -1 -threads [THREADS] -ignore_unknown -map 0:v:0? [PREFERRED_LANGUAGE] -map 0:a:[AUDIO_STREAM] -map -0:s -vcodec copy -acodec aac -ac 2 -c:s copy -hls_time [SEGMENT_DURATION] -start_number 0 -hls_list_size [SEGMENT_COUNT] -y [TARGET]' + else: + child.text = 'default' + tree.write(base, encoding='utf-8') + + if child.text == 'default': + self.showMessage(LS(30018)) + else: + self.showMessage(LS(30019)) + + def resetWebCredentials(self): + rewrite = False + base = os.path.join(xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('profile')), 'config/config.xml') + tree = ET.parse(base) + parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)) + tree = ET.parse(base, parser=parser) + root = tree.getroot() + parent = root.find("WebServer") + child = parent.find('Username') + if child.text != 'admin': + child.text = 'admin' + rewrite = True + child = parent.find('Password') + if child.text != '5f4dcc3b5aa765d61d8327deb882cf99': + child.text = '5f4dcc3b5aa765d61d8327deb882cf99' + rewrite = True + if rewrite: + tree.write(base, encoding='utf-8') + self.showMessage(LS(30046)) + + +if __name__ == '__main__': + option = Controller() + try: + if sys.argv[1] == 'getscantables': + option.downloadScanTable() + elif sys.argv[1] == 'updategeneric': + option.updateNextPVR() + elif sys.argv[1] == 'updateepg': + option.updateEpg() + elif sys.argv[1] == 'transcode': + option.transcodeHLS() + elif sys.argv[1] == 'updatem3u': + option.updateM3u() + elif sys.argv[1] == 'rescan': + option.rescanDevices() + elif sys.argv[1] == 'defaults': + option.resetWebCredentials() + except IndexError: + pass diff --git a/packages/addons/service/nextpvr/source/bin/nextpvr-downloader b/packages/addons/service/nextpvr/source/bin/nextpvr-downloader new file mode 100644 index 0000000000..803538469f --- /dev/null +++ b/packages/addons/service/nextpvr/source/bin/nextpvr-downloader @@ -0,0 +1,76 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +. /etc/profile +oe_setup_addon service.nextpvr + +ICON="${ADDON_DIR}/resources/icon.png" +CONTROL_FILE="/tmp/curl.nextpvr.done" +DATA_FILE="/tmp/curl.nextpvr.data" +NEXTPVR_FILE="NPVR-@NEXTPVR_VERSION@.zip" + +# check for enough free disk space +if [ $(df . | awk 'END {print $4}') -lt 400000 ]; then + kodi-send --action="Notification(Not enough disk space, at least 400MB are required,30000,${ICON})" >/dev/null + exit 0 +fi + +# remove install status and folders +if [ -f ${ADDON_DIR}/extract.ok ]; then + rm ${ADDON_DIR}/extract.ok +fi + +if [ -d ${ADDON_DIR}/nextpvr-bin ]; then + rm -rf ${ADDON_DIR}/nextpvr-bin +fi + +if [ -d ${ADDON_DIR}/tmp_download ]; then + rm -rf ${ADDON_DIR}/tmp_download +fi + +# create tmp download dir +mkdir -p ${ADDON_DIR}/tmp_download +cd ${ADDON_DIR}/tmp_download + +echo "Downloading NextPVR" + +# download NextPVR +rm -f ${CONTROL_FILE} ${DATA_FILE} +( + curl -# -O -C - https://nextpvr.com/stable/linux/${NEXTPVR_FILE} 2>${DATA_FILE} + touch ${CONTROL_FILE} +) | + while [ : ]; do + [ -f ${DATA_FILE} ] && prog="$(tr '\r' '\n' <${DATA_FILE} | tail -n 1 | sed -r 's/^[# ]+/#/;s/^[^0-9]*//g')" || prog= + kodi-send --action="Notification(Downloading NextPVR,\"${prog:-0.0%}\",3000,${ICON})" >/dev/null + [ -f ${CONTROL_FILE} ] && break + sleep 4 + done + +rm -f ${CONTROL_FILE} ${DATA_FILE} + +# check for failed download +if [ ! -f ${NEXTPVR_FILE} ]; then + kodi-send --action="Notification(Download NextPVR failed,${ICON})" + exit 1 +fi + +# extract NextPVR +kodi-send --action="Notification(Extracting NextPVR,starting,1000,${ICON})" >/dev/null +mkdir -p ${ADDON_DIR}/nextpvr-bin +unzip ${NEXTPVR_FILE} -d ${ADDON_DIR}/nextpvr-bin >/dev/null + +if [ "$(uname -m)" != "x86_64" ]; then + sed -i 's/default<\/TranscodeHLS>/-y [ANALYZE_DURATION] [SEEK] -i [SOURCE] -map_metadata -1 -threads [THREADS] -ignore_unknown -map 0:v:0? [PREFERRED_LANGUAGE] -map 0:a:[AUDIO_STREAM] -map -0:s -vcodec copy -acodec aac -ac 2 -c:s copy -hls_time [SEGMENT_DURATION] -start_number 0 -hls_list_size [SEGMENT_COUNT] -y [TARGET]<\/TranscodeHLS>/' ${ADDON_DIR}/nextpvr-bin/data/Config-master-dont-edit.xml +fi +sed -i 's/C:\\Users\\Public\\Videos\\<\/RecordingDirectory>/\/storage\/tvshows\/<\/RecordingDirectory>/' ${ADDON_DIR}/nextpvr-bin/data/Config-master-dont-edit.xml +sed -i 's/C:\\Users\\Public\\Videos\\<\/LiveTVBufferDirectory>/\/tmp\/<\/LiveTVBufferDirectory>/' ${ADDON_DIR}/nextpvr-bin/data/Config-master-dont-edit.xml +find ${ADDON_DIR}/nextpvr-bin/DeviceHost -name DeviceHostLinux -exec chmod 755 {} \; + +# cleanup +cd ${ADDON_DIR} +rm -rf ${ADDON_DIR}/tmp_download +touch ${ADDON_DIR}/extract.ok +kodi-send --action="Notification(Extracting NextPVR,finished,1000,${ICON})" >/dev/null diff --git a/packages/addons/service/nextpvr/source/bin/nextpvr.start b/packages/addons/service/nextpvr/source/bin/nextpvr.start new file mode 100644 index 0000000000..ec63d336db --- /dev/null +++ b/packages/addons/service/nextpvr/source/bin/nextpvr.start @@ -0,0 +1,26 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +. /etc/profile +oe_setup_addon service.nextpvr + +# check if nextpvr-server is already successful installed +if [ ! -f "${ADDON_DIR}/extract.ok" ]; then + cd ${ADDON_DIR} + nextpvr-downloader +fi + +export NEXTPVR_DATADIR_USERDATA=${ADDON_HOME}/config/ +export NEXTPVR_DVBDIR=${ADDON_DIR}/dtv-scan-tables/ + +export SATIP_RTSP_PORT=$satiprtsp + +read -d. uptime < /proc/uptime +startdelay=$((waitfor-uptime)) +if [ $startdelay -gt 0 ]; then + sleep $startdelay +fi + +cd ${ADDON_DIR}/nextpvr-bin +exec dotnet ${ADDON_DIR}/nextpvr-bin/NextPVRServer.dll >/dev/null diff --git a/packages/addons/service/nextpvr/source/default.py b/packages/addons/service/nextpvr/source/default.py new file mode 100644 index 0000000000..5119bb652c --- /dev/null +++ b/packages/addons/service/nextpvr/source/default.py @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +import xbmc +import xbmcaddon + +class Monitor(xbmc.Monitor): + + def __init__(self, *args, **kwargs): + xbmc.Monitor.__init__(self) + + def onSettingsChanged(self): + pass + +if __name__ == "__main__": + Monitor().waitForAbort() diff --git a/packages/addons/service/nextpvr/source/resources/Language/English/strings.po b/packages/addons/service/nextpvr/source/resources/Language/English/strings.po new file mode 100644 index 0000000000..498927074f --- /dev/null +++ b/packages/addons/service/nextpvr/source/resources/Language/English/strings.po @@ -0,0 +1,142 @@ +# Kodi Media Center language file +# Addon Name: nextpvr +# Addon id: service.nextpvr +# Addon Provider: Team LibreELEC +msgid "" +msgstr "" + +msgctxt "#30001" +msgid "Download" +msgstr "" + +msgctxt "#30002" +msgid "Download current Linux NPVR.zip" +msgstr "" + +msgctxt "#30003" +msgid "Check the NextPVR forum before updating" +msgstr "" + +msgctxt "#30004" +msgid "Manage Server" +msgstr "" + +msgctxt "#30005" +msgid "Update guide" +msgstr "" + +msgctxt "#30006" +msgid "Start an unscheduled EPG update" +msgstr "" + +msgctxt "#30007" +msgid "Update IPTV m3u source" +msgstr "" + +msgctxt "#30008" +msgid "Rescan m3u file(s) and update URLs" +msgstr "" + +msgctxt "#30009" +msgid "Toggle custom HLS transcoding with default" +msgstr "" + +msgctxt "#30010" +msgid "Change HLS transcoding mode, default will not work on all platforms" +msgstr "" + +msgctxt "#30011" +msgid "Download NPVR.zip" +msgstr "" + +msgctxt "#30012" +msgid "Extract NPVR.zip" +msgstr "" + +msgctxt "#30013" +msgid "Rescan tuning devices" +msgstr "" + +msgctxt "#30014" +msgid "Rescan for tuner changes after start-up" +msgstr "" + +msgctxt "#30015" +msgid "Update EPG started" +msgstr "" + +msgctxt "#30016" +msgid "Update m3u started" +msgstr "" + +msgctxt "#30017" +msgid "Device refresh started" +msgstr "" + +msgctxt "#30018" +msgid "Transcode set to default" +msgstr "" + +msgctxt "#30019" +msgid "Transcode set to custom" +msgstr "" + +msgctxt "#30020" +msgid "Restart server now" +msgstr "" + +msgctxt "#30037" +msgid "Install the frequency scanning table for digital devices" +msgstr "" + +msgctxt "#30038" +msgid "Download and install Scan-Tables" +msgstr "" + +msgctxt "#30039" +msgid "Download completed and installed" +msgstr "" + +msgctxt "#30040" +msgid "Could not download zip file" +msgstr "" + +msgctxt "#30041" +msgid "Could not extract zip file" +msgstr "" + +msgctxt "#30042" +msgid "Download Scan-Tables" +msgstr "" + +msgctxt "#30043" +msgid "Extract Scan-Tables" +msgstr "" + +msgctxt "#30044" +msgid "Reset web server credentials" +msgstr "" + +msgctxt "#30045" +msgid "Reset to defaults Username: admin Password: password" +msgstr "" + +msgctxt "#30046" +msgid "Set Username: admin Password: password" +msgstr "" + +msgctxt "#30047" +msgid "SAT>IP RTSP port" +msgstr "" + +msgctxt "#30048" +msgid "Default is 554 - TVHeadend uses 9983" +msgstr "" + +msgctxt "#30049" +msgid "Startup uptime wait" +msgstr "" + +msgctxt "#30050" +msgid "Delay service launch on boot to specified uptime (seconds)" +msgstr "" diff --git a/packages/addons/service/nextpvr/source/resources/settings.xml b/packages/addons/service/nextpvr/source/resources/settings.xml new file mode 100644 index 0000000000..03ad6c7d86 --- /dev/null +++ b/packages/addons/service/nextpvr/source/resources/settings.xml @@ -0,0 +1,81 @@ + + +
+ + + + 0 + RunScript(service.nextpvr, getscantables) + + false + + + + 2 + RunScript(service.nextpvr, updategeneric) + + false + + + + + + + + 1 + 5 + + 5 + 1 + 60 + + + false + + + + 1 + RunScript(service.nextpvr, updateepg) + + false + + + + 3 + RunScript(service.nextpvr, updatem3u) + + false + + + + 2 + RunScript(service.nextpvr, rescan) + + false + + + + 3 + RunScript(service.nextpvr, transcode) + + false + + + + 3 + RunScript(service.nextpvr, defaults) + + false + + + + 1 + 554 + + 30047 + + + + +
+
diff --git a/packages/addons/service/nextpvr/source/system.d/service.nextpvr.service b/packages/addons/service/nextpvr/source/system.d/service.nextpvr.service new file mode 100644 index 0000000000..3603ac3558 --- /dev/null +++ b/packages/addons/service/nextpvr/source/system.d/service.nextpvr.service @@ -0,0 +1,13 @@ +[Unit] +Description=NextPVR Server +Documentation=https://nextpvr.com +Wants=multi-user.target +After=multi-user.target + +[Service] +SyslogIdentifier=%N +ExecStart=/bin/sh /storage/.kodi/addons/%N/bin/nextpvr.start +Restart=always + +[Install] +WantedBy=multi-user.target