Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Radio support #162

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def router(params_string):
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)
Expand All @@ -45,6 +46,10 @@ def router(params_string):
tv_guide.show_tvguide(params)
elif action == actions.PLAY:
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()

Expand Down
2 changes: 1 addition & 1 deletion addon.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</requires>

<extension point="xbmc.python.pluginsource" library="addon.py">
<provides>video</provides>
<provides>video audio</provides>
</extension>
<extension point="xbmc.service" library="service.py"/>
<extension point="xbmc.addon.metadata">
Expand Down
15 changes: 13 additions & 2 deletions resources/lib/kodiwrappers/kodiwrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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(type='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))

Expand Down Expand Up @@ -121,6 +121,17 @@ def play(self, video):
xbmc.sleep(100)
xbmc.Player().showSubtitles(subtitles_visible)

def play_radio(self, stream):
play_item = xbmcgui.ListItem(path=stream)
if stream.endswith('.mpd'):
play_item.setProperty('inputstreamaddon', 'inputstream.adaptive')
play_item.setProperty('inputstream.adaptive.manifest_type', 'mpd')
play_item.setMimeType('application/dash+xml')
play_item.setContentLookup(False)
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)

Expand Down
188 changes: 187 additions & 1 deletion resources/lib/vrtplayer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,38 +30,54 @@
id='O8',
type='tv',
name='Eén',
tagline='',
studio='Een',
website='https://een.be/',
live_stream='https://www.vrt.be/vrtnu/kanalen/een/',
live_stream_id='vualto_een_geo',
),
'canvas': dict(
id='1H',
type='tv',
name='Canvas',
tagline='',
studio='Canvas',
website='https://canvas.be/',
live_stream='https://www.vrt.be/vrtnu/kanalen/canvas/',
live_stream_id='vualto_canvas_geo',
),
'ketnet': dict(
id='O9',
type='tv',
name='Ketnet',
tagline='',
studio='Ketnet',
website='https://ketnet.be/',
live_stream='https://www.vrt.be/vrtnu/kanalen/ketnet/',
live_stream_id='vualto_ketnet_geo',
),
'ketnet-jr': dict(
id='1H',
type='tv',
name='Ketnet Junior',
tagline='',
studio='Ketnet Junior',
website='https://ketnet.be/',
),
'sporza': dict(
id='12',
type='radio+tv',
name='Sporza',
tagline='Kristalheldere sportverslaggeving',
studio='Sporza',
live_stream_id='vualto_sporza_geo',
website='https://sporza.be/',
live_stream='https://live-aka.vrtcdn.be/groupa/live/bf2f7c79-1d77-4cdc-80e8-47ae024f30ba/live.isml/.mpd',
hls_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/a1211b31-541b-43ce-b6e2-489d9a8995ad/live.isml/.m3u8',
mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/a1211b31-541b-43ce-b6e2-489d9a8995ad/live.isml/.mpd',
mp3_128='http://icecast.vrtcdn.be/sporza-high.mp3',
mp3_64='http://icecast.vrtcdn.be/sporza-mid.mp3',
aac_128='http://icecast.vrtcdn.be/sporza.aac',
),
'vrtnxt': dict(
id='',
Expand All @@ -73,42 +89,212 @@
id='11',
type='radio',
name='Radio 1',
tagline='Altijd Benieuwd',
studio='Radio 1',
website='https://radio1.be/',
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-antwerpen': dict(
id='21',
type='radio',
name='Radio 2 Antwerpen',
tagline='De grootste familie',
studio='Radio 2',
website='https://radio2.be/',
hls_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/033d312d-31f7-400a-b81a-61195f0b79c5/live.isml/.m3u8',
mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/033d312d-31f7-400a-b81a-61195f0b79c5/live.isml/.mpd',
mp3_128='http://icecast.vrtcdn.be/ra2ant-high.mp3',
mp3_64='http://icecast.vrtcdn.be/ra2ant-mid.mp3',
aac_128='http://icecast.vrtcdn.be/ra2ant.aac',
),
'radio2-vlaams-brabant': dict(
id='22',
type='radio',
name='Radio 2 Vlaams-Brabant',
tagline='De grootste familie',
studio='Radio 2',
website='https://radio2.be/',
hls_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/1e08f370-1f20-4807-aaa3-051c7f0d8359/live.isml/.m3u8',
mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/1e08f370-1f20-4807-aaa3-051c7f0d8359/live.isml/.mpd',
mp3_128='http://icecast.vrtcdn.be/ra2vlb-high.mp3',
mp3_64='http://icecast.vrtcdn.be/ra2vlb-mid.mp3',
aac_128='http://icecast.vrtcdn.be/ra2vlb.aac',
),
'radio2-limburg': dict(
id='23',
type='radio',
name='Radio 2 Limburg',
tagline='De grootste familie',
studio='Radio 2',
website='https://radio2.be/',
hls_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/d9c49923-b49f-4ab3-8532-4e9bd850b4e2/live.isml/.m3u8',
mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupb/live/d9c49923-b49f-4ab3-8532-4e9bd850b4e2/live.isml/.mpd',
mp3_128='http://icecast.vrtcdn.be/ra2lim-high.mp3',
mp3_64='http://icecast.vrtcdn.be/ra2lim-mid.mp3',
aac_128='http://icecast.vrtcdn.be/ra2lim.aac',
),
'radio2': dict(
id='24',
type='radio',
name='Radio 2',
name='Radio 2 Oost-Vlaanderen',
tagline='De grootste familie',
studio='Radio 2',
website='https://radio2.be/',
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',
),
'radio2-west-vlaanderen': dict(
id='25',
type='radio',
name='Radio 2 West-Vlaanderen',
tagline='De grootste familie',
studio='Radio 2',
website='https://radio2.be/',
hls_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/604e4a0e-22e8-4f99-ad5e-4f62d27dfec4/live.isml/.m3u8',
mpeg_dash_128='https://live-radio-cf-vrt.akamaized.net/groupc/live/604e4a0e-22e8-4f99-ad5e-4f62d27dfec4/live.isml/.mpd',
mp3_128='http://icecast.vrtcdn.be/ra2wvl-high.mp3',
mp3_64='http://icecast.vrtcdn.be/ra2wvl-mid.mp3',
aac_128='http://icecast.vrtcdn.be/ra2wvl.aac',
),
'klara': dict(
id='31',
type='radio',
tagline='Blijf verwonderd',
name='Klara',
studio='Klara',
website='https://klara.be/',
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',
website='https://klara.be/',
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+tv',
name='Studio Brussel',
tagline='Life is Music',
studio='Studio Brussel',
website='https://stubru.be/',
# live_stream='https://stubru.be/live',
live_stream_id='vualto_stubru',
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',
),
'stubru-tijdloze': dict(
id='44',
type='radio',
name='Studio Brussel, 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+tv',
name='MNM',
tagline='Music and More',
studio='MNM',
website='https://mnm.be/',
# live_stream='https://mnm.be/kijk/live',
live_stream_id='vualto_mnm',
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='https://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+tv',
name='VRT NWS',
tagline='Ieder moment het meest recente nieuws',
studio='VRT NWS',
live_stream_id='vualto_nieuws',
# live_stream_id='vualto_journaal',
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',
),
}
1 change: 1 addition & 0 deletions resources/lib/vrtplayer/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
LISTING_TVGUIDE = 'listingtvguide'

