Initial support for live photos (Photos 5 only)
This commit is contained in:
@@ -114,7 +114,8 @@ class PhotoInfo:
|
|||||||
def path_edited(self):
|
def path_edited(self):
|
||||||
""" absolute path on disk of the edited picture """
|
""" absolute path on disk of the edited picture """
|
||||||
""" None if photo has not been edited """
|
""" None if photo has not been edited """
|
||||||
photopath = ""
|
|
||||||
|
photopath = None
|
||||||
|
|
||||||
if self._db._db_version < _PHOTOS_5_VERSION:
|
if self._db._db_version < _PHOTOS_5_VERSION:
|
||||||
if self._info["hasAdjustments"]:
|
if self._info["hasAdjustments"]:
|
||||||
@@ -329,6 +330,41 @@ class PhotoInfo:
|
|||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def live_photo(self):
|
||||||
|
""" Returns True if photo is a live photo, otherwise False """
|
||||||
|
# TODO: fixme for Photos 4
|
||||||
|
if self._db._db_version >= _PHOTOS_5_VERSION:
|
||||||
|
return self._info["live_photo"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path_live_photo(self):
|
||||||
|
""" Returns path to the associated video file for a live photo
|
||||||
|
If photo is not a live photo, returns None
|
||||||
|
If photo is missing, returns None """
|
||||||
|
|
||||||
|
photopath = None
|
||||||
|
# TODO: fixme for Photos 4
|
||||||
|
if self._db._db_version < _PHOTOS_5_VERSION:
|
||||||
|
photopath = None
|
||||||
|
else:
|
||||||
|
if self.live_photo and not self.ismissing:
|
||||||
|
filename = pathlib.Path(self.path)
|
||||||
|
photopath = filename.parent.joinpath(f"{filename.stem}_3.mov")
|
||||||
|
if not os.path.isfile(photopath):
|
||||||
|
photopath = None
|
||||||
|
# In testing, I've seen occasional missing movie for live photo
|
||||||
|
# TODO: should this be a warning or debug?
|
||||||
|
logging.debug(
|
||||||
|
f"live photo path for UUID {self._uuid} should be at {photopath} but does not appear to exist"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
photopath = None
|
||||||
|
|
||||||
|
return photopath
|
||||||
|
|
||||||
def export(
|
def export(
|
||||||
self,
|
self,
|
||||||
dest,
|
dest,
|
||||||
|
|||||||
@@ -851,7 +851,8 @@ class PhotosDB:
|
|||||||
ZGENERICASSET.ZKIND,
|
ZGENERICASSET.ZKIND,
|
||||||
ZGENERICASSET.ZUNIFORMTYPEIDENTIFIER,
|
ZGENERICASSET.ZUNIFORMTYPEIDENTIFIER,
|
||||||
ZGENERICASSET.ZAVALANCHEUUID,
|
ZGENERICASSET.ZAVALANCHEUUID,
|
||||||
ZGENERICASSET.ZAVALANCHEPICKTYPE
|
ZGENERICASSET.ZAVALANCHEPICKTYPE,
|
||||||
|
ZGENERICASSET.ZKINDSUBTYPE
|
||||||
FROM ZGENERICASSET
|
FROM ZGENERICASSET
|
||||||
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK
|
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK
|
||||||
WHERE ZGENERICASSET.ZTRASHEDSTATE = 0
|
WHERE ZGENERICASSET.ZTRASHEDSTATE = 0
|
||||||
@@ -879,6 +880,8 @@ class PhotosDB:
|
|||||||
# 18 ZUNIFORMTYPEIDENTIFIER -- UTI
|
# 18 ZUNIFORMTYPEIDENTIFIER -- UTI
|
||||||
# 19 ZGENERICASSET.ZAVALANCHEUUID, -- if not NULL, is burst photo
|
# 19 ZGENERICASSET.ZAVALANCHEUUID, -- if not NULL, is burst photo
|
||||||
# 20 ZGENERICASSET.ZAVALANCHEPICKTYPE -- if not 2, is a selected burst photo
|
# 20 ZGENERICASSET.ZAVALANCHEPICKTYPE -- if not 2, is a selected burst photo
|
||||||
|
# 21 ZGENERICASSET.ZKINDSUBTYPE
|
||||||
|
|
||||||
|
|
||||||
for row in c:
|
for row in c:
|
||||||
uuid = row[0]
|
uuid = row[0]
|
||||||
@@ -957,6 +960,10 @@ class PhotosDB:
|
|||||||
info["burst"] = False
|
info["burst"] = False
|
||||||
info["burst_key"] = None
|
info["burst_key"] = None
|
||||||
|
|
||||||
|
# Info on sub-type (live photo, panorama, etc)
|
||||||
|
info["subtype"] = row[21]
|
||||||
|
info["live_photo"] = True if row[21] == 2 else False
|
||||||
|
|
||||||
self._dbphotos[uuid] = info
|
self._dbphotos[uuid] = info
|
||||||
|
|
||||||
# # if row[19] is not None and ((row[20] == 2) or (row[20] == 4)):
|
# # if row[19] is not None and ((row[20] == 2) or (row[20] == 4)):
|
||||||
|
|||||||
Reference in New Issue
Block a user