Skip to content
This repository has been archived by the owner on Oct 21, 2024. It is now read-only.

Implement program caching for more metadata in listings #8

Merged
merged 6 commits into from
Mar 22, 2020
Merged
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version = $(shell xmllint --xpath 'string(/addon/@version)' addon.xml)
git_branch = $(shell git rev-parse --abbrev-ref HEAD)
git_hash = $(shell git rev-parse --short HEAD)
zip_name = $(name)-$(version)-$(git_branch)-$(git_hash).zip
include_files = addon_entry.py addon.xml CHANGELOG.md LICENSE README.md resources/
include_files = addon_entry.py addon.xml CHANGELOG.md LICENSE README.md service_entry.py resources/
include_paths = $(patsubst %,$(name)/%,$(include_files))
exclude_files = \*.new \*.orig \*.pyc \*.pyo

Expand Down
1 change: 1 addition & 0 deletions addon.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<extension point="xbmc.python.pluginsource" library="addon_entry.py">
<provides>video</provides>
</extension>
<extension point="xbmc.service" library="service_entry.py"/>
<extension point="xbmc.addon.metadata">
<summary lang="en_GB">Watch content from VIER, VIJF and ZES.</summary>
<platform>all</platform>
Expand Down
33 changes: 33 additions & 0 deletions resources/language/resource.language.en_gb/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ msgctxt "#30713"
msgid "The requested video was not found in the guide."
msgstr ""

msgctxt "#30714"
msgid "Local metadata is cleared."
msgstr ""

msgctxt "#30715"
msgid "Updating metadata"
msgstr ""

msgctxt "#30716"
msgid "Updating metadata ({index}/{total})..."
msgstr ""

msgctxt "#30717"
msgid "This program is not available in the catalogue."
msgstr ""
Expand All @@ -141,3 +153,24 @@ msgstr ""
msgctxt "#30805"
msgid "Password"
msgstr ""

msgctxt "#30820"
msgid "Interface"
msgstr ""

msgctxt "#30827"
msgid "Metadata"
msgstr ""

msgctxt "#30829"
msgid "Periodically refresh metadata in the background"
msgstr ""

msgctxt "#30831"
msgid "Update local metadata now"
msgstr ""

msgctxt "#30833"
msgid "Clear local metadata"
msgstr ""

33 changes: 33 additions & 0 deletions resources/language/resource.language.nl_nl/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ msgctxt "#30713"
msgid "The requested video was not found in the guide."
msgstr "De gevraagde video werd niet gevonden in de tv-gids."

msgctxt "#30714"
msgid "Local metadata is cleared."
msgstr "De locale metadata is verwijderd."

msgctxt "#30715"
msgid "Updating metadata"
msgstr "Vernieuwen metadata"

msgctxt "#30716"
msgid "Updating metadata ({index}/{total})..."
msgstr "Vernieuwen metadata ({index}/{total})..."

msgctxt "#30717"
msgid "This program is not available in the catalogue."
msgstr "Dit programma is niet beschikbaar in de catalogus."
Expand All @@ -142,3 +154,24 @@ msgstr "E-mailadres"
msgctxt "#30805"
msgid "Password"
msgstr "Wachtwoord"

msgctxt "#30820"
msgid "Interface"
msgstr "Interface"

msgctxt "#30827"
msgid "Metadata"
msgstr "Metadata"

msgctxt "#30829"
msgid "Periodically refresh metadata in the background"
msgstr "Vernieuw de metdata automatisch in de achtergrond"

msgctxt "#30831"
msgid "Update local metadata now"
msgstr "De locale metadata nu vernieuwen"

msgctxt "#30833"
msgid "Clear local metadata"
msgstr "De locale metadata verwijderen"

27 changes: 22 additions & 5 deletions resources/lib/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@

from __future__ import absolute_import, division, unicode_literals

import logging

from routing import Plugin

from resources.lib import kodilogging

kodilogging.config()
routing = Plugin()
_LOGGER = logging.getLogger('addon')


@routing.route('/')
Expand Down Expand Up @@ -67,11 +70,11 @@ def show_catalog_program(channel, program):
Catalog().show_program(channel, program)


@routing.route('/program/program/<channel>/<program>/<season>')
@routing.route('/catalog/program/<channel>/<program>/<season>')
def show_catalog_program_season(channel, program, season):
""" Show a program from the catalog """
from resources.lib.modules.catalog import Catalog
Catalog().show_program_season(channel, program, int(season))
Catalog().show_program_season(channel, program, season)


@routing.route('/search')
Expand All @@ -82,11 +85,11 @@ def show_search(query=None):
Search().show_search(query)


