Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
romanvm committed Nov 26, 2023
1 parent 730b7ad commit a68a7d7
Show file tree
Hide file tree
Showing 15 changed files with 1,364 additions and 266 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ celerybeat-schedule
# virtualenv
venv/
ENV/
.venv/

# Spyder project settings
.spyderproject
Expand Down
619 changes: 619 additions & 0 deletions plugin.video.external.library/LICENSE.txt

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions plugin.video.external.library/addon.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ provider-name="Roman V.M.">
<extension point="xbmc.python.pluginsource" library="main.py">
<provides>video</provides>
</extension>
<extension point="xbmc.python.script" library="commands.py">
<provides>executable</provides>
</extension>
<extension point="xbmc.service" library="service.py" />
<extension point="xbmc.addon.metadata">
<summary lang="en">Kodi External Video Library</summary>
<description lang="en">A plugin that allows to browse and play items from a video library on an external Kodi instance.</description>
<summary lang="en_GB">Kodi External Video Library</summary>
<description lang="en_GB">A plugin that allows to browse and play items from a video library on an external Kodi instance.</description>
<license>GPL-3.0-only</license>
</extension>
</addon>
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
# License: GPL v.3 https://www.gnu.org/copyleft/gpl.html

import sys

import xbmc
import medialibrary as ml

from libs import medialibrary as ml

if __name__ == '__main__':
if sys.argv[1] == 'update_playcount':
Expand Down
254 changes: 59 additions & 195 deletions plugin.video.external.library/libs/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,209 +3,73 @@
# Author: Roman Miroshnychenko aka Roman V.M. ([email protected])
# License: GPL v.3 https://www.gnu.org/copyleft/gpl.html

import os
from urllib import quote
from xbmcgui import Dialog
from simpleplugin import Plugin
import medialibrary as ml
from mem_storage import MemStorage
import sys
from urllib.parse import quote, urljoin, parse_qsl, urlencode

plugin = Plugin()
_ = plugin.initialize_gettext()
dialog = Dialog()
storage = MemStorage()
image_url = ml.kodi_url + '/image/'
commands = os.path.join(plugin.path, 'libs', 'commands.py')
import xbmcplugin
from xbmcgui import Dialog, ListItem

from libs import medialibrary
from libs.kodi_service import ADDON, ADDON_ID, GettextEmulator, logger, get_kodi_url
from libs.mem_storage import MemStorage

@plugin.action()
def root(params):
"""Root action"""
if plugin.show_movies:
yield {
'label': '[{0}]'.format(_('Movies')),
'url' : plugin.get_url(action='library_items', content='movies'),
'thumb': 'DefaultMovies.png',
}
if plugin.show_tvshows:
yield {
'label': '[{0}]'.format(_('TV Shows')),
'url' : plugin.get_url(action='library_items', content='tvshows'),
'thumb': 'DefaultTVShows.png',
}
_ = GettextEmulator.gettext

PLUGIN_URL = f'plugin://{ADDON_ID}/'
HANDLE = int(sys.argv[1])

DIALOG = Dialog()
STORAGE = MemStorage()

KODI_URL = get_kodi_url(with_credentials=True)
IMAGE_URL = urljoin(KODI_URL, 'image')
VIDEO_URL = urljoin(KODI_URL, 'vfs')

def _set_info(content, item, list_item):
"""
Set list item info
"""
video_info = {'title': item['label']}
if content.endswith('movies') or content == 'tvshows':
video_info['genre'] = u', '.join(item['genre'])
video_info['year'] = item['year']
video_info['plot'] = item['plot']
video_info['cast'] = [actor['name'] for actor in item['cast']]
video_info['studio'] = u', '.join(item['studio'])
if content.endswith('movies'):
video_info['director'] = u', '.join(item['director'])
elif content == 'seasons':
video_info['tvshowtitle'] = item['showtitle']
video_info['season'] = item['season']
elif content.endswith('episodes'):
video_info['tvshowtitle'] = item['showtitle']
video_info['plot'] = item['plot']
video_info['cast'] = [actor['name'] for actor in item['cast']]
video_info['director'] = u', '.join(item['director'])
video_info['premiered'] = item['firstaired']
video_info['season'] = item['season']
video_info['episode'] = item['episode']
if content == 'recent_episodes':
list_item['label'] = video_info['title'] = u'{0} - {1}'.format(item['showtitle'], item['label'])
list_item['info']['video'] = video_info

