-
Notifications
You must be signed in to change notification settings - Fork 28
Integration
IPTV Manager was designed with add-on developers in mind. We wanted to make it as easy as possible to integrate your existing channels and EPG information with IPTV Manager.
For this we decided that add-ons
- do not require a separate service for communication
- decide for themselves how they will get called by IPTV Manager
- map the information they already have using simple JSON formats
- can integrate with little effort and clean, simple code (see example below)
NOTE: If you like to understand why we decided to design IPTV Manager the way it works now, please read the Design wiki page for the decisions and rationale.
Add-ons can advertise supporting IPTV Manager by adding the following values to their settings.xml:
Setting | Required | Description | Example |
---|---|---|---|
iptv.enabled | yes | Opt-in on polling | true |
iptv.channels_uri | yes | Endpoint for Channel data | plugin://plugin.video.example/iptv/channels |
iptv.epg_uri | no | Endpoint for EPG data | plugin://plugin.video.example/iptv/epg |
When IPTV Manager detects that your add-on has iptv.enabled
set to true
it will query for channel and EPG
information to integrate with PVR IPTV Simple. Using the above example, IPTV Manager will call
plugin://plugin.video.example/iptv/channels?port=XYZ
and plugin://plugin.video.example/iptv/epg?port=XYZ
Due to limitations of Kodi, an Add-on cannot just return data on an RunPlugin()
or RunScript()
call,
so it needs another way to send the data back to IPTV Manager. Therefore, IPTV Manager temporary binds to
a free port on localhost
, and passes this port to the configured endpoint.
IPTV Manager will wait for a few seconds for the Add-on to call us back on the socket. If we do not get a connection back, we will consider the request to have failed and this indicates that something went wrong in the Add-on.
Since querying for EPG data could take a while, the Add-on should open the callback connection as soon as possible, so IPTV Manager does not timeout. Once the connection is opened, the Add-on can generate the EPG data and reply JSON-structured information (JSON-STREAMS format for channel listings and JSON-EPG format for EPG data) through the socket connection. IPTV Manager will wait as long as the connection is kept open.
When an exception occurs, the Add-on should not send any data and simply close the socket again. IPTV Manager will see this and knows that something went wrong and can continue.
IMPORTANT: Beware that if your add-on requires credentials in order to return the channel or EPG data, it must not show a pop-up to request for credentials. This could lead to confusing or unworkable situations where people get sudden pop-ups for credentials unrelated to what they are doing. Logging an error and closing the socket should be sufficient.
An add-on wanting to implement IPTV Manager support can use the below examples:
You could choose to enable IPTV Manager integration by default, by adding it as a requirement in your addon.xml and hidden settings in your settings.xml:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
<setting id="iptv.enabled" default="true" visible="false"/>
<setting id="iptv.channels_uri" default="plugin://plugin.video.example/iptv/channels" visible="false"/>
<setting id="iptv.epg_uri" default="plugin://plugin.video.example/iptv/epg" visible="false"/>
</settings>
Or you could integrate IPTV Manager optionally, and give the user the option to install and enable this integration:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
<category label="Integration">
<setting label="Install IPTV Manager add-on" type="action" action="InstallAddon(service.iptv.manager)" option="close" visible="!System.HasAddon(service.iptv.manager)"/>
<setting label="Enable IPTV Manager integration" type="bool" id="iptv.enabled" default="true" visible="System.HasAddon(service.iptv.manager)" />
<setting label="IPTV Manager settings…" type="action" action="Addon.OpenSettings(service.iptv.manager)" enable="eq(-1,true)" option="close" visible="System.HasAddon(service.iptv.manager)" subsetting="true"/>
<setting id="iptv.channels_uri" default="plugin://plugin.video.example/iptv/channels" visible="false"/>
<setting id="iptv.epg_uri" default="plugin://plugin.video.example/iptv/epg" visible="false"/>
</category>
</settings>
This would result in the following Integration settings category:
-
Integration
- Install IPTV Manager add-on (when not installed)
- Enable IPTV Manager integration (when installed)
- IPTV Manager settings… (when enabled)
Next you need to add some code to map internal channel and EPG data, and send it over a socket. We do this below in an IPTV Manager class:
# -*- coding: utf-8 -*-
"""IPTV Manager Integration module"""
import json
import socket
class IPTVManager:
"""Interface to IPTV Manager"""
def __init__(self, port):
"""Initialize IPTV Manager object"""
self.port = port
def via_socket(func):
"""Send the output of the wrapped function to socket"""
def send(self):
"""Decorator to send over a socket"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('127.0.0.1', self.port))
try:
sock.sendall(json.dumps(func(self)).encode())
finally:
sock.close()
return send
@via_socket
def send_channels(self):
"""Return JSON-STREAMS formatted python datastructure to IPTV Manager"""
from resources.lib.channels import CHANNELS
channels = []
for entry in CHANNELS:
channels.append(dict(
id=entry.get('id'),
name=entry.get('label'),
logo=entry.get('logo'),
stream=entry.get('url'),
))
return dict(version=1, streams=channels)
@via_socket
def send_epg(self):
"""Return JSON-EPG formatted python data structure to IPTV Manager"""
from resources.lib.tvguide import TVGuide
return dict(version=1, epg=TVGuide().get_epg_data())
NOTE: The internal data structures of the channels and EPG data are simple Python data structures, not JSON. For your convenience, the
via_socket
wrapper'ssend()
function will convert your Python data structure to JSON on-the-fly.
And finally you need to link the incoming requests to the respective routine that sends the data structure over a socket (here we use the popular routing module for this):
import routing
plugin = routing.Plugin()
@plugin.route('/iptv/channels')
def iptv_channels():
"""Return JSON-STREAMS formatted data for all live channels"""
from resources.lib.iptvmanager import IPTVManager
port = int(plugin.args.get('port')[0])
IPTVManager(port).send_channels()
@plugin.route('/iptv/epg')
def iptv_epg():
"""Return JSON-EPG formatted data for all live channel EPG data"""
from resources.lib.iptvmanager import IPTVManager
port = int(plugin.args.get('port')[0])
IPTVManager(port).send_epg()
NOTE: The above
IPTVManager
class may look a lot more complex than needed, but this is to ensure the socket is opened as quickly as possible, and the data only being sent when available. This offers a nice and clean interface that abstracts the connection-handling out of the data-fetching logic. In the future we may offer an alternative HTTP drop-in replacement.
We decided to use an actual Kodi add-on as the reference implementation. Our choice is the Red Bull TV add-on as it is an internationally known add-on, the content is open to anyone and high quality even, and people can relate to the implementation. (REST API)
The following files have been modified for IPTV Manager integration:
- resources/lib/addon.py → Maps the URL endpoint to the IPTV Manager socket request
- resources/lib/iptvmanager.py → Wraps the data structure into a TCP socket request
- resources/lib/redbull.py → Returns the actual Channels and EPG data lookup
- resources/settings.xml → Enables IPTV Manager discovery and user controls
INFO: If you like to experiment with the IPTV Manager integration, feel free to clone this add-on and add some print statements, or modify the data structures to understand how everything fits together.
For Radio integration this works exactly the same, a straightforward implementation is in the VRT Radio add-on.
If you would like to discuss the implementation or integration bits, we have an internal Slack #iptvmanager channel on the Add-ons developer organisation.
Please send your email address to @michaelarnauts or @dagwieers to get an invitation for the Add-ons developer organisation and the Slack channel.
Feel free to add to or improve this Wiki space. Questions can be asked by opening an issue.