ordigi/elodie/media/media.py

184 lines
5.3 KiB
Python
Raw Normal View History

2015-10-07 08:47:51 +02:00
"""
The media module provides a base :class:`Media` class for media objects that
2016-01-08 23:49:06 +01:00
are tracked by Elodie. The Media class provides some base functionality used
by all the media types, but isn't itself used to represent anything. Its
sub-classes (:class:`~elodie.media.audio.Audio`,
:class:`~elodie.media.photo.Photo`, and :class:`~elodie.media.video.Video`)
are used to represent the actual files.
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
2015-10-07 08:47:51 +02:00
"""
# load modules
from elodie import constants
from elodie.dependencies import get_exiftool
from elodie.media.base import Base
2015-10-07 08:47:51 +02:00
import os
import pyexiv2
2015-10-07 08:47:51 +02:00
import re
import subprocess
class Media(Base):
2016-01-08 23:49:06 +01:00
"""The base class for all media objects.
:param str source: The fully qualified path to the video file.
2015-10-07 08:47:51 +02:00
"""
2016-01-08 23:49:06 +01:00
__name__ = 'Media'
2016-02-12 20:22:26 +01:00
d_coordinates = {
'latitude': 'latitude_ref',
'longitude': 'longitude_ref'
}
2016-02-12 20:22:26 +01:00
2015-10-07 08:47:51 +02:00
def __init__(self, source=None):
super(Media, self).__init__(source)
self.exif_map = {
2016-03-23 08:09:25 +01:00
'date_taken': ['Exif.Photo.DateTimeOriginal', 'Exif.Image.DateTime', 'Exif.Photo.DateTimeDigitized'], # , 'EXIF FileDateTime'], # noqa
'latitude': 'Exif.GPSInfo.GPSLatitude',
'latitude_ref': 'Exif.GPSInfo.GPSLatitudeRef',
'longitude': 'Exif.GPSInfo.GPSLongitude',
'longitude_ref': 'Exif.GPSInfo.GPSLongitudeRef',
}
def get_album(self):
2016-01-08 23:49:06 +01:00
"""Get album from EXIF
:returns: None or string
"""
if(not self.is_valid()):
return None
exiftool_attributes = self.get_exiftool_attributes()
2015-11-02 11:11:53 +01:00
if(exiftool_attributes is None or 'album' not in exiftool_attributes):
return None
return exiftool_attributes['album']
2015-10-07 08:47:51 +02:00
def get_exif(self):
2016-01-08 23:49:06 +01:00
"""Read EXIF from a photo file.
We store the result in a member variable so we can call get_exif()
often without performance degredation.
:returns: list or none for a non-photo file
"""
if(not self.is_valid()):
return None
if(self.exif is not None):
return self.exif
source = self.source
self.exif = pyexiv2.ImageMetadata(source)
self.exif.read()
return self.exif
def get_exiftool_attributes(self):
2016-01-08 23:49:06 +01:00
"""Get attributes for the media object from exiftool.
:returns: dict, or False if exiftool was not available.
"""
if(self.exiftool_attributes is not None):
return self.exiftool_attributes
exiftool = get_exiftool()
if(exiftool is None):
return False
source = self.source
process_output = subprocess.Popen(
'%s "%s"' % (exiftool, source),
stdout=subprocess.PIPE,
2016-01-26 20:01:05 +01:00
shell=True,
universal_newlines=True
)
output = process_output.stdout.read()
# Get album from exiftool output
album = None
album_regex = re.search('Album +: +(.+)', output)
if(album_regex is not None):
album = album_regex.group(1)
# Get title from exiftool output
title = None
for key in ['Displayname', 'Headline', 'Title', 'ImageDescription']:
title_regex = re.search('%s +: +(.+)' % key, output)
if(title_regex is not None):
title_return = title_regex.group(1).strip()
if(len(title_return) > 0):
title = title_return
break
self.exiftool_attributes = {
'album': album,
'title': title
}
return self.exiftool_attributes
def get_title(self):
2016-01-08 23:49:06 +01:00
"""Get the title for a photo of video
:returns: str or None if no title is set or not a valid media type
"""
if(not self.is_valid()):
return None
exiftool_attributes = self.get_exiftool_attributes()
2015-11-02 11:11:53 +01:00
if(exiftool_attributes is None or 'title' not in exiftool_attributes):
return None
return exiftool_attributes['title']
def reset_cache(self):
"""Resets any internal cache
"""
self.exiftool_attributes = None
super(Media, self).reset_cache()
def set_album(self, name):
2016-01-08 23:49:06 +01:00
"""Set album for a photo
:param str name: Name of album
:returns: bool
"""
if(name is None):
return False
exiftool = get_exiftool()
if(exiftool is None):
return False
source = self.source
stat = os.stat(source)
exiftool_config = constants.exiftool_config
if(constants.debug is True):
print '%s -config "%s" -xmp-elodie:Album="%s" "%s"' % (exiftool, exiftool_config, name, source) # noqa
process_output = subprocess.Popen(
'%s -config "%s" -xmp-elodie:Album="%s" "%s"' %
(exiftool, exiftool_config, name, source),
stdout=subprocess.PIPE,
shell=True
)
process_output.communicate()
if(process_output.returncode != 0):
return False
os.utime(source, (stat.st_atime, stat.st_mtime))
2015-10-26 10:06:48 +01:00
exiftool_backup_file = '%s%s' % (source, '_original')
if(os.path.isfile(exiftool_backup_file) is True):
os.remove(exiftool_backup_file)
self.set_metadata(album=name)
self.reset_cache()
return True