def get_url(**kwargs):
return PLUGIN_URL + '?' + urlencode(kwargs)

def _set_art(content, item, list_item):
"""
Set list item artwork
"""
if content.endswith('movies'):
list_item['thumb'] = list_item['art']['poster'] = image_url + quote(item['art'].get('poster', ''))
list_item['fanart'] = image_url + quote(item['art'].get('fanart', ''))
elif content == 'tvshows':
list_item['thumb'] = list_item['art']['poster'] = image_url + quote(
item['art'].get('tvshow.poster') or
item['art'].get('poster', '')
)
list_item['art']['banner'] = image_url + quote(
item['art'].get('tvshow.banner') or
item['art'].get('banner', '')
)
list_item['fanart'] = image_url + quote(
item['art'].get('tvshow.fanart') or
item['art'].get('fanart')
)
elif content == 'seasons':
list_item['thumb'] = list_item['art']['poster'] = image_url + quote(
item['art'].get('season.poster') or
item['art'].get('tvshow.poster') or
item['art'].get('poster', '')
)
list_item['art']['banner'] = image_url + quote(
item['art'].get('season.banner') or
item['art'].get('tvshow.banner') or
item['art'].get('banner', '')
)
list_item['fanart'] = image_url + quote(
item['art'].get('season.fanart') or
item['art'].get('tvshow.fanart') or
item['art'].get('fanart', '')
)
elif content.endswith('episodes'):
list_item['thumb'] = image_url + quote(
item['art'].get('thumb', '') or
item['art'].get('season.poster') or
item['art'].get('tvshow.poster') or
item['art'].get('poster', '')
)
list_item['poster'] = image_url + quote(
item['art'].get('season.poster') or
item['art'].get('tvshow.poster') or
item['art'].get('poster', '')
)
list_item['art']['banner'] = image_url + quote(
item['art'].get('season.banner') or
item['art'].get('tvshow.banner') or
item['art'].get('banner', '')
)
list_item['fanart'] = image_url + quote(
item['art'].get('season.fanart') or
item['art'].get('tvshow.fanart') or
item['art'].get('fanart', '')
)

def root():
"""Root action"""
if ADDON.getSettingBool('show_movies'):
list_item = ListItem(f'[{_("Movies")}]')
list_item.setArt({'icon': 'DefaultMovies.png', 'thumb': 'DefaultMovies.png'})
url = get_url(content='movies')
xbmcplugin.addDirectoryItem(HANDLE, url, list_item, isFolder=True)
# if ADDON.getSettingBool('show_tvshows'):
# list_item = ListItem(f'[{_("TV Shows")}]')
# list_item.setArt({'icon': 'DefaultTVShows.png', 'thumb': 'DefaultTVShows.png'})
# url = get_url(content='tvshows')
# xbmcplugin.addDirectoryItem(HANDLE, url, list_item, isFolder=True)