PLAY = 'play'
PLAY_RADIO = 'play_radio'
30 changes: 30 additions & 0 deletions resources/lib/vrtplayer/vrtplayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,29 @@ def show_livestream_items(self):

self._kodi_wrapper.show_listing(livestream_items, sort='unsorted', content_type='videos', cache=False)

def show_radio_menu_items(self):
radio_items = []
for channel in CHANNELS:
if 'radio' not in CHANNELS[channel].get('type'):
continue
if CHANNELS[channel].get('tagline'):
label = '%(name)s [I][COLOR blue]-- %(tagline)s[/COLOR][/I]' % CHANNELS[channel]
else:
label = CHANNELS[channel].get('name')
radio_items.append(helperobjects.TitleItem(
title=label,
# Only MP3 support includes song information
url_dict=dict(action=actions.PLAY_RADIO, radio_stream=CHANNELS[channel].get('mp3_128')),
is_playable=True,
art_dict=dict(thumb='DefaultAddonMusic.png', icon='DefaultAddonMusic.png', fanart='DefaultAddonMusic.png'),
video_dict=dict(
plot='[B]%(name)s[/B]\n[I]%(tagline)s[/I]\n\n[COLOR yellow]%(website)s[/COLOR]' % CHANNELS[channel],
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)
Expand All @@ -128,6 +151,13 @@ def play(self, 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')].get('mp3_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)

Expand Down
1 change: 1 addition & 0 deletions test/vrtplayertests.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ 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)
self.assertEqual(categories, CATEGORIES)

def test_random_tvshow_episodes(self):
Expand Down