summaryrefslogtreecommitdiff
path: root/rapid/media.py
diff options
context:
space:
mode:
authorJulien Valroff <julien@kirya.net>2011-03-25 22:07:02 +0100
committerJulien Valroff <julien@kirya.net>2011-03-25 22:07:02 +0100
commit59350657b70c3c2bb9e1cf90817bb4607a00e4fe (patch)
tree4eb598ac0235c9cf1614eaf9e33b1d7d290e9e3d /rapid/media.py
parent478f6858602c736b67d420cbf198aeab3313cc23 (diff)
parent6866d4a5b74779f087b8e44148a49163d8b7327b (diff)
Merge commit 'upstream/0.4.0_alpha1' into experimental
Diffstat (limited to 'rapid/media.py')
-rwxr-xr-xrapid/media.py339
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)
-