@routing.route('/play/catalog/<channel>/<uuid>')
def play(channel, uuid):
@routing.route('/play/catalog/<uuid>')
def play(uuid):
""" Play the requested item """
from resources.lib.modules.player import Player
Player().play(channel, uuid)
Player().play(uuid)


@routing.route('/play/page/<channel>/<page>')
Expand All @@ -101,6 +104,20 @@ def play_from_page(channel, page):
Player().play_from_page(channel, unquote(page))


@routing.route('/metadata/update')
def metadata_update():
""" Update the metadata for the listings (called from settings) """
from resources.lib.modules.metadata import Metadata
Metadata().update()


@routing.route('/metadata/clean')
def metadata_clean():
""" Clear metadata (called from settings) """
from resources.lib.modules.metadata import Metadata
Metadata().clean()


def run(params):
""" Run the routing plugin """
routing.run(params)
34 changes: 25 additions & 9 deletions resources/lib/kodiutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
SORT_METHODS = dict(
unsorted=xbmcplugin.SORT_METHOD_UNSORTED,
label=xbmcplugin.SORT_METHOD_LABEL_IGNORE_FOLDERS,
title=xbmcplugin.SORT_METHOD_TITLE,
episode=xbmcplugin.SORT_METHOD_EPISODE,
duration=xbmcplugin.SORT_METHOD_DURATION,
year=xbmcplugin.SORT_METHOD_VIDEO_YEAR,
date=xbmcplugin.SORT_METHOD_DATE,
)
DEFAULT_SORT_METHODS = [
'unsorted', 'label'
'unsorted', 'title'
]

_LOGGER = logging.getLogger('kodiutils')
Expand Down Expand Up @@ -269,7 +270,7 @@ def set_locale():
setlocale(LC_ALL, locale_lang)
except (Error, ValueError) as exc:
if locale_lang != 'en_GB':
_LOGGER.debug("Your system does not support locale '{locale}': {error}", locale=locale_lang, error=exc)
_LOGGER.debug("Your system does not support locale '%s': %s", locale_lang, exc)
set_locale.cached = False
return False
set_locale.cached = True
Expand Down Expand Up @@ -423,14 +424,14 @@ def listdir(path):
def mkdir(path):
"""Create a directory (using xbmcvfs)"""
from xbmcvfs import mkdir as vfsmkdir
_LOGGER.debug("Create directory '{path}'.", path=path)
_LOGGER.debug("Create directory '%s'.", path)
return vfsmkdir(path)


def mkdirs(path):
"""Create directory including parents (using xbmcvfs)"""
from xbmcvfs import mkdirs as vfsmkdirs
_LOGGER.debug("Recursively create directory '{path}'.", path=path)
_LOGGER.debug("Recursively create directory '%s'.", path)
return vfsmkdirs(path)


Expand Down Expand Up @@ -458,14 +459,14 @@ def stat_file(path):
def delete(path):
"""Remove a file (using xbmcvfs)"""
from xbmcvfs import delete as vfsdelete
_LOGGER.debug("Delete file '{path}'.", path=path)
_LOGGER.debug("Delete file '%s'.", path)
return vfsdelete(path)


def container_refresh(url=None):
"""Refresh the current container or (re)load a container by URL"""
if url:
_LOGGER.debug('Execute: Container.Refresh({url})', url=url)
_LOGGER.debug('Execute: Container.Refresh(%s)', url)
xbmc.executebuiltin('Container.Refresh({url})'.format(url=url))
else:
_LOGGER.debug('Execute: Container.Refresh')
Expand All @@ -475,7 +476,7 @@ def container_refresh(url=None):
def container_update(url):
"""Update the current container while respecting the path history."""
if url:
_LOGGER.debug('Execute: Container.Update({url})', url=url)
_LOGGER.debug('Execute: Container.Update(%s)', url)
xbmc.executebuiltin('Container.Update({url})'.format(url=url))
else:
# URL is a mandatory argument for Container.Update, use Container.Refresh instead
Expand Down Expand Up @@ -529,7 +530,7 @@ def get_cache(key, ttl=None):

with open_file(fullpath, 'r') as fdesc:
try:
_LOGGER.info('Fetching {file} from cache', file=filename)
_LOGGER.debug('Fetching %s from cache', filename)
import json
value = json.load(fdesc)
return value
Expand All @@ -547,6 +548,21 @@ def set_cache(key, data):
mkdirs(path)

with open_file(fullpath, 'w') as fdesc:
_LOGGER.info('Storing to cache as {file}', file=filename)
_LOGGER.debug('Storing to cache as %s', filename)
import json
json.dump(data, fdesc)


