diff --git a/addon.py b/addon.py
index e10c23346..8b5974426 100644
--- a/addon.py
+++ b/addon.py
@@ -25,12 +25,11 @@ def router(params_string):
addon = xbmcaddon.Addon()
kodi_wrapper = kodiwrapper.KodiWrapper(_ADDON_HANDLE, _ADDON_URL, addon)
token_resolver = tokenresolver.TokenResolver(kodi_wrapper)
- stream_service = streamservice.StreamService(vrtplayer.VRTPlayer.VRT_BASE,
- vrtplayer.VRTPlayer.VRTNU_BASE_URL,
- kodi_wrapper, token_resolver)
+ stream_service = streamservice.StreamService(kodi_wrapper, token_resolver)
api_helper = vrtapihelper.VRTApiHelper(kodi_wrapper)
vrt_player = vrtplayer.VRTPlayer(addon.getAddonInfo('path'), kodi_wrapper, stream_service, api_helper)
params = dict(parse_qsl(params_string))
+ content_type = params.get('content_type')
action = params.get('action')
if action == actions.LISTING_AZ_TVSHOWS:
vrt_player.show_tvshow_menu_items(path=None)
@@ -46,12 +45,11 @@ def router(params_string):
tv_guide = tvguide.TVGuide(addon.getAddonInfo('path'), kodi_wrapper)
tv_guide.show_tvguide(params)
elif action == actions.PLAY:
- video = dict(
- video_url=params.get('video_url'),
- video_id=params.get('video_id'),
- publication_id=params.get('publication_id'),
- )
- vrt_player.play(video)
+ vrt_player.play(params)
+ elif action == actions.PLAY_RADIO:
+ vrt_player.play_radio(params)
+ elif content_type == 'audio':
+ vrt_player.show_radio_menu_items()
else:
vrt_player.show_main_menu_items()
diff --git a/addon.xml b/addon.xml
index 6c01cf51d..8fd0f9ade 100644
--- a/addon.xml
+++ b/addon.xml
@@ -15,7 +15,7 @@
- video
+ video audio
diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po
index 27fe0e3a1..6a0fa9237 100644
--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -132,36 +132,12 @@ msgid "Episode"
msgstr "Episode"
msgctxt "#32101"
-msgid "Eén live"
-msgstr "Eén live"
+msgid "%s live"
+msgstr "%s live"
msgctxt "#32102"
-msgid "Watch Eén live TV stream (via Internet)"
-msgstr "Watch Eén live TV stream (via Internet)"
-
-msgctxt "#32111"
-msgid "Canvas live"
-msgstr "Canvas live"
-
-msgctxt "#32112"
-msgid "Watch Canvas live TV stream (via Internet)"
-msgstr "Watch Canvas live TV stream (via Internet)"
-
-msgctxt "#32121"
-msgid "Ketnet live"
-msgstr "Ketnet live"
-
-msgctxt "#32122"
-msgid "Watch Ketnet live TV stream (via Internet)"
-msgstr "Watch Ketnet live TV stream (via Internet)"
-
-msgctxt "#32131"
-msgid "Sporza live"
-msgstr "Sporza live"
-
-msgctxt "#32132"
-msgid "Watch Sporza live TV stream (via Internet)"
-msgstr "Watch Sporza live TV stream via (Internet)"
+msgid "Watch %s live TV stream (via Internet)"
+msgstr "Watch %s live TV stream (via Internet)"
msgctxt "#32201"
msgid "[B][COLOR red]Geo-blocked[/COLOR][/B]\n"
diff --git a/resources/language/resource.language.nl_nl/strings.po b/resources/language/resource.language.nl_nl/strings.po
index c081e7ae8..ebec60d4b 100644
--- a/resources/language/resource.language.nl_nl/strings.po
+++ b/resources/language/resource.language.nl_nl/strings.po
@@ -133,36 +133,12 @@ msgid "Episode"
msgstr "Aflevering"
msgctxt "#32101"
-msgid "Eén live"
-msgstr "Eén live"
+msgid "%s live"
+msgstr "%s live"
msgctxt "#32102"
-msgid "Watch Eén live TV stream (via Internet)"
-msgstr "Bekijk Eén live tv stream (via Internet)"
-
-msgctxt "#32111"
-msgid "Canvas live"
-msgstr "Canvas live"
-
-msgctxt "#32112"
-msgid "Watch Canvas live TV stream (via Internet)"
-msgstr "Bekijk Canvas live tv stream (via Internet)"
-
-msgctxt "#32121"
-msgid "Ketnet live"
-msgstr "Ketnet live"
-
-msgctxt "#32122"
-msgid "Watch Ketnet live TV stream (via Internet)"
-msgstr "Bekijk Ketnet live tv stream (via Internet)"
-
-msgctxt "#32131"
-msgid "Sporza live"
-msgstr "Sporza live"
-
-msgctxt "#32132"
-msgid "Watch Sporza live TV stream (via Internet)"
-msgstr "Bekijk Sporza live tv stream (via Internet)"
+msgid "Watch %s live TV stream (via Internet)"
+msgstr "Bekijk %s live tv stream (via Internet)"
msgctxt "#32201"
msgid "[B][COLOR red]Geo-blocked[/COLOR][/B]\n"
diff --git a/resources/lib/kodiwrappers/kodiwrapper.py b/resources/lib/kodiwrappers/kodiwrapper.py
index 1f736fa20..8b213d041 100644
--- a/resources/lib/kodiwrappers/kodiwrapper.py
+++ b/resources/lib/kodiwrappers/kodiwrapper.py
@@ -50,7 +50,7 @@ def __init__(self, handle, url, addon):
self._addon = addon
self._addon_id = addon.getAddonInfo('id')
- def show_listing(self, list_items, sort='unsorted', ascending=True, content_type='episodes', cache=True):
+ def show_listing(self, list_items, sort='unsorted', ascending=True, content_type='episodes', list_type='video', cache=True):
listing = []
xbmcplugin.setContent(self._handle, content=content_type)
@@ -90,7 +90,7 @@ def show_listing(self, list_items, sort='unsorted', ascending=True, content_type
list_item.setArt(title_item.art_dict)
if title_item.video_dict:
- list_item.setInfo('video', infoLabels=title_item.video_dict)
+ list_item.setInfo(type=list_type, infoLabels=title_item.video_dict)
listing.append((url, list_item, not title_item.is_playable))
@@ -121,6 +121,13 @@ def play(self, video):
xbmc.sleep(100)
xbmc.Player().showSubtitles(subtitles_visible)
+ def play_radio(self, stream):
+ xbmc.Player().play(stream)
+ play_item = xbmcgui.ListItem(path=stream)
+ xbmcplugin.setResolvedUrl(self._handle, True, listitem=play_item)
+ while not xbmc.Player().isPlaying() and not xbmc.Monitor().abortRequested():
+ xbmc.sleep(100)
+
def show_ok_dialog(self, title, message):
xbmcgui.Dialog().ok(self._addon.getAddonInfo('name'), title, message)
diff --git a/resources/lib/vrtplayer/__init__.py b/resources/lib/vrtplayer/__init__.py
index e69de29bb..db4d2b72e 100644
--- a/resources/lib/vrtplayer/__init__.py
+++ b/resources/lib/vrtplayer/__init__.py
@@ -0,0 +1,215 @@
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, unicode_literals
+
+# Fallback list of categories so we don't depend on web scraping only
+CATEGORIES = [
+ dict(name='Audiodescriptie', id='met-audiodescriptie'),
+ dict(name='Cultuur', id='cultuur'),
+ dict(name='Docu', id='docu'),
+ dict(name='Entertainment', id='entertainment'),
+ dict(name='Films', id='films'),
+ dict(name='Human interest', id='human-interest'),
+ dict(name='Humor', id='humor'),
+ dict(name='Kinderen', id='voor-kinderen'),
+ dict(name='Koken', id='koken'),
+ dict(name='Lifestyle', id='lifestyle'),
+ dict(name='Muziek', id='muziek'),
+ dict(name='Nieuws en actua', id='nieuws-en-actua'),
+ dict(name='Series', id='series'),
+ dict(name='Sport', id='sport'),
+ dict(name='Talkshows', id='talkshows'),
+ dict(name='Vlaamse Gebarentaal', id='met-gebarentaal'),
+ dict(name='Wetenschap en natuur', id='wetenschap-en-natuur'),
+]
+
+CHANNELS = {
+ 'een': dict(
+ id='O8',
+ type='tv',
+ name='Eén',
+ tagline='',
+ studio='Een',
+ website='https://een.be/',
+ live_stream='https://www.vrt.be/vrtnu/kanalen/een/',
+
+ ),
+ 'canvas': dict(
+ id='1H',
+ type='tv',
+ name='Canvas',
+ tagline='',
+ studio='Canvas',
+ website='https://canvas.be/',
+ live_stream='https://www.vrt.be/vrtnu/kanalen/canvas/',
+ ),
+ 'ketnet': dict(
+ id='O9',
+ type='tv',
+ name='Ketnet',
+ tagline='',
+ studio='Ketnet',
+ website='https://ketnet.be/',
+ live_stream='https://www.vrt.be/vrtnu/kanalen/ketnet/',
+ ),
+ 'ketnet-jr': dict(
+ id='1H',
+ type='tv',
+ name='Ketnet Junior',
+ tagline='',
+ studio='Ketnet Junior',
+ website='https://ketnet.be/',
+ ),
+ 'radio1': dict(
+ id='11',
+ type='radio',
+ name='Radio 1',
+ tagline='Altijd Benieuwd',
+ studio='Radio 1',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/47303075-8243-434b-8199-2e62cf4dd97a/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/47303075-8243-434b-8199-2e62cf4dd97a/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/radio1-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/radio1-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/radio1.aac',
+ ),
+ 'radio2': dict(
+ id='24',
+ type='radio',
+ name='Radio 2',
+ tagline='De grootste familie',
+ studio='Radio 2',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/93a8a402-9008-4a97-b473-bc107be7524d/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/93a8a402-9008-4a97-b473-bc107be7524d/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/ra2ovl-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/ra2ovl-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/ra2ovl.aac',
+ ),
+ 'klara': dict(
+ id='31',
+ type='radio',
+ tagline='Blijf verwonderd',
+ name='Klara',
+ studio='Klara',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/a9f36fda-cb3c-4b4e-9405-a5bba55654c0/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/a9f36fda-cb3c-4b4e-9405-a5bba55654c0/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/klara-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/klara-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/klara.aac',
+ ),
+ 'klara-continuo': dict(
+ id='32',
+ type='radio',
+ tagline='Non-stop klassieke muziek',
+ name='Klara Continuo',
+ studio='Klara Continuo',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/0d06dbbe-92d4-4cfe-a0b3-ccc6b7a32ec4/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/0d06dbbe-92d4-4cfe-a0b3-ccc6b7a32ec4/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/klaracontinuo-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/klaracontinuo-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/klaracontinuo.aac',
+ ),
+ 'stubru': dict(
+ id='41',
+ type='radio',
+ name='Studio Brussel',
+ tagline='Life is Music',
+ studio='Studio Brussel',
+ website='https://stubru.be/',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/f404f0f3-3917-40fd-80b6-a152761072fe/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/f404f0f3-3917-40fd-80b6-a152761072fe/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/stubru-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/stubru-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/stubru.aac',
+ ),
+ 'de-tijdloze': dict(
+ id='44',
+ type='radio',
+ name='De Tijdloze',
+ tagline='Altijd en overal de beste Tijdloze muziek',
+ studio='Studio Brussel',
+ website='https://stubru.be/',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/582109ca-1e71-4330-93fc-e9affee94d7d/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/582109ca-1e71-4330-93fc-e9affee94d7d/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/stubru_tijdloze-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/stubru_tijdloze-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/stubru_tijdloze.aac',
+ ),
+ 'mnm': dict(
+ id='55',
+ type='radio',
+ name='MNM',
+ tagline='Music and More',
+ studio='MNM',
+ website='https://mnm.be/',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/68dc3b80-040e-4a75-a394-72f3bb7aff9a/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/68dc3b80-040e-4a75-a394-72f3bb7aff9a/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/mnm-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/mnm-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/mnm.aac',
+ ),
+ 'mnm-hits': dict(
+ id='56',
+ type='radio',
+ name='MNM Hits',
+ tagline='Music and More - The Hits',
+ studio='MNM',
+ website='http://mnm.be/',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/35dd91de-0352-4865-8632-17e5af8dc6ba/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/35dd91de-0352-4865-8632-17e5af8dc6ba/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/mnm_hits-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/mnm_hits-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/mnm_hits.aac',
+ ),
+ 'mnm-urbanice': dict(
+ id='57',
+ type='radio',
+ name='MNM UrbaNice',
+ tagline='De Online Urban Stream van MNM',
+ studio='MNM',
+ website='https://mnm.be/',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/da0b681c-73db-4c9e-af32-7921591d3fbd/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/da0b681c-73db-4c9e-af32-7921591d3fbd/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/mnm_urb-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/mnm_urb-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/mnm_urb.aac',
+ ),
+ 'ketnet-hits': dict(
+ id='O3',
+ type='radio',
+ name='Ketnet Hits',
+ tagline='De hipste, de coolste én de plezantste hits op een rijtje',
+ studio='Ketnet',
+ website='https://ketnet.be/',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/014a9eea-af85-4da6-aab2-c472ca8d0149/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/014a9eea-af85-4da6-aab2-c472ca8d0149/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/ketnetradio-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/ketnetradio-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/ketnetradio.aac',
+ ),
+ 'vrtnws': dict(
+ id='13',
+ type='radio',
+ name='VRT NWS',
+ tagline='Ieder moment het meest recente nieuws',
+ studio='VRT NWS',
+ website='https://www.vrtnieuws.be/',
+ hls_128='https://ondemand-radio-cf-vrt.akamaized.net/audioonly/content/fixed/11_11niws-snip_hi.mp4/.m3u8',
+ mpeg_dash_128='https://ondemand-radio-cf-vrt.akamaized.net/audioonly/content/fixed/11_11niws-snip_hi.mp4/.mpd',
+ mp3_128='https://progressive-audio.lwc.vrtcdn.be/content/fixed/11_11niws-snip_hi.mp3',
+ ),
+ 'vrt-event': dict(
+ id='71',
+ type='radio',
+ name='VRT Event',
+ tagline='',
+ studio='VRT',
+ website='https://vrt.be/',
+ hls_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/779d53fc-9472-4fe8-b62a-1d38c5878c60/live.isml/.m3u8',
+ mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupa/live/779d53fc-9472-4fe8-b62a-1d38c5878c60/live.isml/.mpd',
+ mp3_128='http://icecast.vrtcdn.be/vrtevent-high.mp3',
+ mp3_64='http://icecast.vrtcdn.be/vrtevent-mid.mp3',
+ aac_128='http://icecast.vrtcdn.be/vrtevent.aac',
+ ),
+}
diff --git a/resources/lib/vrtplayer/actions.py b/resources/lib/vrtplayer/actions.py
index 96ec0ee99..84ba3b5a3 100644
--- a/resources/lib/vrtplayer/actions.py
+++ b/resources/lib/vrtplayer/actions.py
@@ -14,3 +14,4 @@
LISTING_TVGUIDE = 'listingtvguide'
PLAY = 'play'
+PLAY_RADIO = 'play_radio'
diff --git a/resources/lib/vrtplayer/metadatacreator.py b/resources/lib/vrtplayer/metadatacreator.py
index 05e1c8c4c..da746f0ca 100644
--- a/resources/lib/vrtplayer/metadatacreator.py
+++ b/resources/lib/vrtplayer/metadatacreator.py
@@ -6,6 +6,8 @@
from datetime import datetime
import dateutil.tz
+from resources.lib.vrtplayer import CHANNELS
+
class MetadataCreator:
@@ -160,8 +162,9 @@ def get_video_dict(self):
video_dict = dict()
if self.brands:
- video_dict['studio'] = self.brands
-# video_dict['channelname'] = self.brands[0] if isinstance(self.brands, list) else self.brands
+ video_dict['studio'] = CHANNELS.get(self.brands[0], {'studio': 'VRT'}).get('studio')
+ else:
+ video_dict['studio'] = 'VRT'
if self.datetime:
video_dict['aired'] = self.datetime.strftime('%Y-%m-%d %H:%M:%S')
diff --git a/resources/lib/vrtplayer/streamservice.py b/resources/lib/vrtplayer/streamservice.py
index 09525b64b..fcdd65cf2 100644
--- a/resources/lib/vrtplayer/streamservice.py
+++ b/resources/lib/vrtplayer/streamservice.py
@@ -23,12 +23,10 @@ class StreamService:
_VUALTO_API_URL = 'https://media-services-public.vrt.be/vualto-video-aggregator-web/rest/external/v1'
_CLIENT = 'vrtvideo'
- def __init__(self, vrt_base, vrtnu_base_url, kodi_wrapper, token_resolver):
+ def __init__(self, kodi_wrapper, token_resolver):
self._kodi_wrapper = kodi_wrapper
self._proxies = self._kodi_wrapper.get_proxies()
self.token_resolver = token_resolver
- self._vrt_base = vrt_base
- self._vrtnu_base_url = vrtnu_base_url
self._create_settings_dir()
self._can_play_drm = self._kodi_wrapper.can_play_drm()
self._license_url = None
diff --git a/resources/lib/vrtplayer/tvguide.py b/resources/lib/vrtplayer/tvguide.py
index 91f809df7..9925cf1dd 100644
--- a/resources/lib/vrtplayer/tvguide.py
+++ b/resources/lib/vrtplayer/tvguide.py
@@ -10,22 +10,7 @@
import requests
from resources.lib.helperobjects import helperobjects
-from resources.lib.vrtplayer import actions, metadatacreator, statichelper
-
-CHANNELS = dict(
- een=dict(
- id='O8',
- name='Eén',
- ),
- canvas=dict(
- id='1H',
- name='Canvas',
- ),
- ketnet=dict(
- id='O9',
- name='Ketnet',
- ),
-)
+from resources.lib.vrtplayer import CHANNELS, actions, metadatacreator, statichelper
DATE_STRINGS = {
'-2': 32330, # 2 days ago
@@ -82,7 +67,7 @@ def show_tvguide(self, params):
url_dict=dict(action=actions.LISTING_TVGUIDE, date=date, channel=channel),
is_playable=False,
art_dict=dict(thumb=self.__get_media(channel + '.png'), icon='DefaultAddonPVRClient.png', fanart='DefaultAddonPVRClient.png'),
- video_dict=dict(plot=plot),
+ video_dict=dict(plot=plot, studio=CHANNELS[channel]['studio']),
),
)
self._kodi_wrapper.show_listing(channel_items, content_type='files')
diff --git a/resources/lib/vrtplayer/vrtapihelper.py b/resources/lib/vrtplayer/vrtapihelper.py
index f2ab1b9c1..ce5d7ede7 100644
--- a/resources/lib/vrtplayer/vrtapihelper.py
+++ b/resources/lib/vrtplayer/vrtapihelper.py
@@ -20,10 +20,9 @@
class VRTApiHelper:
_VRT_BASE = 'https://www.vrt.be'
- _VRTNU_API_BASE = 'https://vrtnu-api.vrt.be'
- _VRTNU_SEARCH_URL = _VRTNU_API_BASE + '/search'
- _VRTNU_SUGGEST_URL = _VRTNU_API_BASE + '/suggest'
- _VRTNU_SCREENSHOT_URL = _VRTNU_API_BASE + '/screenshots'
+ _VRTNU_SEARCH_URL = 'https://vrtnu-api.vrt.be/search'
+ _VRTNU_SUGGEST_URL = 'https://vrtnu-api.vrt.be/suggest'
+ _VRTNU_SCREENSHOT_URL = 'https://vrtnu-api.vrt.be/screenshots'
def __init__(self, kodi_wrapper):
self._kodi_wrapper = kodi_wrapper
diff --git a/resources/lib/vrtplayer/vrtplayer.py b/resources/lib/vrtplayer/vrtplayer.py
index d8b6e56f3..4463b1d63 100644
--- a/resources/lib/vrtplayer/vrtplayer.py
+++ b/resources/lib/vrtplayer/vrtplayer.py
@@ -8,18 +8,38 @@
import requests
from resources.lib.helperobjects import helperobjects
-from resources.lib.vrtplayer import actions, statichelper
+from resources.lib.vrtplayer import CATEGORIES, CHANNELS, actions, statichelper
-class VRTPlayer:
+def get_categories(proxies=None):
+ response = requests.get('https://www.vrt.be/vrtnu/categorieen/', proxies=proxies)
+ tiles = SoupStrainer('a', {'class': 'nui-tile'})
+ soup = BeautifulSoup(response.content, 'html.parser', parse_only=tiles)
+
+ categories = []
+ for tile in soup.find_all(class_='nui-tile'):
+ categories.append(dict(
+ id=tile.get('href').split('/')[-2],
+ thumbnail=get_category_thumbnail(tile),
+ name=get_category_title(tile),
+ ))
+
+ return categories
+
+
+def get_category_thumbnail(element):
+ raw_thumbnail = element.find(class_='media').get('data-responsive-image', 'DefaultGenre.png')
+ return statichelper.add_https_method(raw_thumbnail)
+
- # URLs van https://services.vrt.be/videoplayer/r/live.json
- _EEN_LIVESTREAM = 'https://www.vrt.be/vrtnu/kanalen/een/'
- _CANVAS_LIVESTREAM = 'https://www.vrt.be/vrtnu/kanalen/canvas/'
- _KETNET_LIVESTREAM = 'https://www.vrt.be/vrtnu/kanalen/ketnet/'
+def get_category_title(element):
+ found_element = element.find('h3')
+ if found_element is not None:
+ return statichelper.strip_newlines(found_element.contents[0])
+ return ''
- VRT_BASE = 'https://www.vrt.be/'
- VRTNU_BASE_URL = VRT_BASE + '/vrtnu'
+
+class VRTPlayer:
def __init__(self, addon_path, kodi_wrapper, stream_service, api_helper):
self._addon_path = addon_path
@@ -63,77 +83,83 @@ def show_tvshow_menu_items(self, path):
self._kodi_wrapper.show_listing(tvshow_items, sort='label', content_type='tvshows')
def show_category_menu_items(self):
- joined_url = self.VRTNU_BASE_URL + '/categorieen/'
- category_items = self.__get_category_menu_items(joined_url, {'class': 'nui-tile'}, actions.LISTING_CATEGORY_TVSHOWS)
+ category_items = self.__get_category_menu_items()
self._kodi_wrapper.show_listing(category_items, sort='label', content_type='files')
- def play(self, video):
- stream = self._stream_service.get_stream(video)
- if stream is not None:
- self._kodi_wrapper.play(stream)
-
def show_livestream_items(self):
- livestream_items = [
- helperobjects.TitleItem(
- title=self._kodi_wrapper.get_localized_string(32101),
- url_dict=dict(action=actions.PLAY, video_url=self._EEN_LIVESTREAM),
+ livestream_items = []
+ for channel in ['een', 'canvas', 'ketnet']:
+ livestream_items.append(helperobjects.TitleItem(
+ title=self._kodi_wrapper.get_localized_string(32101) % CHANNELS[channel]['name'],
+ url_dict=dict(action=actions.PLAY, video_url=CHANNELS[channel]['live_stream']),
is_playable=True,
- art_dict=dict(thumb=self.__get_media('een.png'), icon='DefaultAddonPVRClient.png', fanart=self._api_helper.get_live_screenshot('een')),
- video_dict=dict(plot=self._kodi_wrapper.get_localized_string(32201) + '\n' + self._kodi_wrapper.get_localized_string(32102)),
- ),
- helperobjects.TitleItem(
- title=self._kodi_wrapper.get_localized_string(32111),
- url_dict=dict(action=actions.PLAY, video_url=self._CANVAS_LIVESTREAM),
+ art_dict=dict(thumb=self.__get_media(channel + '.png'), icon='DefaultAddonPVRClient.png', fanart=self._api_helper.get_live_screenshot(channel)),
+ video_dict=dict(
+ title=self._kodi_wrapper.get_localized_string(32101) % CHANNELS[channel]['name'],
+ plot=self._kodi_wrapper.get_localized_string(32201) + '\n' + self._kodi_wrapper.get_localized_string(32102) % CHANNELS[channel]['name'],
+ studio=CHANNELS[channel]['studio'],
+ mediatype='video',
+ ),
+ ))
+
+ self._kodi_wrapper.show_listing(livestream_items, sort='unsorted', content_type='videos')
+
+ def show_radio_menu_items(self):
+ radio_items = []
+ for channel in CHANNELS:
+ if CHANNELS[channel]['type'] != 'radio':
+ continue
+ radio_items.append(helperobjects.TitleItem(
+ title=CHANNELS[channel]['name'],
+ url_dict=dict(action=actions.PLAY_RADIO, radio_stream=CHANNELS[channel]['hls_128']),
is_playable=True,
- art_dict=dict(thumb=self.__get_media('canvas.png'), icon='DefaultAddonPVRClient.png', fanart=self._api_helper.get_live_screenshot('canvas')),
- video_dict=dict(plot=self._kodi_wrapper.get_localized_string(32201) + '\n' + self._kodi_wrapper.get_localized_string(32112)),
- ),
- helperobjects.TitleItem(
- title=self._kodi_wrapper.get_localized_string(32121),
- url_dict=dict(action=actions.PLAY, video_url=self._KETNET_LIVESTREAM),
- is_playable=True,
- art_dict=dict(thumb=self.__get_media('ketnet.png'), icon='DefaultAddonPVRClient.png', fanart=self._api_helper.get_live_screenshot('ketnet')),
- video_dict=dict(plot=self._kodi_wrapper.get_localized_string(32201) + '\n' + self._kodi_wrapper.get_localized_string(32122)),
- ),
- ]
- self._kodi_wrapper.show_listing(livestream_items, content_type='videos')
+ art_dict=dict(thumb='DefaultAddonMusic.png', icon='DefaultAddonMusic.png', fanart='DefaultAddonMusic.png'),
+ video_dict=dict(
+ title=CHANNELS[channel]['name'],
+ tagline=CHANNELS[channel]['tagline'],
+ plot=self._kodi_wrapper.get_localized_string(32102) % CHANNELS[channel]['name'],
+ studio=CHANNELS[channel]['studio'],
+ mediatype='music',
+ ),
+ ))
+
+ self._kodi_wrapper.show_listing(radio_items, sort='label', content_type='music', list_type='video')
def show_episodes(self, path):
episode_items, sort, ascending = self._api_helper.get_episode_items(path)
self._kodi_wrapper.show_listing(episode_items, sort=sort, ascending=ascending, content_type='episodes', cache=False)
+ def play(self, params):
+ stream = self._stream_service.get_stream(params)
+ if stream is not None:
+ self._kodi_wrapper.play(stream)
+
+ def play_radio(self, params):
+ if 'channel' in params:
+ stream = CHANNELS[params.get('channel')]['hls_128']
+ else:
+ stream = params.get('radio_stream')
+ self._kodi_wrapper.play_radio(stream)
+
def __get_media(self, file_name):
return os.path.join(self._addon_path, 'resources', 'media', file_name)
- def __get_category_menu_items(self, url, soupstrainer_parser_selector, routing_action, video_dict_action=None):
- response = requests.get(url, proxies=self._proxies)
- tiles = SoupStrainer('a', soupstrainer_parser_selector)
- soup = BeautifulSoup(response.content, 'html.parser', parse_only=tiles)
+ def __get_category_menu_items(self):
+ try:
+ categories = get_categories(self._proxies)
+ except Exception:
+ categories = CATEGORIES
+
+ if not categories:
+ categories = CATEGORIES
+
listing = []
- for tile in soup.find_all(class_='nui-tile'):
- category = tile.get('href').split('/')[-2]
- thumbnail, title = self.__get_category_thumbnail_and_title(tile)
- video_dict = None
- if video_dict_action is not None:
- video_dict = video_dict_action(tile)
-
- listing.append(helperobjects.TitleItem(title=title,
- url_dict=dict(action=routing_action, video_url=category),
+ for category in categories:
+ thumbnail = category.get('thumbnail', 'DefaultGenre.png')
+ listing.append(helperobjects.TitleItem(title=category['name'],
+ url_dict=dict(action=actions.LISTING_CATEGORY_TVSHOWS, video_url=category['id']),
is_playable=False,
art_dict=dict(thumb=thumbnail, icon='DefaultGenre.png', fanart=thumbnail),
- video_dict=video_dict))
- return listing
+ video_dict=None))
- @staticmethod
- def __format_category_image_url(element):
- raw_thumbnail = element.find(class_='media').get('data-responsive-image', 'DefaultGenre.png')
- return statichelper.add_https_method(raw_thumbnail)
-
- @staticmethod
- def __get_category_thumbnail_and_title(element):
- thumbnail = VRTPlayer.__format_category_image_url(element)
- found_element = element.find('h3')
- title = ''
- if found_element is not None:
- title = statichelper.strip_newlines(found_element.contents[0])
- return thumbnail, title
+ return listing
diff --git a/test/vrtplayertests.py b/test/vrtplayertests.py
index 0a8781819..9c402f5cc 100644
--- a/test/vrtplayertests.py
+++ b/test/vrtplayertests.py
@@ -5,7 +5,8 @@
from __future__ import absolute_import, division, unicode_literals
import mock
import unittest
-from resources.lib.vrtplayer import vrtapihelper, vrtplayer
+
+from resources.lib.vrtplayer import CATEGORIES, vrtapihelper, vrtplayer
class TestVRTPlayer(unittest.TestCase):
@@ -34,6 +35,12 @@ def test_show_videos_specific_seasons_shows_videos(self):
player.show_episodes('/vrtnu/a-z/thuis/24.lists.all-episodes.relevant/')
self.assertTrue(self._kodi_wrapper.show_listing.called)
+ def test_categories_scraping(self):
+ ''' Test to ensure our hardcoded categories conforms to scraped categories '''
+ # Remove thumbnails from scraped categories first
+ categories = [dict(id=c['id'], name=c['name']) for c in vrtplayer.get_categories()]
+ self.assertTrue(categories == CATEGORIES)
+
if __name__ == '__main__':
unittest.main()