script.cinematic/addon.py

165 lines
6.3 KiB
Python

import xbmc
import xbmcgui
import xbmcaddon
import xbmcvfs
import json
import random
import sys
import tmdb
ADDON = xbmcaddon.Addon()
CWD = ADDON.getAddonInfo('path').decode('utf-8')
#CWD = ADDON.getAddonInfo('path') # for kodi 19
# reads program names from JSON files and returns a dict
def list_programs(cinematic_path):
dirs, files = xbmcvfs.listdir(cinematic_path)
programs = {}
for filename in files:
if filename.endswith('.json'):
filehandle = xbmcvfs.File(cinematic_path + filename)
program_json = filehandle.read()
filehandle.close()
program_data = json.loads(program_json)
programs[program_data['name']] = filename
return programs
# shows the selection dialog with program names, returns JSON filename
def show_dialog(programs):
entries = programs.keys()
dialog = xbmcgui.Dialog()
ret = dialog.select('Cinematic: Select a program', entries)
del dialog
return programs[entries[ret]]
# get a number of random files from a directory
def files_from_dir(count, location):
dirs, files = xbmcvfs.listdir(location)
files = random.sample(files, count)
for i in range(len(files)):
files[i] = location + files[i]
return files
# reads the JSON file and conducts a pre-program for the feature movie
def conduct_program(program_file, feature):
filehandle = xbmcvfs.File(program_file)
program_json = filehandle.read()
filehandle.close()
program_data = json.loads(program_json)
program = []
for item in program_data['items']:
settings = item['settings']
if settings['source'] == 'file':
entry = {'type': 'video', 'data': settings['location']}
program.append(entry)
elif settings['source'] == 'dir':
for location in files_from_dir(settings['count'], settings['location']):
entry = {'type': 'video', 'data': location}
program.append(entry)
elif settings['source'] == 'tmdbtrailer':
TMDB = tmdb.Tmdb(apikey = settings['apikey'], language = settings['language'])
tmdbid = int(feature['tmdbid'])
imdbid = feature['imdbid']
choice = settings['choice']
trailertype = settings['type']
count = settings['count']
if not tmdbid:
tmdbid = TMDB.get_tmdbid(imdbid)
if tmdbid:
movies = TMDB.get_recommendations(tmdbid, choice)
random.shuffle(movies)
trailers = TMDB.get_trailers(movies, trailertype, count)
else:
print("TODO: this feature has no tmdb id, find someting else to play")
trailers = []
for trailer in trailers:
entry = {'type': 'video', 'data': trailer['location']}
program.append(entry)
elif settings['source'] == 'rating':
rating = -1
for s in feature['mpaa'].split():
if s.isdigit():
rating = int(s)
break
if rating > -1:
dirs, files = xbmcvfs.listdir(settings['location'])
for f in files:
if f.startswith(str(rating)+'.'):
location = settings['location'] + f
break
entry = {'type': 'video', 'data': location}
program.append(entry)
elif settings['source'] == 'feature':
entry = {'type': 'video', 'data': feature['file']}
program.append(entry)
return program
# fetches information on the feature movie
def get_feature(movieid):
query = '{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovieDetails", "params": {"movieid": %s, "properties": ["file", "mpaa", "uniqueid"]}, "id": "1"}' % movieid
json_response = xbmc.executeJSONRPC(query)
response = json.loads(json_response)
if not 'tmdb' in response['result']['moviedetails']['uniqueid']:
response['result']['moviedetails']['uniqueid']['tmdb'] = 0
if not 'imdb' in response['result']['moviedetails']['uniqueid']:
response['result']['moviedetails']['uniqueid']['tmdb'] = ''
feature = {
'label': response['result']['moviedetails']['label'],
'file': response['result']['moviedetails']['file'],
'mpaa': response['result']['moviedetails']['mpaa'],
'tmdbid': response['result']['moviedetails']['uniqueid']['tmdb'],
'imdbid': response['result']['moviedetails']['uniqueid']['imdb']
}
return feature
# entry point
if __name__ == '__main__':
cinematic_path = ADDON.getSettingString('cinematic_path')
# collect info about the selected feature movie
movieid = xbmc.getInfoLabel('ListItem.DBID').decode('utf-8')
feature = get_feature(movieid)
print(feature)
# let user select one of the JSON programs
programs = list_programs(cinematic_path)
program_file = cinematic_path + show_dialog(programs)
# conduct and show playlist
program = conduct_program(program_file, feature)
print('=== playlist')
for entry in program:
print(" * [%s] -- %s" % (entry['type'], entry['data'].encode('utf-8')))
# close modal movie information window
if xbmc.getCondVisibility('Window.IsVisible(MovieInformation)'):
xbmc.executebuiltin('Dialog.Close(MovieInformation)')
"""
TODO: this is not the intended way of playing back the conducted playlist.
hints for a better implementation are welcome.
the plan is to play each video file in the list separately, so the addon is
able to perform further tasks in between, like controlling home automation
systems. unfortunately, research has to be done in order to find out how
that should be implemented.
"""
# build kodi style playlist
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
playlist.clear()
for entry in program:
if entry['type'] == 'video':
playlist.add(entry['data'])
else:
# it is planned to implement features other than video playback
# e. g. call scripts in home automation to dim the lights
print(" unable to handle %s yet" % entry['type'])
# start playback
xbmc.Player().play(playlist)
xbmc.sleep(500)
# wait until program is finished
while xbmc.getCondVisibility('Player.HasMedia'):
xbmc.sleep(100)