def invalidate_cache(ttl=None):
""" Clear the cache """
path = get_cache_path()
if not exists(path):
return
_, files = listdir(path)
import time
now = time.mktime(time.localtime())
for filename in files:
fullpath = path + filename
if ttl and now - stat_file(fullpath).st_mtime() < ttl:
continue
delete(fullpath)
30 changes: 15 additions & 15 deletions resources/lib/modules/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from resources.lib.kodiutils import TitleItem
from resources.lib.modules.menu import Menu
from resources.lib.viervijfzes import CHANNELS
from resources.lib.viervijfzes.auth import AuthApi
from resources.lib.viervijfzes.content import ContentApi, UnavailableException

_LOGGER = logging.getLogger('catalog')
Expand All @@ -19,7 +20,8 @@ class Catalog:

def __init__(self):
""" Initialise object """
self._api = ContentApi()
auth = AuthApi(kodiutils.get_setting('username'), kodiutils.get_setting('password'))
self._api = ContentApi(auth)
self._menu = Menu()

def show_catalog(self):
Expand All @@ -34,9 +36,9 @@ def show_catalog(self):

listing = [self._menu.generate_titleitem(item) for item in items]

# Sort items by label, but don't put folders at the top.
# Sort items by title
# Used for A-Z listing or when movies and episodes are mixed.
kodiutils.show_listing(listing, 30003, content='tvshows', sort='label')
kodiutils.show_listing(listing, 30003, content='tvshows', sort='title')

def show_catalog_channel(self, channel):
""" Show the programs of a specific channel
Expand All @@ -52,9 +54,9 @@ def show_catalog_channel(self, channel):
for item in items:
listing.append(self._menu.generate_titleitem(item))

# Sort items by label, but don't put folders at the top.
# Sort items by title
# Used for A-Z listing or when movies and episodes are mixed.
kodiutils.show_listing(listing, 30003, content='tvshows', sort='label')
kodiutils.show_listing(listing, 30003, content='tvshows', sort='title')

def show_program(self, channel, program_id):
""" Show a program from the catalog
Expand All @@ -75,7 +77,7 @@ def show_program(self, channel, program_id):

# Go directly to the season when we have only one season
if len(program.seasons) == 1:
self.show_program_season(channel, program_id, program.seasons.values()[0].number)
self.show_program_season(channel, program_id, program.seasons.values()[0].uuid)
return

studio = CHANNELS.get(program.channel, {}).get('studio_icon')
Expand All @@ -87,9 +89,8 @@ def show_program(self, channel, program_id):
listing.append(
TitleItem(
title='* %s' % kodiutils.localize(30204), # * All seasons
path=kodiutils.url_for('show_catalog_program_season', channel=channel, program=program_id, season=-1),
path=kodiutils.url_for('show_catalog_program_season', channel=channel, program=program_id, season='-1'),
art_dict={
'thumb': program.cover,
'fanart': program.background,
},
info_dict={
Expand All @@ -107,9 +108,8 @@ def show_program(self, channel, program_id):
listing.append(
TitleItem(
title=s.title, # kodiutils.localize(30205, season=s.number), # Season {season}
path=kodiutils.url_for('show_catalog_program_season', channel=channel, program=program_id, season=s.number),
path=kodiutils.url_for('show_catalog_program_season', channel=channel, program=program_id, season=s.uuid),
art_dict={
'thumb': s.cover,
'fanart': program.background,
},
info_dict={
Expand All @@ -123,13 +123,13 @@ def show_program(self, channel, program_id):
)

# Sort by label. Some programs return seasons unordered.
kodiutils.show_listing(listing, 30003, content='tvshows', sort=['label'])
kodiutils.show_listing(listing, 30003, content='tvshows')

def show_program_season(self, channel, program_id, season):
def show_program_season(self, channel, program_id, season_uuid):
""" Show the episodes of a program from the catalog
:type channel: str
:type program_id: str
:type season: int
:type season_uuid: str
"""
try:
program = self._api.get_program(channel, program_id)
Expand All @@ -138,12 +138,12 @@ def show_program_season(self, channel, program_id, season):
kodiutils.end_of_directory()
return

if season == -1:
if season_uuid == "-1":
# Show all episodes
episodes = program.episodes
else:
# Show the episodes of the season that was selected
episodes = [e for e in program.episodes if e.season == season]
episodes = [e for e in program.episodes if e.season_uuid == season_uuid]

listing = [self._menu.generate_titleitem(episode) for episode in episodes]

Expand Down
Loading