diff --git a/README.md b/README.md
index cf470eb..4ff7b81 100644
--- a/README.md
+++ b/README.md
@@ -6,3 +6,7 @@
This Screensaver uses the database from the plugin.image.mypicsdb2 addon. Filters can be used to select which pictures will be shown in the slideshow.
+ The values of some image tags are set in Window properties. There is an option to display the values overlayed on the images. The values that can be displayed are:
+
+ Headline, Caption, Location, Date and Time, and Folder and File name.
+
diff --git a/lib/getfilternames.py b/lib/getfilternames.py
index c4a1e38..771edfb 100644
--- a/lib/getfilternames.py
+++ b/lib/getfilternames.py
@@ -52,6 +52,6 @@
tree.write(settings_file)
# Notify that you must exit from settings and return to see any new filter names
-heading = xbmcaddon.Addon().getLocalizedString(30009)
-message = xbmcaddon.Addon().getLocalizedString(30010)
+heading = xbmcaddon.Addon().getLocalizedString(30010)
+message = xbmcaddon.Addon().getLocalizedString(30011)
xbmc.executebuiltin('Notification('+heading+','+message+',10000)')
diff --git a/lib/screensaver.py b/lib/screensaver.py
index f11971c..133c09f 100644
--- a/lib/screensaver.py
+++ b/lib/screensaver.py
@@ -18,11 +18,15 @@
# The screensaver uses the picture database created by the plugin.image.mypicsdb2 addon.
# You can also use Filters created in the plugin.image.mypicsdb2 addon to select which
# pictures are shown in the slideshow.
+# The values of some image tags are set in Window properties. There is an option
+# to display the values overlayed on the images. The values displayed are
+# Headline, Caption, Location, Date and Time, and Folder and File name.
import os.path
import sys
import random
import urllib.parse
+import time
import xbmc
import xbmcgui
@@ -32,32 +36,41 @@
ADDON = xbmcaddon.Addon()
-SETTINGS_ERROR = ADDON.getLocalizedString(30005)
-NO_FILTER_NAME_ERROR = ADDON.getLocalizedString(30006)
-BAD_FILTER_NAME_ERROR = ADDON.getLocalizedString(30007)
-NO_FILES_MATCH_FILTER = ADDON.getLocalizedString(30008)
+SETTINGS_ERROR = ADDON.getLocalizedString(30006)
+NO_FILTER_NAME_ERROR = ADDON.getLocalizedString(30007)
+BAD_FILTER_NAME_ERROR = ADDON.getLocalizedString(30008)
+NO_FILES_MATCH_FILTER = ADDON.getLocalizedString(30009)
def log(msg, level=xbmc.LOGINFO):
filename = os.path.basename(sys._getframe(1).f_code.co_filename)
lineno = str(sys._getframe(1).f_lineno)
xbmc.log(str("[%s] line %5d in %s >> %s"%(ADDON.getAddonInfo('name'), int(lineno), filename, msg.__str__())), level)
+DB_BACKEND = xbmcaddon.Addon('plugin.image.mypicsdb2').getSetting('db_backend').lower()
+# The random function is different in mysql and sqlite
+DB_RANDOM = {"mysql" :"RAND()","sqlite":"RANDOM()"}
+# DateTimes are stored and retreived differently between mysql and sqlite.
+IMGDATE = {"mysql" :"DATE_FORMAT(ImageDateTime,'%Y-%m-%d')",
+ "sqlite":"SUBSTR(ImageDateTime, 0, 11)"}
+IMGDATETIME = {"mysql" :"DATE_FORMAT(ImageDateTime,'%Y-%m-%d %T')",
+ "sqlite":"ImageDateTime"}
+
# Formats that can be displayed in a slideshow
PICTURE_FORMATS = ('jpg', 'jpeg', 'tiff', 'gif', 'png', 'bmp', 'mng', 'ico', 'pcx', 'tga')
-SINGLE_PICTURE_QUERY = """ SELECT strPath, strFilename FROM Files """
-SINGLE_PICTURE_QUERY += """ WHERE strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ OR strFilename LIKE '%s' """
-SINGLE_PICTURE_QUERY += """ ORDER BY RANDOM() LIMIT 1 """
+SINGLE_PICTURE_QUERY = " SELECT strPath, strFilename FROM Files "
+SINGLE_PICTURE_QUERY += " WHERE strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " OR strFilename LIKE '%s' "
+SINGLE_PICTURE_QUERY += " ORDER BY " + DB_RANDOM[DB_BACKEND] + " LIMIT 1 "
SINGLE_PICTURE_QUERY = SINGLE_PICTURE_QUERY % PICTURE_FORMATS
-SINGLE_PICTURE_QUERY = SINGLE_PICTURE_QUERY.replace("LIKE '", "LIKE '%")
+SINGLE_PICTURE_QUERY = SINGLE_PICTURE_QUERY.replace("LIKE '", "LIKE '%")
# Get the Database from the My Pictures Database addon
MPDB = MypicsDB.MyPictureDB()
@@ -67,6 +80,7 @@ def __init__(self, *args, **kwargs):
pass
def onInit(self):
+ self.db_backend = xbmcaddon.Addon('plugin.image.mypicsdb2').getSetting('db_backend').lower()
# Get the screensaver window id
self.winid = xbmcgui.Window(xbmcgui.getCurrentWindowDialogId())
# Init the monitor class to catch onscreensaverdeactivated calls
@@ -80,13 +94,32 @@ def onInit(self):
def _get_settings(self):
# read addon settings
- self.anim_time = 101000
self.slideshow_time = ADDON.getSettingInt('time')
self.slideshow_filter = ADDON.getSettingBool('filter')
self.slideshow_filtername = ADDON.getSettingString('filtername')
+ self.slideshow_showinfo = ADDON.getSettingBool('tags')
# Set the image controls from the xml we are going to use
self.image1 = self.getControl(1)
self.image2 = self.getControl(2)
+ # Get MyPicsDB tagids for the information that can be displayed for each slide
+ _query = " Select idTagType FROM TagTypes WHERE TagType = 'Headline'; "
+ _ids = self._exec_query(_query)
+ self.headline_tagid = _ids[0][0]
+ _query = " Select idTagType FROM TagTypes WHERE TagType = 'Caption/abstract'; "
+ _ids = self._exec_query(_query)
+ self.caption_tagid = _ids[0][0]
+ _query = " Select idTagType FROM TagTypes WHERE TagType = 'Sub-location'; "
+ _ids = self._exec_query(_query)
+ self.sublocation_tagid = _ids[0][0]
+ _query = " Select idTagType FROM TagTypes WHERE TagType = 'City'; "
+ _ids = self._exec_query(_query)
+ self.city_tagid= _ids[0][0]
+ _query = " Select idTagType FROM TagTypes WHERE TagType = 'Province/state'; "
+ _ids = self._exec_query(_query)
+ self.state_tagid= _ids[0][0]
+ _query = " Select idTagType FROM TagTypes WHERE TagType = 'Country/primary location name'; "
+ _ids = self._exec_query(_query)
+ self.country_tagid= _ids[0][0]
def _get_filtered_pictures(self):
# If we are going to use a MyPicsDB filter, then get all of the possible pictures we could use to match the filter
@@ -100,9 +133,9 @@ def _get_filtered_pictures(self):
else:
# Use filter selected, and filter name specified
# Make sure the specified filter exists
- query = """SELECT pkFilter FROM FilterWizard"""
- query += """ WHERE strFilterName IS '%s'; """ %(self.slideshow_filtername.replace("'","''"))
- filter_ids = self.exec_query(query)
+ query = "Select pkFilter FROM FilterWizard"
+ query += " WHERE strFilterName = '%s'; " %(self.slideshow_filtername.replace("'","''"))
+ filter_ids = self._exec_query(query)
if len(filter_ids) != 1:
# Filter name was not found in the My Pictures Database.
message = 'Notification(' + SETTINGS_ERROR + ', ' + BAD_FILTER_NAME_ERROR%(self.slideshow_filtername) + ', 15000, DefaultIconError.png)'
@@ -133,10 +166,14 @@ def _start_show(self):
# loop until onScreensaverDeactivated is called
while (not self.Monitor.abortRequested()) and (not self.stop):
# Get the next picture
- img_name = self._get_item()
+ picture = self._get_item()
+ img_name = os.path.join(picture[0], picture[1])
current_image_control.setImage(img_name, False)
+ xbmc.sleep(1000)
self._set_prop('Fade%d' % order[0], '0')
self._set_prop('Fade%d' % order[1], '1')
+ if (self.slideshow_showinfo):
+ self._set_info_fields(picture)
# define next image
if current_image_control == self.image1:
current_image_control = self.image2
@@ -146,7 +183,7 @@ def _start_show(self):
order = [1,2]
# display the image for the specified amount of time
- count = timetowait
+ count = timetowait - 1000
while (not self.Monitor.abortRequested()) and (not self.stop) and count > 0:
count -= 1000
xbmc.sleep(1000)
@@ -167,20 +204,61 @@ def _get_item(self, update=False):
self.filtered_results_index = 0
else:
# Not using a filter
- result_list = self.exec_query(SINGLE_PICTURE_QUERY)
+ result_list = self._exec_query(SINGLE_PICTURE_QUERY)
result = result_list[0]
- (folder, file) = result
- return os.path.join(folder, file)
+ return result
+
+ def _set_info_fields(self, picture):
+ self._clear_prop('Headline')
+ self._clear_prop('Caption')
+ self._clear_prop('Sublocation')
+ self._clear_prop('City')
+ self._clear_prop('State')
+ self._clear_prop('Country')
+ self._clear_prop('Date')
+ self._clear_prop('Time')
+ # Get info to set in window properties
+ (folder,file) = picture
+ self._set_prop('Folder',folder)
+ self._set_prop('File',file)
+ query = " Select idFile, " + IMGDATETIME[self.db_backend]+ " FROM Files WHERE strPath = '%s' AND strFilename = '%s'; " \
+ %(folder.replace("'","''"), file.replace("'","''"))
+ file_info = self._exec_query(query)
+ if len(file_info) > 0:
+ self._set_prop('Date',time.strftime('%A %B %e, %Y',time.strptime(file_info[0][1], '%Y-%m-%d %H:%M:%S')))
+ self._set_prop('Time',time.strftime('%I:%M:%S %p',time.strptime(file_info[0][1], '%Y-%m-%d %H:%M:%S')))
+ image_id=file_info[0][0]
+ # Get all of the tags that are on this image
+ query = " Select idTagContent FROM TagsInFiles WHERE idFile = '%s'; " %(image_id)
+ content_ids = self._exec_query(query)
+ for content_id in content_ids:
+ # Go through each of the tags, and store the ones of interest
+ query = " Select idTagtype, TagContent FROM TagContents WHERE idTagContent = '%s'; " %(content_id[0])
+ tags = self._exec_query(query)
+ tag_id = tags[0][0]
+ tag_value = tags[0][1]
+ if tag_id == self.headline_tagid:
+ self._set_prop('Headline',tag_value)
+ elif tag_id == self.caption_tagid:
+ self._set_prop('Caption',tag_value)
+ elif tag_id == self.sublocation_tagid:
+ self._set_prop('Sublocation',tag_value)
+ elif tag_id == self.city_tagid:
+ self._set_prop('City',tag_value)
+ elif tag_id == self.state_tagid:
+ self._set_prop('State',tag_value)
+ elif tag_id == self.country_tagid:
+ self._set_prop('Country',tag_value)
# Utility functions
- def exec_query(self,query):
+ def _exec_query(self,query):
return MPDB.cur.request(query)
def _set_prop(self, name, value):
- self.winid.setProperty('SlideView.%s' % name, value)
+ self.winid.setProperty('Screensaver.%s' % name, value)
def _clear_prop(self, name):
- self.winid.clearProperty('SlideView.%s' % name)
+ self.winid.clearProperty('Screensaver.%s' % name)
def _exit(self):
# exit when onScreensaverDeactivated gets called
diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po
index 7cb3098..c312e8b 100644
--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -32,26 +32,30 @@ msgid "Update Filter Names"
msgstr "Update Filter Names"
msgctxt "#30005"
+msgid "Show Picture Information on Slides"
+msgstr "Show Picture Information on Slides"
+
+msgctxt "#30006"
msgid "Slideshow settings error"
msgstr "Slideshow settings error"
-msgctxt "#30006"
+msgctxt "#30007"
msgid "Filter name was not specified"
msgstr "Filter name was not specified"
-msgctxt "#30007"
+msgctxt "#30008"
msgid "Filtername '%s' not found in MyPictures Database"
msgstr "Filtername '%s' not found in MyPictures Database"
-msgctxt "#30008"
+msgctxt "#30009"
msgid "No files match filter '%s'in MyPictures Database"
msgstr "No files match filter '%s'in MyPictures Database"
-msgctxt "#30009"
+msgctxt "#30010"
msgid "Filter Names Updated"
msgstr "Filter Names Updated"
-msgctxt "#30010"
+msgctxt "#30011"
msgid "Exit from 'Settings' and return to see new Filter Names"
msgstr "Exit from 'Settings' and return to see new Filter Names"
@@ -70,3 +74,7 @@ msgid "The name of the Filter to use for matching."
msgctxt "#30104"
msgstr "Help for Update Filter Names"
msgid "Select this if the list of Filters to choose from is not up-to-date. After updating the Filter Names, you must exit from 'Settings' and return in order to see the updated Filter names."
+
+msgctxt "#30105"
+msgstr "Help for Ahow Picture Inforamtion on Slides"
+msgid "Select this to have information about the picture overlayed on top of the picture."
diff --git a/resources/settings.xml b/resources/settings.xml
index 360f1a6..8371839 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -50,6 +50,12 @@
+
+ Display picture information
+ 0
+ false
+
+
diff --git a/resources/skins/default/1080i/screensaver.mypicsdb2.slideshow.xml b/resources/skins/default/1080i/screensaver.mypicsdb2.slideshow.xml
index f6747ba..b6d3e84 100644
--- a/resources/skins/default/1080i/screensaver.mypicsdb2.slideshow.xml
+++ b/resources/skins/default/1080i/screensaver.mypicsdb2.slideshow.xml
@@ -1,45 +1,81 @@
-
- 0
- 0
+
+ 0
+ 019201080
- screensaver-black.png
- WindowOpen
-
-
-
+
+ screensaver-black.png
+ WindowOpen
+ stretch
+
+ image 1
-
-
+
+
-
- 0
- 0
- 1920
- 1080
-
- keep
- 0
-
+ keep
-
+ image 2
-
-
+
+
-
- 0
- 0
- 1920
- 1080
-
- keep
- 0
-
+ keep
+
+ Picture Information
+ 15
+ 20
+ 1620
+ 180
+ bottom
+ FFFFFFFF
+ FF000000
+
+ headline
+ 30
+ !String.IsEmpty(Window.Property(Screensaver.Headline))
+
+
+
+ caption
+ 30
+ !String.IsEmpty(Window.Property(Screensaver.Caption))
+
+
+
+ location
+ 30
+
+ !String.IsEmpty(Window.Property(Screensaver.Sublocation)) |
+ !String.IsEmpty(Window.Property(Screensaver.City)) |
+ !String.IsEmpty(Window.Property(Screensaver.State)) |
+ !String.IsEmpty(Window.Property(Screensaver.Country))
+
+
+
+
+ date and time
+ 30
+
+ !String.IsEmpty(Window.Property(Screensaver.Date)) |
+ !String.IsEmpty(Window.Property(Screensaver.Time))
+
+
+
+
+ folder and filename
+ 30
+
+ !String.IsEmpty(Window.Property(Screensaver.Folder)) |
+ !IsEmpty(Window.Property(Screensaver.File))
+
+
+
+