diff options
Diffstat (limited to 'rapid/media.py')
-rwxr-xr-x | rapid/media.py | 339 |
1 files changed, 0 insertions, 339 deletions
diff --git a/rapid/media.py b/rapid/media.py deleted file mode 100755 index 9819ab7..0000000 --- a/rapid/media.py +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/bin/python -# -*- coding: latin1 -*- - -### Copyright (C) 2007, 2008, 2009, 2010 Damon Lynch <damonlynch@gmail.com> - -### This program is free software; you can redistribute it and/or modify -### it under the terms of the GNU General Public License as published by -### the Free Software Foundation; either version 2 of the License, or -### (at your option) any later version. - -### This program is distributed in the hope that it will be useful, -### but WITHOUT ANY WARRANTY; without even the implied warranty of -### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -### GNU General Public License for more details. - -### You should have received a copy of the GNU General Public License -### along with this program; if not, write to the Free Software -### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import os -import sys -import types -import datetime -import subprocess - -import config -from config import max_thumbnail_size -from config import STATUS_NOT_DOWNLOADED, \ - STATUS_DOWNLOAD_PENDING, \ - STATUS_CANNOT_DOWNLOAD - - -import common -import metadata -import videometadata - -from common import Configi18n -global _ -_ = Configi18n._ - -import operator -import gtk - -def _getDefaultLocationLegacy(options, ignore_missing_dir=False): - if ignore_missing_dir: - return common.getFullPath(options[0]) - for default in options: - path = common.getFullPath(default) - if os.path.isdir(path): - return path - return common.getFullPath('') - -def _getDefaultLocationXDG(dir_type): - proc = subprocess.Popen(['xdg-user-dir', dir_type], stdout=subprocess.PIPE) - output = proc.communicate()[0].strip() - return output - -def getDefaultPhotoLocation(ignore_missing_dir=False): - try: - return _getDefaultLocationXDG('PICTURES') - except: - return _getDefaultLocationLegacy(config.DEFAULT_PHOTO_LOCATIONS, ignore_missing_dir) - -def getDefaultVideoLocation(ignore_missing_dir=False): - try: - return _getDefaultLocationXDG('VIDEOS') - except: - return _getDefaultLocationLegacy(config.DEFAULT_VIDEO_LOCATIONS, ignore_missing_dir) - -def getDefaultBackupPhotoIdentifier(): - return os.path.split(getDefaultPhotoLocation(ignore_missing_dir = True))[1] - -def getDefaultBackupVideoIdentifier(): - return os.path.split(getDefaultVideoLocation(ignore_missing_dir = True))[1] - -def is_DCIM_Media(path): - """ Returns true if directory specifies some media with photos on it """ - - if os.path.isdir(os.path.join(path, "DCIM")): - # is very likely a memory card, or something like that! - return True - else: - return False - - -def isBackupMedia(path, identifiers, writeable=True): - """ Test to see if path is used as a backup medium for storing photos or videos - - Identifiers is expected to be a list of folder names to check to see - if the path is a backup path. Only one of them needs to be present - for the path to be considered a backup medium. - - If writeable is True, the directory must be writeable by the user """ - suitable = False - - for identifier in identifiers: - if os.path.isdir(os.path.join(path, identifier)): - if writeable: - suitable = os.access(os.path.join(path, identifier), os.W_OK) - else: - suitable = True - if suitable: - return True - return False - -def isImage(fileName): - ext = os.path.splitext(fileName)[1].lower()[1:] - return (ext in metadata.RAW_FILE_EXTENSIONS) or (ext in metadata.NON_RAW_IMAGE_FILE_EXTENSIONS) - -def isVideo(fileName): - ext = os.path.splitext(fileName)[1].lower()[1:] - return (ext in videometadata.VIDEO_FILE_EXTENSIONS) - - -class MediaFile: - """ - A photo or video file, with metadata - """ - - def __init__(self, thread_id, name, path, size, fileSystemModificationTime, deviceName, downloadFolder, volume, isPhoto = True): - self.thread_id = thread_id - self.path = path - self.name = name - self.fullFileName = os.path.join(path, name) - self.size = size # type int - self.modificationTime = fileSystemModificationTime - self.deviceName = deviceName - self.downloadFolder = downloadFolder - self.volume = volume - - self.jobcode = '' - - # a reference into the SelectionTreeView's liststore - self.treerowref = None - - # generated values - self.downloadSubfolder = '' - self.downloadPath = '' - self.downloadName = '' - self.downloadFullFileName = '' - - self.isImage = isPhoto - self.isVideo = not self.isImage - if isPhoto: - self.displayName = _("photo") - self.displayNameCap = _("Photo") - else: - self.displayName = _("video") - self.displayNameCap = _("Video") - - - self.metadata = None - self.thumbnail = None - self.genericThumbnail = False - self.sampleName = '' - self.sampleSubfolder = '' - self.samplePath = '' - - # whether the sample genereated name, subfolder and path need to be refreshed in a preview - self.sampleStale = False - - self.status = STATUS_NOT_DOWNLOADED - self.problem = None # class Problem in problemnotifcation.py - - def loadMetadata(self): - """ - Attempt to load the metadata for the photo or video - - Raises errors if unable to be loaded - """ - if not self.metadata: - if self.isImage: - self.metadata = metadata.MetaData(self.fullFileName) - self.metadata.read() - else: - self.metadata = videometadata.VideoMetaData(self.fullFileName) - - - def dateTime(self, alternative_if_date_missing=None): - date = None - if self.metadata: - date = self.metadata.dateTime() - if not date: - if alternative_if_date_missing: - date = alternative_if_date_missing - else: - date = datetime.datetime.fromtimestamp(self.modificationTime) - return date - - - def generateThumbnail(self, tempWorkingDir): - """ - Attempts to generate or extract a thumnail and its orientation for the photo or video - """ - if self.metadata is None: - sys.stderr.write("metadata should not be empty!") - else: - if self.isImage: - try: - thumbnail = self.metadata.getThumbnailData(max_thumbnail_size) - if not isinstance(thumbnail, types.StringType): - self.thumbnail = None - else: - orientation = self.metadata.orientation(missing=None) - pbloader = gtk.gdk.PixbufLoader() - pbloader.write(thumbnail) - pbloader.close() - # Get the resulting pixbuf and build an image to be displayed - pixbuf = pbloader.get_pixbuf() - if orientation == 8: - pixbuf = pixbuf.rotate_simple(gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE) - elif orientation == 6: - pixbuf = pixbuf.rotate_simple(gtk.gdk.PIXBUF_ROTATE_CLOCKWISE) - elif orientation == 3: - pixbuf = pixbuf.rotate_simple(gtk.gdk.PIXBUF_ROTATE_UPSIDEDOWN) - - self.thumbnail = pixbuf - except: - pass - else: - # get thumbnail of video - # it may need to be generated - self.thumbnail = self.metadata.getThumbnailData(max_thumbnail_size, tempWorkingDir) - if self.thumbnail: - # scale to size - self.thumbnail = common.scale2pixbuf(max_thumbnail_size, max_thumbnail_size, self.thumbnail) - - - -class Media: - """ Generic class for media holding images and videos """ - def __init__(self, path, volume = None): - """ - volume is a gnomevfs or gio volume: see class Volume in rapid.py - """ - - self.path = path - self.volume = volume - - - def prettyName(self, limit=config.MAX_LENGTH_DEVICE_NAME): - """ - Returns a name for the media, useful for display. - - If the media is from a gnomevfs volume, returns the gnome name. - - Else. returns the last part of the mount point after stripping out - underscores. - """ - - if self.volume: - return self.volume.get_name(limit) - else: - name = os.path.split(self.path)[1] - name = name.replace('_', ' ') - v = name - if limit: - if len(v) > limit: - v = v[:limit] + '...' - return v - - def getPath(self): - return self.path - - -class CardMedia(Media): - """Compact Flash cards, hard drives, etc.""" - def __init__(self, path, volume = None): - """ - volume is a gnomevfs or gio volume, see class Volume in rapid.py - """ - Media.__init__(self, path, volume) - - - def setMedia(self, imagesAndVideos, fileSizeSum, noFiles): - self.imagesAndVideos = imagesAndVideos # class MediaFile - self.fileSizeSum = fileSizeSum - self.noFiles = noFiles - - def numberOfImagesAndVideos(self): - return self.noFiles - - def sizeOfImagesAndVideos(self, humanReadable = True): - if humanReadable: - return common.formatSizeForUser(self.fileSizeSum) - else: - return self.fileSizeSum - - def sizeAndNumberDownloadPending(self): - """ - Returns how many files have their status set to download pending, and their size - """ - v = s = 0 - fileIndex = [] - for i in range(len(self.imagesAndVideos)): - mediaFile = self.imagesAndVideos[i][0] - if mediaFile.status == STATUS_DOWNLOAD_PENDING: - v += 1 - s += mediaFile.size - fileIndex.append(i) - return (v, s, fileIndex) - - def numberOfFilesNotCannotDownload(self): - """ - Returns how many files whose status is not cannot download - """ - v = 0 - for i in range(len(self.imagesAndVideos)): - mediaFile = self.imagesAndVideos[i][0] - if mediaFile.status <> STATUS_CANNOT_DOWNLOAD: - v += 1 - - return v - - def downloadPending(self): - """ - Returns true if there a mediaFile with status download pending on the device. - Inefficient. Not currently used. - """ - for i in range(len(self.imagesAndVideos)): - mediaFile = self.imagesAndVideos[i][0] - if mediaFile.status == config.STATUS_DOWNLOAD_PENDING: - return True - return False - - def _firstFile(self, isImage): - if self.imagesAndVideos: - for i in range(len(self.imagesAndVideos)): - if self.imagesAndVideos[i][0].isImage == isImage: - return self.imagesAndVideos[i][0] - else: - return None - - def firstImage(self): - return self._firstFile(True) - - def firstVideo(self): - return self._firstFile(False) - |