2020-03-19 16:45:31 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
""" Player module """
|
|
|
|
|
|
|
|
from __future__ import absolute_import, division, unicode_literals
|
|
|
|
|
|
|
|
import logging
|
2020-04-02 20:21:00 +02:00
|
|
|
import os
|
2020-03-19 16:45:31 +01:00
|
|
|
|
|
|
|
from resources.lib import kodiutils
|
2020-04-02 20:21:00 +02:00
|
|
|
from resources.lib.downloader import Downloader
|
2020-03-19 16:45:31 +01:00
|
|
|
from resources.lib.viervijfzes.auth import AuthApi
|
2020-03-22 10:30:23 +01:00
|
|
|
from resources.lib.viervijfzes.auth_awsidp import InvalidLoginException, AuthenticationException
|
2020-03-19 16:45:31 +01:00
|
|
|
from resources.lib.viervijfzes.content import ContentApi, UnavailableException, GeoblockedException
|
|
|
|
|
|
|
|
_LOGGER = logging.getLogger('player')
|
|
|
|
|
|
|
|
|
|
|
|
class Player:
|
|
|
|
""" Code responsible for playing media """
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
""" Initialise object """
|
2020-04-02 20:21:00 +02:00
|
|
|
auth = AuthApi(kodiutils.get_setting('username'), kodiutils.get_setting('password'), kodiutils.get_tokens_path())
|
|
|
|
self._api = ContentApi(auth)
|
2020-03-19 16:45:31 +01:00
|
|
|
|
|
|
|
def play_from_page(self, channel, path):
|
|
|
|
""" Play the requested item.
|
|
|
|
:type channel: string
|
|
|
|
:type path: string
|
|
|
|
"""
|
|
|
|
# Get episode information
|
2020-03-21 20:34:07 +01:00
|
|
|
episode = ContentApi().get_episode(channel, path)
|
2020-03-19 16:45:31 +01:00
|
|
|
|
|
|
|
# Play this now we have the uuid
|
2020-03-22 15:37:15 +01:00
|
|
|
self.play(episode.uuid)
|
2020-03-19 16:45:31 +01:00
|
|
|
|
2020-04-02 20:21:00 +02:00
|
|
|
def play(self, uuid):
|
2020-03-19 16:45:31 +01:00
|
|
|
""" Play the requested item.
|
2020-04-02 20:21:00 +02:00
|
|
|
:type uuid: string
|
2020-03-19 16:45:31 +01:00
|
|
|
"""
|
2020-04-02 20:21:00 +02:00
|
|
|
if kodiutils.get_setting_bool('episode_cache_enabled'):
|
|
|
|
# Check for a cached version
|
|
|
|
cached_file = self._check_cached_episode(uuid)
|
|
|
|
if cached_file:
|
|
|
|
kodiutils.play(cached_file)
|
|
|
|
return
|
2020-03-25 07:50:45 +01:00
|
|
|
|
|
|
|
# Workaround for Raspberry Pi 3 and older
|
|
|
|
omxplayer = kodiutils.get_global_setting('videoplayer.useomxplayer')
|
|
|
|
if omxplayer is False:
|
|
|
|
kodiutils.set_global_setting('videoplayer.useomxplayer', True)
|
|
|
|
|
2020-04-02 20:21:00 +02:00
|
|
|
# Resolve the stream
|
|
|
|
resolved_stream = self._fetch_stream(uuid)
|
|
|
|
if not resolved_stream:
|
|
|
|
kodiutils.end_of_directory()
|
|
|
|
return
|
|
|
|
|
|
|
|
# Play this item
|
|
|
|
kodiutils.play(resolved_stream)
|
|
|
|
|
|
|
|
def download(self, uuid):
|
|
|
|
""" Download the requested item to cache.
|
|
|
|
:type uuid: string
|
|
|
|
"""
|
|
|
|
# We can notify Kodi already that we won't be returning a listing.
|
|
|
|
# This also fixes an odd Kodi bug where a starting a Progress() without closing the directory listing causes Kodi to hang.
|
|
|
|
kodiutils.end_of_directory()
|
|
|
|
|
|
|
|
# Check ffmpeg
|
|
|
|
if not Downloader.check():
|
|
|
|
kodiutils.ok_dialog(message=kodiutils.localize(30719)) # Could not download this episode since ffmpeg seems to be unavailable.
|
|
|
|
return
|
|
|
|
|
|
|
|
# Check download folder
|
|
|
|
download_folder = kodiutils.get_setting('episode_cache_folder').rstrip('/')
|
|
|
|
if not os.path.exists(download_folder):
|
|
|
|
kodiutils.ok_dialog(message=kodiutils.localize(30718)) # Could not download this episode since the download folder is not set or does not exist.
|
|
|
|
return
|
|
|
|
|
|
|
|
# Check if we already have downloaded this file
|
|
|
|
download_path = '%s/%s.mp4' % (download_folder, uuid)
|
|
|
|
if os.path.isfile(download_path):
|
|
|
|
# You have already downloaded this episode. Do you want to download it again?
|
|
|
|
result = kodiutils.yesno_dialog(message=kodiutils.localize(30726))
|
|
|
|
if not result:
|
|
|
|
return
|
|
|
|
|
|
|
|
# Download this item
|
|
|
|
downloader = Downloader()
|
|
|
|
progress = kodiutils.progress(message=kodiutils.localize(30723)) # Starting download...
|
|
|
|
|
|
|
|
def callback(total, current):
|
|
|
|
""" Callback function to update the progress bar. """
|
|
|
|
percentage = current * 100 / total
|
|
|
|
progress.update(int(percentage), kodiutils.localize(30724, amount=round(percentage, 2))) # Downloading... ({amount}%)
|
|
|
|
return progress.iscanceled()
|
|
|
|
|
|
|
|
# Resolve the stream and start the download
|
|
|
|
resolved_stream = self._fetch_stream(uuid)
|
|
|
|
status = downloader.download(resolved_stream, download_path, callback)
|
|
|
|
|
|
|
|
# Close the progress bar
|
|
|
|
progress.close()
|
|
|
|
|
|
|
|
if status:
|
|
|
|
kodiutils.ok_dialog(message=kodiutils.localize(30725)) # Download has finished. You can now play this episode from cache.
|
|
|
|
|
|
|
|
def _fetch_stream(self, uuid):
|
|
|
|
""" Fetches the HLS stream of the item.
|
|
|
|
:type uuid: string
|
|
|
|
"""
|
2020-03-19 16:45:31 +01:00
|
|
|
try:
|
2020-03-21 20:34:07 +01:00
|
|
|
# Check if we have credentials
|
|
|
|
if not kodiutils.get_setting('username') or not kodiutils.get_setting('password'):
|
2020-03-22 10:30:23 +01:00
|
|
|
confirm = kodiutils.yesno_dialog(
|
|
|
|
message=kodiutils.localize(30701)) # To watch a video, you need to enter your credentials. Do you want to enter them now?
|
2020-03-21 20:34:07 +01:00
|
|
|
if confirm:
|
|
|
|
kodiutils.open_settings()
|
2020-04-02 20:21:00 +02:00
|
|
|
return None
|
2020-03-21 20:34:07 +01:00
|
|
|
|
2020-03-22 10:30:23 +01:00
|
|
|
try:
|
2020-03-22 15:37:15 +01:00
|
|
|
# Get stream information
|
2020-04-02 20:21:00 +02:00
|
|
|
resolved_stream = self._api.get_stream_by_uuid(uuid)
|
2020-03-22 15:37:15 +01:00
|
|
|
|
2020-03-22 10:30:23 +01:00
|
|
|
except (InvalidLoginException, AuthenticationException) as ex:
|
|
|
|
_LOGGER.error(ex)
|
2020-03-22 15:37:15 +01:00
|
|
|
kodiutils.ok_dialog(message=kodiutils.localize(30702, error=str(ex)))
|
2020-04-02 20:21:00 +02:00
|
|
|
return None
|
2020-03-21 20:34:07 +01:00
|
|
|
|
2020-03-19 16:45:31 +01:00
|
|
|
except GeoblockedException:
|
|
|
|
kodiutils.ok_dialog(heading=kodiutils.localize(30709), message=kodiutils.localize(30710)) # This video is geo-blocked...
|
2020-04-02 20:21:00 +02:00
|
|
|
return None
|
2020-03-19 16:45:31 +01:00
|
|
|
|
|
|
|
except UnavailableException:
|
|
|
|
kodiutils.ok_dialog(heading=kodiutils.localize(30711), message=kodiutils.localize(30712)) # The video is unavailable...
|
2020-04-02 20:21:00 +02:00
|
|
|
return None
|
2020-03-19 16:45:31 +01:00
|
|
|
|
2020-04-02 20:21:00 +02:00
|
|
|
return resolved_stream
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def _check_cached_episode(uuid):
|
|
|
|
""" Check if this episode is available in the download cache.
|
|
|
|
:type uuid: string
|
|
|
|
"""
|
|
|
|
download_folder = kodiutils.get_setting('episode_cache_folder').rstrip('/')
|
|
|
|
if not download_folder or not os.path.exists(download_folder):
|
|
|
|
return None
|
|
|
|
|
|
|
|
# Check if we already have downloaded this file
|
|
|
|
download_path = '%s/%s.mp4' % (download_folder, uuid)
|
|
|
|
if os.path.isfile(download_path):
|
|
|
|
# You have cached this episode. Do you want to play from your cache or stream it?
|
|
|
|
result = kodiutils.yesno_dialog(message=kodiutils.localize(30720),
|
|
|
|
yeslabel=kodiutils.localize(30721), # Stream
|
|
|
|
nolabel=kodiutils.localize(30722)) # Play from cache
|
|
|
|
|
|
|
|
if not result:
|
|
|
|
return download_path
|
|
|
|
|
|
|
|
return None
|