The branch, dharma has been updated
via 1953d78e48bcb7441b4394211379fb54653d9dd3 (commit)
from 50efb8f0dbaac1deee0ac181f4ad76e70a553b5a (commit)
- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/plugins;a=commit;h=1953d78e48bcb7441b4394211379fb54653d9dd3
commit 1953d78e48bcb7441b4394211379fb54653d9dd3
Author: spiff <[email protected]>
Date: Fri Feb 3 19:29:29 2012 +0100
[plugin.image.iphoto] updated to version 1.6.0
diff --git a/plugin.image.iphoto/README.txt b/plugin.image.iphoto/README.txt
index f09e245..2315fc0 100644
--- a/plugin.image.iphoto/README.txt
+++ b/plugin.image.iphoto/README.txt
@@ -70,4 +70,14 @@ Known Issues
============
* Sorting by Date sorts on the file date, not the EXIF date.
See http://trac.xbmc.org/ticket/10519
-* Need icons for Faces, Places, and Keywords.
+
+Credits
+=======
+jingai (jingai at floatingpenguins dot com)
+Original code:
+- Anoop Menon
+- Nuka1195
+- JMarshal
+Icons:
+- Firnsy
+- brsev (http://brsev.com#licensing)
diff --git a/plugin.image.iphoto/addon.py b/plugin.image.iphoto/addon.py
index 412778c..430d757 100644
--- a/plugin.image.iphoto/addon.py
+++ b/plugin.image.iphoto/addon.py
@@ -4,7 +4,7 @@
__plugin__ = "iPhoto"
__author__ = "jingai <[email protected]>"
-__credits__ = "Anoop Menon, Nuka1195, JMarshal, jingai"
+__credits__ = "Anoop Menon, Nuka1195, JMarshal, jingai, brsev
(http://brsev.com#licensing)"
__url__ = "git://github.com/jingai/plugin.image.iphoto.git"
import sys
@@ -35,13 +35,14 @@ ALBUM_DATA_XML = "AlbumData.xml"
BASE_URL = "%s" % (sys.argv[0])
PLUGIN_PATH = addon.getAddonInfo("path")
RESOURCE_PATH = os.path.join(PLUGIN_PATH, "resources")
-ICONS_PATH = os.path.join(RESOURCE_PATH, "icons")
+ICONS_THEME = "token_light"
+ICONS_PATH = os.path.join(RESOURCE_PATH, "icons", ICONS_THEME)
LIB_PATH = os.path.join(RESOURCE_PATH, "lib")
sys.path.append(LIB_PATH)
from resources.lib.iphoto_parser import *
db_file = xbmc.translatePath(os.path.join(addon.getAddonInfo("Profile"),
"iphoto.db"))
-db = IPhotoDB(db_file)
+db = None
apple_epoch = 978307200
@@ -122,7 +123,7 @@ def render_media(media):
plugin.addSortMethod(int(sys.argv[1]), plugin.SORT_METHOD_UNSORTED)
plugin.addSortMethod(int(sys.argv[1]), plugin.SORT_METHOD_LABEL)
- if sort_date == True:
+ if (sort_date == True):
plugin.addSortMethod(int(sys.argv[1]), plugin.SORT_METHOD_DATE)
return n
@@ -135,7 +136,7 @@ def list_photos_in_album(params):
return render_media(media)
def list_albums(params):
- global db, BASE_URL, album_ign_empty
+ global db, BASE_URL, ICONS_PATH, album_ign_empty
albumid = 0
try:
@@ -147,6 +148,8 @@ def list_albums(params):
albums = db.GetAlbums()
if (not albums):
+ dialog = gui.Dialog()
+ dialog.ok(addon.getLocalizedString(30240),
addon.getLocalizedString(30241))
return
n = 0
@@ -157,7 +160,7 @@ def list_albums(params):
if (not count and album_ign_empty == "true"):
continue
- item = gui.ListItem(name, thumbnailImage="DefaultFolder.png")
+ item = gui.ListItem(name, thumbnailImage=ICONS_PATH+"/folder.png")
plugin.addDirectoryItem(handle = int(sys.argv[1]),
url=BASE_URL+"?action=albums&albumid=%s" % (albumid), listitem = item, isFolder
= True, totalItems = count)
n += 1
@@ -185,6 +188,8 @@ def list_events(params):
rolls = db.GetRolls()
if (not rolls):
+ dialog = gui.Dialog()
+ dialog.ok(addon.getLocalizedString(30240),
addon.getLocalizedString(30241))
return
sort_date = False
@@ -231,6 +236,8 @@ def list_faces(params):
faces = db.GetFaces()
if (not faces):
+ dialog = gui.Dialog()
+ dialog.ok(addon.getLocalizedString(30240),
addon.getLocalizedString(30241))
return
n = 0
@@ -284,6 +291,8 @@ def list_places(params):
places = db.GetPlaces()
if (not places):
+ dialog = gui.Dialog()
+ dialog.ok(addon.getLocalizedString(30240),
addon.getLocalizedString(30241))
return
n = 0
@@ -321,7 +330,7 @@ def list_photos_with_keyword(params):
return render_media(media)
def list_keywords(params):
- global db, BASE_URL, album_ign_empty
+ global db, BASE_URL, ICONS_PATH, album_ign_empty
keywordid = 0
try:
@@ -333,6 +342,8 @@ def list_keywords(params):
keywords = db.GetKeywords()
if (not keywords):
+ dialog = gui.Dialog()
+ dialog.ok(addon.getLocalizedString(30240),
addon.getLocalizedString(30241))
return
hidden_keywords = addon.getSetting('hidden_keywords')
@@ -345,7 +356,7 @@ def list_keywords(params):
if (not count and album_ign_empty == "true"):
continue
- item = gui.ListItem(name, thumbnailImage="DefaultFolder.png")
+ item = gui.ListItem(name, thumbnailImage=ICONS_PATH+"/folder.png")
item.addContextMenuItems([(addon.getLocalizedString(30214),
"XBMC.RunPlugin(\""+BASE_URL+"?action=hidekeyword&keyword=%s\")" % (name),)])
plugin.addDirectoryItem(handle = int(sys.argv[1]),
url=BASE_URL+"?action=keywords&keywordid=%s" % (keywordid), listitem = item,
isFolder = True, totalItems = count)
n += 1
@@ -384,7 +395,7 @@ def list_ratings(params):
plugin.addSortMethod(int(sys.argv[1]), plugin.SORT_METHOD_LABEL)
return n
-def progress_callback(progress_dialog, altinfo, nphotos, ntotal):
+def import_progress_callback(progress_dialog, altinfo, nphotos, ntotal):
if (not progress_dialog):
return 0
if (progress_dialog.iscanceled()):
@@ -394,11 +405,9 @@ def progress_callback(progress_dialog, altinfo, nphotos,
ntotal):
progress_dialog.update(percent, addon.getLocalizedString(30211) %
(nphotos), altinfo)
return nphotos
-def import_library(xmlpath, xmlfile, enable_places):
+def import_library(xmlpath, xmlfile, masterspath, masters_realpath,
enable_places):
global db
- db.ResetDB()
-
# always ignore Books and currently selected album
album_ign = []
album_ign.append("Book")
@@ -428,27 +437,72 @@ def import_library(xmlpath, xmlfile, enable_places):
elif (e == "false"):
enable_maps = False
+ db.ResetDB()
+
progress_dialog = gui.DialogProgress()
try:
progress_dialog.create(addon.getLocalizedString(30210))
+ progress_dialog.update(0, addon.getLocalizedString(30212))
+ except:
+ print traceback.print_exc()
+ else:
map_aspect = 0.0
if (enable_maps == True):
res_x = float(xbmc.getInfoLabel("System.ScreenWidth"))
res_y = float(xbmc.getInfoLabel("System.ScreenHeight"))
map_aspect = res_x / res_y
- except:
- print traceback.print_exc()
- else:
- iparser = IPhotoParser(xmlpath, xmlfile, album_ign, enable_places,
map_aspect, db.AddAlbumNew, db.AddRollNew, db.AddFaceNew, db.AddKeywordNew,
db.AddMediaNew, progress_callback, progress_dialog)
- progress_dialog.update(0, addon.getLocalizedString(30212))
+ iparser = IPhotoParser(xmlpath, xmlfile, masterspath, masters_realpath,
album_ign, enable_places, map_aspect, db.AddAlbumNew, db.AddRollNew,
db.AddFaceNew, db.AddKeywordNew, db.AddMediaNew, import_progress_callback,
progress_dialog)
+
try:
iparser.Parse()
- db.UpdateLastImport()
except:
print traceback.print_exc()
+ progress_dialog.close()
+ xbmc.executebuiltin("XBMC.RunPlugin(%s?action=resetdb&corrupted=1)"
% (BASE_URL))
+ else:
+ print "iPhoto Library imported successfully."
+
+ progress_dialog.close()
+
+ xbmc.sleep(1000)
+ try:
+ # this is non-critical
+ db.UpdateLastImport()
+ except:
+ pass
+
+def reset_db(params):
+ try:
+ if (params['noconfirm']):
+ confirm = False
+ except:
+ confirm = True
+
+ try:
+ if (params['corrupted']):
+ corrupted = True
+ except:
+ corrupted = False
+
+ confirmed = True
+ if (confirm):
+ dialog = gui.Dialog()
+ if (corrupted):
+ confirmed = dialog.yesno(addon.getLocalizedString(30230),
addon.getLocalizedString(30231), addon.getLocalizedString(30232),
addon.getLocalizedString(30233))
+ else:
+ confirmed = dialog.yesno(addon.getLocalizedString(30230),
addon.getLocalizedString(30232), addon.getLocalizedString(30233))
- progress_dialog.close()
+ if (confirmed):
+ remove_tries = 3
+ while (remove_tries and os.path.isfile(db_file)):
+ try:
+ os.remove(db_file)
+ except:
+ remove_tries -= 1
+ xbmc.sleep(1000)
+ else:
+ print "iPhoto addon database deleted."
def hide_keyword(params):
try:
@@ -477,8 +531,9 @@ def get_params(paramstring):
print params
return params
-def add_import_lib_context_item(item):
+def add_generic_context_menu_items(item):
item.addContextMenuItems([(addon.getLocalizedString(30213),
"XBMC.RunPlugin(\""+BASE_URL+"?action=rescan\")",)])
+ item.addContextMenuItems([(addon.getLocalizedString(30216),
"XBMC.RunPlugin(\""+BASE_URL+"?action=resetdb\")",)])
if (__name__ == "__main__"):
xmlpath = addon.getSetting('albumdata_xml_path')
@@ -497,10 +552,28 @@ if (__name__ == "__main__"):
origxml = os.path.join(xmlpath, ALBUM_DATA_XML)
xmlfile = xbmc.translatePath(os.path.join(addon.getAddonInfo("Profile"),
"iphoto.xml"))
+ enable_managed_lib = True
+ e = addon.getSetting('managed_lib_enable')
+ if (e == ""):
+ addon.setSetting('managed_lib_enable', "true")
+ elif (e == "false"):
+ enable_managed_lib = False
+
+ masterspath = ""
+ masters_realpath = ""
+ if (enable_managed_lib == False):
+ masterspath = addon.getSetting('masters_path')
+ masters_realpath = addon.getSetting('masters_real_path')
+ if (masterspath == "" or masters_realpath == ""):
+ addon.setSetting('managed_lib_enable', "true")
+ enable_managed_lib = True
+ masterspath = ""
+ masters_realpath = ""
+
enable_places = True
e = addon.getSetting('places_enable')
if (e == ""):
- addon.setSetting('places_enable', "True")
+ addon.setSetting('places_enable', "true")
elif (e == "false"):
enable_places = False
@@ -511,28 +584,28 @@ if (__name__ == "__main__"):
# main menu
try:
item = gui.ListItem(addon.getLocalizedString(30100),
thumbnailImage=ICONS_PATH+"/events.png")
- add_import_lib_context_item(item)
+ add_generic_context_menu_items(item)
plugin.addDirectoryItem(int(sys.argv[1]),
BASE_URL+"?action=events", item, True)
item = gui.ListItem(addon.getLocalizedString(30101),
thumbnailImage=ICONS_PATH+"/albums.png")
- add_import_lib_context_item(item)
+ add_generic_context_menu_items(item)
plugin.addDirectoryItem(int(sys.argv[1]),
BASE_URL+"?action=albums", item, True)
item = gui.ListItem(addon.getLocalizedString(30105),
thumbnailImage=ICONS_PATH+"/faces.png")
- add_import_lib_context_item(item)
+ add_generic_context_menu_items(item)
plugin.addDirectoryItem(int(sys.argv[1]), BASE_URL+"?action=faces",
item, True)
item = gui.ListItem(addon.getLocalizedString(30106),
thumbnailImage=ICONS_PATH+"/places.png")
- add_import_lib_context_item(item)
+ add_generic_context_menu_items(item)
item.addContextMenuItems([(addon.getLocalizedString(30215),
"XBMC.RunPlugin(\""+BASE_URL+"?action=rm_caches\")",)])
plugin.addDirectoryItem(int(sys.argv[1]),
BASE_URL+"?action=places", item, True)
item = gui.ListItem(addon.getLocalizedString(30104),
thumbnailImage=ICONS_PATH+"/keywords.png")
- add_import_lib_context_item(item)
+ add_generic_context_menu_items(item)
plugin.addDirectoryItem(int(sys.argv[1]),
BASE_URL+"?action=keywords", item, True)
item = gui.ListItem(addon.getLocalizedString(30102),
thumbnailImage=ICONS_PATH+"/star.png")
- add_import_lib_context_item(item)
+ add_generic_context_menu_items(item)
plugin.addDirectoryItem(int(sys.argv[1]),
BASE_URL+"?action=ratings", item, True)
hide_import_lib = addon.getSetting('hide_import_lib')
@@ -540,7 +613,7 @@ if (__name__ == "__main__"):
hide_import_lib = "false"
addon.setSetting('hide_import_lib', hide_import_lib)
if (hide_import_lib == "false"):
- item = gui.ListItem(addon.getLocalizedString(30103),
thumbnailImage=PLUGIN_PATH+"/icon.png")
+ item = gui.ListItem(addon.getLocalizedString(30103),
thumbnailImage=ICONS_PATH+"/update.png")
plugin.addDirectoryItem(int(sys.argv[1]),
BASE_URL+"?action=rescan", item, False)
except:
plugin.endOfDirectory(int(sys.argv[1]), False)
@@ -560,37 +633,75 @@ if (__name__ == "__main__"):
os.remove(tmpfile)
else:
os.rename(tmpfile, xmlfile)
- import_library(xmlpath, xmlfile, enable_places)
+ try:
+ db = IPhotoDB(db_file)
+ except:
+ dialog = gui.Dialog()
+ dialog.ok(addon.getLocalizedString(30240),
addon.getLocalizedString(30241))
+
xbmc.executebuiltin('XBMC.RunPlugin(%s?action=resetdb&noconfirm=1)' % BASE_URL)
+ else:
+ import_library(xmlpath, xmlfile, masterspath,
masters_realpath, enable_places)
else:
items = None
- if (action == "events"):
- items = list_events(params)
- elif (action == "albums"):
- items = list_albums(params)
- elif (action == "faces"):
- items = list_faces(params)
- elif (action == "places"):
- if (enable_places == True):
- items = list_places(params)
- else:
- dialog = gui.Dialog()
- ret = dialog.yesno(addon.getLocalizedString(30220),
addon.getLocalizedString(30221), addon.getLocalizedString(30222),
addon.getLocalizedString(30223))
- if (ret == True):
- enable_places = True
- addon.setSetting('places_enable', "true")
- elif (action == "keywords"):
- items = list_keywords(params)
- elif (action == "ratings"):
- items = list_ratings(params)
- elif (action == "rescan"):
- copyfile(origxml, xmlfile)
- import_library(xmlpath, xmlfile, enable_places)
+
+ # actions that don't require a database connection
+ if (action == "resetdb"):
+ reset_db(params)
elif (action == "hidekeyword"):
items = hide_keyword(params)
elif (action == "rm_caches"):
- r = glob.glob(os.path.join(os.path.dirname(db_file), "map_*"))
- for f in r:
- os.remove(f)
+ progress_dialog = gui.DialogProgress()
+ try:
+ progress_dialog.create(addon.getLocalizedString(30250))
+ progress_dialog.update(0, addon.getLocalizedString(30252))
+ except:
+ print traceback.print_exc()
+ else:
+ r = glob.glob(os.path.join(os.path.dirname(db_file), "map_*"))
+ ntotal = len(r)
+ nfiles = 0
+ for f in r:
+ if (progress_dialog.iscanceled()):
+ break
+ nfiles += 1
+ percent = int(float(nfiles * 100) / ntotal)
+ progress_dialog.update(percent,
addon.getLocalizedString(30251) % (nfiles), os.path.basename(f))
+ os.remove(f)
+ progress_dialog.close()
+ dialog = gui.Dialog()
+ dialog.ok(addon.getLocalizedString(30250),
addon.getLocalizedString(30251) % (nfiles))
+ print "iPhoto: deleted %d cached map image files." % (nfiles)
+ else:
+ # actions that do require a database connection
+ try:
+ db = IPhotoDB(db_file)
+ except:
+ dialog = gui.Dialog()
+ dialog.ok(addon.getLocalizedString(30240),
addon.getLocalizedString(30241))
+
xbmc.executebuiltin('XBMC.RunPlugin(%s?action=resetdb&noconfirm=1)' % BASE_URL)
+ else:
+ if (action == "rescan"):
+ copyfile(origxml, xmlfile)
+ import_library(xmlpath, xmlfile, masterspath,
masters_realpath, enable_places)
+ elif (action == "events"):
+ items = list_events(params)
+ elif (action == "albums"):
+ items = list_albums(params)
+ elif (action == "faces"):
+ items = list_faces(params)
+ elif (action == "places"):
+ if (enable_places == True):
+ items = list_places(params)
+ else:
+ dialog = gui.Dialog()
+ ret = dialog.yesno(addon.getLocalizedString(30220),
addon.getLocalizedString(30221), addon.getLocalizedString(30222),
addon.getLocalizedString(30223))
+ if (ret == True):
+ enable_places = True
+ addon.setSetting('places_enable', "true")
+ elif (action == "keywords"):
+ items = list_keywords(params)
+ elif (action == "ratings"):
+ items = list_ratings(params)
if (items):
plugin.endOfDirectory(int(sys.argv[1]), True)
diff --git a/plugin.image.iphoto/addon.xml b/plugin.image.iphoto/addon.xml
index bd0d4f3..da4fd88 100644
--- a/plugin.image.iphoto/addon.xml
+++ b/plugin.image.iphoto/addon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="plugin.image.iphoto" name="iPhoto" version="1.4.6"
provider-name="jingai">
+<addon id="plugin.image.iphoto" name="iPhoto" version="1.6.0"
provider-name="jingai">
<requires>
<import addon="xbmc.python" version="1.0"/>
<import addon="script.module.pysqlite" version="2.5.6"/>
diff --git a/plugin.image.iphoto/changelog.txt
b/plugin.image.iphoto/changelog.txt
index 07dcc35..749e3ba 100644
--- a/plugin.image.iphoto/changelog.txt
+++ b/plugin.image.iphoto/changelog.txt
@@ -1,3 +1,10 @@
+1.6.0 - 20120202
+- Support for referenced masters.
+- Add context menu item to reset addon database.
+- Better database error handling and reporting.
+- Show progress dialog when removing cached maps.
+- New icons.
+
1.4.6 - 20110705
- Don't show empty events.
diff --git a/plugin.image.iphoto/resources/language/English/strings.xml
b/plugin.image.iphoto/resources/language/English/strings.xml
index c82b297..d1ea841 100644
--- a/plugin.image.iphoto/resources/language/English/strings.xml
+++ b/plugin.image.iphoto/resources/language/English/strings.xml
@@ -8,10 +8,20 @@
<string id="30213">Update library</string>
<string id="30214">Ignore Keyword</string>
<string id="30215">Remove cached maps</string>
+ <string id="30216">Reset addon database</string>
<string id="30220">Enable Support for Places?</string>
<string id="30221">Places looks up addresses via Google.</string>
<string id="30222">This can slow down the library import a bit.</string>
<string id="30223">You will also need to reimport your library.</string>
+ <string id="30230">Delete iPhoto addon database?</string>
+ <string id="30231">Addon database is corrupt.</string>
+ <string id="30232">Deleting it will not harm your iPhoto Library.</string>
+ <string id="30233">You will need to rescan after this.</string>
+ <string id="30240">Failed to initialize addon database.</string>
+ <string id="30241">Please reimport your iPhoto Library.</string>
+ <string id="30250">Deleting cached map images</string>
+ <string id="30251">Deleted %d cached maps</string>
+ <string id="30252">Scanning...</string>
<!-- Category strings -->
<string id="30100">Events</string>
@@ -43,6 +53,9 @@
<string id="30022">XML Date</string>
<string id="30025">Download maps from Google</string>
<string id="30026">Show map as fanart</string>
+ <string id="30027">Managed Library (change requires rescan)</string>
+ <string id="30028">Local root path to Masters</string>
+ <string id="30029">Rewrite root path as</string>
<!-- Plugin settings categories strings -->
<string id="30050">General</string>
diff --git a/plugin.image.iphoto/resources/lib/iphoto_parser.py
b/plugin.image.iphoto/resources/lib/iphoto_parser.py
index c7ace2d..75f842b 100644
--- a/plugin.image.iphoto/resources/lib/iphoto_parser.py
+++ b/plugin.image.iphoto/resources/lib/iphoto_parser.py
@@ -65,26 +65,17 @@ class IPhotoDB:
self.dbconn = sqlite.connect(dbfile)
self.InitDB()
except Exception, e:
- print to_str(e)
- pass
- return
+ print "iphoto.db: init: " + to_str(e)
+ raise e
- def _cleanup_filename(self, filename):
- if (filename.startswith("file://localhost")):
- return unquote(filename[16:])
- else:
- return unquote(filename)
+ return
def InitDB(self):
- try:
- self.dbconn.execute("PRAGMA synchronous = OFF")
- self.dbconn.execute("PRAGMA default_synchronous = OFF")
- self.dbconn.execute("PRAGMA journal_mode = OFF")
- self.dbconn.execute("PRAGMA temp_store = MEMORY")
- self.dbconn.execute("PRAGMA encoding = \"UTF-8\"")
- except Exception, e:
- print to_str(e)
- pass
+ self.dbconn.execute("PRAGMA synchronous = OFF")
+ self.dbconn.execute("PRAGMA default_synchronous = OFF")
+ self.dbconn.execute("PRAGMA journal_mode = OFF")
+ self.dbconn.execute("PRAGMA temp_store = MEMORY")
+ self.dbconn.execute("PRAGMA encoding = \"UTF-8\"")
try:
# config table
@@ -148,7 +139,7 @@ class IPhotoDB:
rollid integer,
mediaid integer
)""")
- except Exception, e:
+ except:
pass
try:
@@ -171,7 +162,7 @@ class IPhotoDB:
albumid integer,
mediaid integer
)""")
- except Exception, e:
+ except:
pass
try:
@@ -196,7 +187,7 @@ class IPhotoDB:
faceid integer,
mediaid integer
)""")
- except Exception, e:
+ except:
pass
try:
@@ -220,7 +211,7 @@ class IPhotoDB:
placeid integer,
mediaid integer
)""")
- except Exception, e:
+ except:
pass
try:
@@ -241,7 +232,7 @@ class IPhotoDB:
keywordid integer,
mediaid integer
)""")
- except Exception, e:
+ except:
pass
def ResetDB(self):
@@ -249,20 +240,17 @@ class IPhotoDB:
try:
self.dbconn.execute("DROP TABLE %s" % table)
except Exception, e:
- print to_str(e)
- pass
- try:
- self.InitDB()
- except Exception, e:
- print to_str(e)
- raise e
+ print "iphoto.db: ResetDB: " + to_str(e)
+ raise e
+
+ self.InitDB()
def Commit(self):
try:
self.dbconn.commit()
except Exception, e:
- print "Commit Error: " + to_str(e)
- pass
+ print "iphoto.db: Commit: " + to_str(e)
+ raise e
def GetConfig(self, key):
try:
@@ -272,24 +260,29 @@ class IPhotoDB:
cur.close()
if (row):
return row[0]
- return None
except:
- return None
+ pass
+
+ return None
def SetConfig(self, key, value):
if (self.GetConfig(key) == None):
self.dbconn.execute("""INSERT INTO config (key, value) VALUES (?,
?)""", (key, value))
else:
self.dbconn.execute("""UPDATE config SET value = ? WHERE key =
?""", (value, key))
+
self.Commit()
def UpdateLastImport(self):
- self.SetConfig('lastimport', 'dummy')
- self.dbconn.execute("""UPDATE config
- SET value = datetime('now')
- WHERE key = ?""",
- ('lastimport',))
- self.Commit()
+ try:
+ self.SetConfig('lastimport', 'dummy')
+ self.dbconn.execute("""UPDATE config
+ SET value = datetime('now')
+ WHERE key = ?""",
+ ('lastimport',))
+ self.Commit()
+ except Exception, e:
+ print "iphoto.db: UpdateLastImport: " + to_str(e)
def GetTableId(self, table, value, column='name', autoadd=False,
autoclean=True):
try:
@@ -317,7 +310,7 @@ class IPhotoDB:
cur.close()
return row[0] # return id
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetTableId: " + to_str(e)
raise e
def GetMediaTypeId(self, mediatype, autoadd=False):
@@ -331,8 +324,10 @@ class IPhotoDB:
for tuple in cur:
albums.append(tuple)
cur.close()
- except:
+ except Exception, e:
+ print "iphoto.db: GetAlbums: " + to_str(e)
pass
+
return albums
def GetMediaInAlbum(self, albumid, sort_col="NULL"):
@@ -348,8 +343,9 @@ class IPhotoDB:
media.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetMediaInAlbum: " + to_str(e)
pass
+
return media
def GetRolls(self):
@@ -362,7 +358,7 @@ class IPhotoDB:
rolls.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetRolls: " + to_str(e)
pass
return rolls
@@ -378,8 +374,9 @@ class IPhotoDB:
media.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetMediaInRoll: " + to_str(e)
pass
+
return media
def GetFaces(self):
@@ -393,8 +390,9 @@ class IPhotoDB:
faces.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetFaces: " + to_str(e)
pass
+
return faces
def GetMediaWithFace(self, faceid, sort_col="NULL"):
@@ -410,8 +408,9 @@ class IPhotoDB:
media.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetMediaWithFace: " + to_str(e)
pass
+
return media
def GetPlaces(self):
@@ -423,8 +422,9 @@ class IPhotoDB:
places.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetPlaces: " + to_str(e)
pass
+
return places
def GetMediaWithPlace(self, placeid, sort_col="NULL"):
@@ -440,8 +440,9 @@ class IPhotoDB:
media.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetMediaWithPlace: " + to_str(e)
pass
+
return media
def GetKeywords(self):
@@ -453,8 +454,9 @@ class IPhotoDB:
keywords.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetKeywords: " + to_str(e)
pass
+
return keywords
def GetMediaWithKeyword(self, keywordid, sort_col="NULL"):
@@ -470,8 +472,9 @@ class IPhotoDB:
media.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetMediaWithKeyword: " + to_str(e)
pass
+
return media
def GetMediaWithRating(self, rating, sort_col="NULL"):
@@ -486,8 +489,9 @@ class IPhotoDB:
media.append(tuple)
cur.close()
except Exception, e:
- print to_str(e)
+ print "iphoto.db: GetMediaWithRating: " + to_str(e)
pass
+
return media
def AddAlbumNew(self, album, album_ign):
@@ -590,7 +594,7 @@ class IPhotoDB:
except Exception, e:
raise e
- def AddMediaNew(self, media, archivePath, libraryPath, enablePlaces,
mapAspect, updateProgress):
+ def AddMediaNew(self, media, archivePath, libraryPath, mastersPath,
mastersRealPath, enablePlaces, mapAspect, updateProgress):
#print "AddMediaNew()", media
try:
@@ -604,9 +608,13 @@ class IPhotoDB:
# if the iPhoto library is mounted as a share, the paths in
# AlbumData.xml probably won't be right.
if (archivePath and libraryPath):
- imagepath = media['ImagePath'].replace(archivePath, libraryPath)
thumbpath = media['ThumbPath'].replace(archivePath, libraryPath)
- originalpath = media['OriginalPath'].replace(archivePath,
libraryPath)
+ if (mastersPath and mastersRealPath):
+ imagepath = media['ImagePath'].replace(mastersPath,
mastersRealPath)
+ originalpath = media['OriginalPath'].replace(mastersPath,
mastersRealPath)
+ else:
+ imagepath = media['ImagePath'].replace(archivePath, libraryPath)
+ originalpath = media['OriginalPath'].replace(archivePath,
libraryPath)
else:
imagepath = media['ImagePath']
thumbpath = media['ThumbPath']
@@ -691,8 +699,10 @@ class IPhotoDB:
placeid = len(self.placeList)
self.placeList[placeid] = []
#print "new placeid %d for addr '%s'" %
(placeid, addr)
+ except ParseCanceled:
+ raise
except Exception, e:
- print to_str(e)
+ print "iphoto.db: AddMediaNew: geocode: " + to_str(e)
raise e
except:
#print "No location information for photo id %d" % (mediaid)
@@ -716,15 +726,15 @@ class IPhotoDB:
map.zoom("", 14)
thumbpath = map.fetch("map_", "_thumb")
except Exception, e:
- print to_str(e)
+ print "iphoto.db: AddMediaNew: map: " +
to_str(e)
pass
updateProgress()
# add new Place
self.placeList[placeid].append(addr)
cur.execute("""
- INSERT INTO places (id, latlon, address, thumbpath,
fanartpath)
- VALUES (?, ?, ?, ?, ?)""", (placeid, latlon, addr,
thumbpath, fanartpath))
+ INSERT INTO places (id, latlon, address,
thumbpath, fanartpath)
+ VALUES (?, ?, ?, ?, ?)""", (placeid,
latlon, addr, thumbpath, fanartpath))
if (latlon not in self.placeList[placeid]):
# existing Place, but add latlon to list for this
address.
@@ -733,8 +743,8 @@ class IPhotoDB:
self.placeList[placeid].append(latlon)
cur.execute("""
- INSERT INTO placesmedia (placeid, mediaid)
- VALUES (?, ?)""", (placeid, mediaid))
+ INSERT INTO placesmedia (placeid, mediaid)
+ VALUES (?, ?)""", (placeid, mediaid))
cur.execute("""SELECT id, photocount
FROM places
WHERE id = ?""", (placeid,))
@@ -744,13 +754,13 @@ class IPhotoDB:
else:
photocount = 1
self.dbconn.execute("""
- UPDATE places SET photocount = ?
- WHERE id = ?""", (photocount, placeid))
+ UPDATE places SET photocount = ?
+ WHERE id = ?""", (photocount,
placeid))
for keywordid in media['keywordlist']:
cur.execute("""
- INSERT INTO keywordmedia (keywordid, mediaid)
- VALUES (?, ?)""", (keywordid, mediaid))
+ INSERT INTO keywordmedia (keywordid, mediaid)
+ VALUES (?, ?)""", (keywordid, mediaid))
cur.execute("""SELECT id, photocount
FROM keywords
WHERE id = ?""", (keywordid,))
@@ -800,11 +810,20 @@ class IPhotoParserState:
self.valueType = ""
class IPhotoParser:
- def __init__(self, library_path="", xmlfile="", album_ign=[],
enable_places=False, map_aspect=0.0,
+ def __init__(self, library_path="", xmlfile="", masters_path="",
masters_real_path="",
+ album_ign=[], enable_places=False, map_aspect=0.0,
album_callback=None, roll_callback=None, face_callback=None,
keyword_callback=None, photo_callback=None,
progress_callback=None, progress_dialog=None):
self.libraryPath = library_path
self.xmlfile = xmlfile
+ self.mastersPath = masters_path
+ self.mastersRealPath = masters_real_path
+ if (self.mastersPath and self.mastersRealPath):
+ try:
+ print "Rewriting referenced masters path '%s'" %
(to_str(self.mastersPath))
+ print "as '%s'" % (to_str(self.mastersRealPath))
+ except:
+ pass
self.imagePath = ""
self.parser = xml.parsers.expat.ParserCreate()
self.parser.StartElementHandler = self.StartElement
@@ -882,7 +901,7 @@ class IPhotoParser:
state = self.state
ret = self.ProgressCallback(self.ProgressDialog, altinfo,
state.nphotos, state.nphotostotal)
if (ret == None):
- raise ParseCanceled(0)
+ raise ParseCanceled("iPhoto library parse canceled by user.")
def commitAll(self):
state = self.state
@@ -916,13 +935,13 @@ class IPhotoParser:
if (self.PhotoCallback and len(self.photoList) > 0):
for a in self.photoList:
- self.PhotoCallback(a, self.imagePath, self.libraryPath,
self.enablePlaces, self.mapAspect, self.updateProgress)
+ self.PhotoCallback(a, self.imagePath, self.libraryPath,
self.mastersPath, self.mastersRealPath, self.enablePlaces, self.mapAspect,
self.updateProgress)
state.nphotos += 1
self.updateProgress()
except ParseCanceled:
raise
except Exception, e:
- print to_str(e)
+ print "iphoto.db: commitAll: " + to_str(e)
raise e
def Parse(self):
@@ -935,18 +954,14 @@ class IPhotoParser:
buf = f.read(BLOCKSIZE)
self.parser.Parse(buf, True)
f.close()
- except ParseCanceled:
- return
except Exception, e:
- print to_str(e)
+ print "iphoto.db: Parse: " + to_str(e)
raise e
try:
self.commitAll()
- except ParseCanceled:
- return
except Exception, e:
- print to_str(e)
+ print "iphoto.db: Parse: " + to_str(e)
raise e
def StartElement(self, name, attrs):
@@ -992,9 +1007,13 @@ class IPhotoParser:
if (state.archivepath):
if (not state.key):
self.imagePath = state.value
- print "Rewriting iPhoto archive path '%s'" %
(to_str(self.imagePath))
- print "as '%s'" % (to_str(self.libraryPath))
state.archivepath = False
+ if (self.imagePath != self.libraryPath):
+ try:
+ print "Rewriting iPhoto archive path '%s'" %
(to_str(self.imagePath))
+ print "as '%s'" % (to_str(self.libraryPath))
+ except:
+ pass
state.inarchivepath -= 1
# Albums
@@ -1148,7 +1167,7 @@ def main():
db = IPhotoDB(dbfile)
db.ResetDB()
- iparser = IPhotoParser("", xmlfile, "", False, 0.0, db.AddAlbumNew,
db.AddRollNew, db.AddFaceNew, db.AddKeywordNew, db.AddMediaNew,
test_progress_callback)
+ iparser = IPhotoParser("", xmlfile, "", "", "", False, 0.0,
db.AddAlbumNew, db.AddRollNew, db.AddFaceNew, db.AddKeywordNew, db.AddMediaNew,
test_progress_callback)
try:
iparser.Parse()
except:
diff --git a/plugin.image.iphoto/resources/settings.xml
b/plugin.image.iphoto/resources/settings.xml
index 9860f4e..cbde507 100644
--- a/plugin.image.iphoto/resources/settings.xml
+++ b/plugin.image.iphoto/resources/settings.xml
@@ -3,6 +3,9 @@
<!-- General -->
<category label="30050">
<setting id="albumdata_xml_path" type="folder" source="video"
label="30000" default=""/>
+ <setting id="managed_lib_enable" type="bool" label="30027"
default="true"/>
+ <setting id="masters_path" type="text" label="30028"
default="/Volumes/Pictures/" enable="eq(-1,false)"/>
+ <setting id="masters_real_path" type="folder" source="video"
label="30029" default="" enable="eq(-2,false)"/>
<setting id="places_enable" type="bool" label="30015" default="true"/>
<setting id="places_enable_maps" type="bool" label="30025"
default="true" enable="eq(-1,true)"/>
<setting id="auto_update_lib" type="bool" label="30003"
default="false"/>
-----------------------------------------------------------------------
Summary of changes:
plugin.image.iphoto/README.txt | 12 +-
plugin.image.iphoto/addon.py | 219 +++++++++++++++-----
plugin.image.iphoto/addon.xml | 2 +-
plugin.image.iphoto/changelog.txt | 7 +
.../resources/icons/token_dark/albums.png | Bin 0 -> 10133 bytes
.../resources/icons/token_dark/events.png | Bin 0 -> 16644 bytes
.../resources/icons/token_dark/faces.png | Bin 0 -> 14618 bytes
.../resources/icons/token_dark/folder.png | Bin 0 -> 8805 bytes
.../resources/icons/token_dark/keywords.png | Bin 0 -> 19005 bytes
.../resources/icons/token_dark/places.png | Bin 0 -> 28781 bytes
.../resources/icons/token_dark/star.png | Bin 0 -> 16273 bytes
.../resources/icons/token_dark/star1.png | Bin 0 -> 11734 bytes
.../resources/icons/token_dark/star2.png | Bin 0 -> 14109 bytes
.../resources/icons/token_dark/star3.png | Bin 0 -> 15557 bytes
.../resources/icons/token_dark/star4.png | Bin 0 -> 17005 bytes
.../resources/icons/token_dark/star5.png | Bin 0 -> 16273 bytes
.../resources/icons/token_dark/update.png | Bin 0 -> 19317 bytes
.../resources/icons/token_light/albums.png | Bin 0 -> 10690 bytes
.../resources/icons/token_light/events.png | Bin 0 -> 15375 bytes
.../resources/icons/token_light/faces.png | Bin 0 -> 16527 bytes
.../resources/icons/token_light/folder.png | Bin 0 -> 8763 bytes
.../resources/icons/token_light/keywords.png | Bin 0 -> 21329 bytes
.../resources/icons/token_light/places.png | Bin 0 -> 31444 bytes
.../resources/icons/token_light/star.png | Bin 0 -> 16990 bytes
.../resources/icons/token_light/star1.png | Bin 0 -> 12373 bytes
.../resources/icons/token_light/star2.png | Bin 0 -> 14720 bytes
.../resources/icons/token_light/star3.png | Bin 0 -> 16275 bytes
.../resources/icons/token_light/star4.png | Bin 0 -> 17301 bytes
.../resources/icons/token_light/star5.png | Bin 0 -> 16990 bytes
.../resources/icons/token_light/update.png | Bin 0 -> 22081 bytes
.../resources/language/English/strings.xml | 13 ++
plugin.image.iphoto/resources/lib/iphoto_parser.py | 173 +++++++++-------
plugin.image.iphoto/resources/settings.xml | 3 +
33 files changed, 296 insertions(+), 133 deletions(-)
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/albums.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/events.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/faces.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/folder.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/keywords.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/places.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/star.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/star1.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/star2.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/star3.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/star4.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/star5.png
create mode 100644 plugin.image.iphoto/resources/icons/token_dark/update.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/albums.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/events.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/faces.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/folder.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/keywords.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/places.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/star.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/star1.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/star2.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/star3.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/star4.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/star5.png
create mode 100644 plugin.image.iphoto/resources/icons/token_light/update.png
hooks/post-receive
--
Plugins
------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons