1
# Miro - an RSS based video player application
2
# Copyright (C) 2005-2010 Participatory Culture Foundation
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
# In addition, as a special exception, the copyright holders give
19
# permission to link the code of portions of this program with the OpenSSL
22
# You must obey the GNU General Public License in all respects for all of
23
# the code used other than OpenSSL. If you modify file(s) with this
24
# exception, you may extend this exception to your version of the file(s),
25
# but you are not obligated to do so. If you do not wish to do so, delete
26
# this exception statement from your version. If you delete this exception
27
# statement from all source files in the program, then also delete it here.
39
from miro.plat import qtcomp
40
from miro.plat import utils
41
from miro.plat.frontends.widgets import mediatypes
43
# =============================================================================
45
def registerQuickTimeComponents():
46
bundlePath = os.getenv('MIRO_BUNDLE_PATH')
47
componentsDirectoryPath = os.path.join(bundlePath, 'Contents', 'Components')
48
components = glob.glob(os.path.join(componentsDirectoryPath, '*.component'))
49
for component in components:
50
ok = qtcomp.register(component.encode('utf-8'))
52
# =============================================================================
54
def extractDuration(qtmovie):
56
qttime = qtmovie.duration()
57
if utils.qttimescale(qttime) == 0:
59
return int((utils.qttimevalue(qttime) / float(utils.qttimescale(qttime))) * 1000)
63
def get_type(qtmovie):
67
allTracks = qtmovie.tracks()
68
if len(allTracks) == 0:
73
for track in allTracks:
74
media_type = track.attributeForKey_(QTKit.QTTrackMediaTypeAttribute)
75
if media_type in mediatypes.AUDIO_MEDIA_TYPES:
77
elif media_type in mediatypes.VIDEO_MEDIA_TYPES:
88
# -----------------------------------------------------------------------------
90
def extractThumbnail(qtmovie, target, width=0, height=0):
92
qttime = qtmovie.duration()
93
qttime = utils.qttimevalue_set(qttime, int(utils.qttimevalue(qttime) * 0.5))
94
frame = qtmovie.frameImageAtTime_(qttime)
98
frameSize = frame.size()
99
if frameSize.width == 0 or frameSize.height == 0:
102
if (width == 0) and (height == 0):
103
width = frameSize.width
104
height = frameSize.height
106
frameRatio = frameSize.width / frameSize.height
107
sourceSize = frame.size()
108
sourceRatio = sourceSize.width / sourceSize.height
109
destinationSize = Foundation.NSSize(width, height)
110
destinationRatio = destinationSize.width / destinationSize.height
112
if sourceRatio > destinationRatio:
113
size = Foundation.NSSize(destinationSize.width, destinationSize.width / sourceRatio)
114
pos = Foundation.NSPoint(0, (destinationSize.height - size.height) / 2.0)
116
size = Foundation.NSSize(destinationSize.height * sourceRatio, destinationSize.height)
117
pos = Foundation.NSPoint((destinationSize.width - size.width) / 2.0, 0)
119
destination = AppKit.NSImage.alloc().initWithSize_(destinationSize)
121
destination.lockFocus()
122
AppKit.NSGraphicsContext.currentContext().setImageInterpolation_(AppKit.NSImageInterpolationHigh)
123
AppKit.NSColor.blackColor().set()
124
AppKit.NSRectFill(((0,0), destinationSize))
125
frame.drawInRect_fromRect_operation_fraction_((pos, size), ((0,0), sourceSize), AppKit.NSCompositeSourceOver, 1.0)
127
destination.unlockFocus()
129
tiffData = destination.TIFFRepresentation()
130
imageRep = AppKit.NSBitmapImageRep.imageRepWithData_(tiffData)
131
properties = {AppKit.NSImageCompressionFactor: 0.8}
132
jpegData = imageRep.representationUsingType_properties_(AppKit.NSJPEGFileType, properties)
133
if jpegData is objc.nil:
136
jpegData.writeToFile_atomically_(target, objc.YES)
142
# =============================================================================
144
moviePath = sys.argv[1].decode('utf-8')
145
thumbPath = sys.argv[2].decode('utf-8')
147
info = AppKit.NSBundle.mainBundle().infoDictionary()
148
info["LSBackgroundOnly"] = "1"
149
AppKit.NSApplicationLoad()
151
registerQuickTimeComponents()
153
pyobjc_version = objc.__version__
154
pyobjc_version = pyobjc_version.split('.')
155
pyobjc_version = int(pyobjc_version[0])
157
if pyobjc_version == 2:
158
qtmovie, error = QTKit.QTMovie.movieWithFile_error_(moviePath, None)
160
qtmovie, error = QTKit.QTMovie.movieWithFile_error_(moviePath)
161
if qtmovie is None or error is not objc.nil:
164
movie_type = get_type(qtmovie)
165
print "Miro-Movie-Data-Type: %s" % movie_type
167
duration = extractDuration(qtmovie)
168
print "Miro-Movie-Data-Length: %s" % duration
170
if movie_type == "video":
171
max_load_state = 100000
172
if utils.getMajorOSVersion() < 10:
173
max_load_state = 20000
175
load_state = qtmovie.attributeForKey_(QTKit.QTMovieLoadStateAttribute)
176
if load_state >= max_load_state or load_state == -1:
180
thmbResult = extractThumbnail(qtmovie, thumbPath)
181
print "Miro-Movie-Data-Thumbnail: %s" % thmbResult
183
print "Miro-Movie-Data-Thumbnail: Failure"
188
# =============================================================================