def _show_library_items(items, content):
"""
Get the list of movies or TV shows
"""
if content == 'movies' and plugin.show_recent_movies:
yield {
'label': '[{0}]'.format(_('Recently added movies')),
'url': plugin.get_url(action='library_items', content='recent_movies'),
'thumb': 'DefaultRecentlyAddedMovies.png'
}
elif content == 'tvshows' and plugin.show_recent_episodes:
yield {
'label': '[{0}]'.format(_('Recently added episodes')),
'url' : plugin.get_url(action='library_items', content='recent_episodes'),
'thumb': 'DefaultRecentlyAddedEpisodes.png'
}
for item in items:
list_item = {'label': item['label'], 'art': {}, 'info': {}}
_set_info(content, item, list_item)
_set_art(content, item, list_item)
if content.endswith('movies') or content.endswith('episodes'):
if item['playcount']:
caption = '[COLOR=yellow]{0}[/COLOR]'.format(_('Mark as unwatched'))
playcount = 0
else:
caption = '[COLOR=green]{0}[/COLOR]'.format(_('Mark as watched'))
playcount = 1
if content.endswith('movies'):
item_id = item['movieid']
else:
item_id = item['episodeid']
list_item['context_menu'] = [(
caption, 'RunScript({commands},update_playcount,{content},{id},{playcount})'.format(
commands=commands,
content=content,
id=item_id,
playcount=playcount
)
)]
list_item['info']['video']['playcount'] = item['playcount']
list_item['url'] = ml.kodi_url + '/vfs/' + quote(item['file'])
list_item['is_playable'] = True
elif content == 'tvshows':
list_item['url'] = plugin.get_url(action='library_items', content='seasons', tvshowid=item['tvshowid'])
elif content == 'seasons':
list_item['url'] = plugin.get_url(action='library_items', content='episodes',
tvshowid=item['tvshowid'], season=item['season'])
plugin.log('List item: {0}'.format(list_item))
yield list_item
def show_movies():
xbmcplugin.setPluginCategory(HANDLE, _('Movies'))
xbmcplugin.setContent(HANDLE, 'movies')
movies = medialibrary.get_movies()
for mov in movies:
list_item = ListItem(mov['label'])
poster = mov.get('art', {}).get('poster', '')
fanart = mov.get('art', {}).get('fanart', '')
list_item.setArt({
'poster': f'{IMAGE_URL}/{quote(poster)}',
'fanart': f'{IMAGE_URL}/{quote(fanart)}',
})
list_item.setInfo('video', {
'plot': mov.get('plot', ''),
'year': mov.get('year', -1),
'genre': mov.get('genre', []),
'director': mov.get('director', []),
'studio': mov.get('studio', []),
})
url = f'{VIDEO_URL}/{quote(mov["file"])}'
xbmcplugin.addDirectoryItem(HANDLE, url, list_item, isFolder=False)


@plugin.action()
def library_items(params):
"""
Display the list of movies or TV shows
"""
listing = []
plugin_content = None
content = params['content']
try:
if content.endswith('movies'):
items = ml.get_movies(recent=content.startswith('recent'))
plugin_content = 'movies'
elif content == 'tvshows':
items = ml.get_tvshows()
plugin_content = 'tvshows'
elif content == 'seasons':
items = ml.get_seasons(int(params['tvshowid']))
plugin_content = 'tvshows'
if (plugin.flatten_tvshows == 1 and len(items) == 1) or plugin.flatten_tvshows == 2:
items = ml.get_episodes(int(params['tvshowid']), items[0]['season'])
content = plugin_content = 'episodes'
elif content.endswith('episodes'):
items = ml.get_episodes(int(params.get('tvshowid', -1)),
int(params.get('season', -1)),
content.startswith('recent'))
plugin_content = 'episodes'
except ml.ConnectionError:
dialog.notification(plugin.id, _('Unable to connect to the remote Kodi host!'), icon='error')
except ml.NoDataError:
dialog.notification(plugin.id, _('Remote Kodi library contains no relevant data!'), icon='error')
else:
storage['__list__'] = items
listing = _show_library_items(items, content)
return plugin.create_listing(listing, content=plugin_content)
def router(paramstring):
params = dict(parse_qsl(paramstring))
logger.debug('Called addon with params: %s', str(sys.argv))
if 'content' not in params:
root()
xbmcplugin.endOfDirectory(HANDLE)
Loading

0 comments on commit a68a7d7

Please sign in to comment.