~ubuntu-branches/ubuntu/natty/miro/natty

« back to all changes in this revision

Viewing changes to platform/osx/qt_extractor.py

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2011-01-22 02:46:33 UTC
  • mfrom: (1.4.10 upstream) (1.7.5 experimental)
  • Revision ID: james.westby@ubuntu.com-20110122024633-kjme8u93y2il5nmf
Tags: 3.5.1-1ubuntu1
* Merge from debian.  Remaining ubuntu changes:
  - Use python 2.7 instead of python 2.6
  - Relax dependency on python-dbus to >= 0.83.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Miro - an RSS based video player application
2
 
# Copyright (C) 2005-2010 Participatory Culture Foundation
3
 
#
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.
8
 
#
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.
13
 
#
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
17
 
#
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
20
 
# library.
21
 
#
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.
28
 
 
29
 
 
30
 
import os
31
 
import sys
32
 
import glob
33
 
import time
34
 
import objc
35
 
import QTKit
36
 
import AppKit
37
 
import Foundation
38
 
 
39
 
from miro.plat import qtcomp
40
 
from miro.plat import utils
41
 
from miro.plat.frontends.widgets import mediatypes
42
 
 
43
 
# =============================================================================
44
 
 
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'))
51
 
 
52
 
# =============================================================================
53
 
 
54
 
def extractDuration(qtmovie):
55
 
    try:
56
 
        qttime = qtmovie.duration()
57
 
        if utils.qttimescale(qttime) == 0:
58
 
            return -1
59
 
        return int((utils.qttimevalue(qttime) / float(utils.qttimescale(qttime))) * 1000)
60
 
    except Exception, e:
61
 
        return -1
62
 
 
63
 
def get_type(qtmovie):
64
 
    if qtmovie is None:
65
 
        return 'other'
66
 
 
67
 
    allTracks = qtmovie.tracks()
68
 
    if len(allTracks) == 0:
69
 
        return 'other'
70
 
 
71
 
    has_audio = False
72
 
    has_video = False
73
 
    for track in allTracks:
74
 
        media_type = track.attributeForKey_(QTKit.QTTrackMediaTypeAttribute)
75
 
        if media_type in mediatypes.AUDIO_MEDIA_TYPES:
76
 
            has_audio = True
77
 
        elif media_type in mediatypes.VIDEO_MEDIA_TYPES:
78
 
            has_video = True
79
 
 
80
 
    item_type = 'other'
81
 
    if has_video:
82
 
        item_type = 'video'
83
 
    elif has_audio:
84
 
        item_type = 'audio'
85
 
 
86
 
    return item_type
87
 
 
88
 
# -----------------------------------------------------------------------------
89
 
 
90
 
def extractThumbnail(qtmovie, target, width=0, height=0):
91
 
    try:
92
 
        qttime = qtmovie.duration()
93
 
        qttime = utils.qttimevalue_set(qttime, int(utils.qttimevalue(qttime) * 0.5))
94
 
        frame = qtmovie.frameImageAtTime_(qttime)
95
 
        if frame is objc.nil:
96
 
            return "Failure"
97
 
 
98
 
        frameSize = frame.size()
99
 
        if frameSize.width == 0 or frameSize.height == 0:
100
 
            return "Failure"
101
 
 
102
 
        if (width == 0) and (height == 0):
103
 
            width = frameSize.width
104
 
            height = frameSize.height
105
 
 
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
111
 
 
112
 
        if sourceRatio > destinationRatio:
113
 
            size = Foundation.NSSize(destinationSize.width, destinationSize.width / sourceRatio)
114
 
            pos = Foundation.NSPoint(0, (destinationSize.height - size.height) / 2.0)
115
 
        else:
116
 
            size = Foundation.NSSize(destinationSize.height * sourceRatio, destinationSize.height)
117
 
            pos = Foundation.NSPoint((destinationSize.width - size.width) / 2.0, 0)
118
 
 
119
 
        destination = AppKit.NSImage.alloc().initWithSize_(destinationSize)
120
 
        try:
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)
126
 
        finally:
127
 
            destination.unlockFocus()
128
 
 
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:
134
 
            return "Failure"
135
 
 
136
 
        jpegData.writeToFile_atomically_(target, objc.YES)
137
 
    except Exception, e:
138
 
        return "Failure"
139
 
 
140
 
    return "Success"
141
 
 
142
 
# =============================================================================
143
 
 
144
 
moviePath = sys.argv[1].decode('utf-8')
145
 
thumbPath = sys.argv[2].decode('utf-8')
146
 
 
147
 
info = AppKit.NSBundle.mainBundle().infoDictionary()
148
 
info["LSBackgroundOnly"] = "1"
149
 
AppKit.NSApplicationLoad()
150
 
 
151
 
registerQuickTimeComponents()
152
 
 
153
 
pyobjc_version = objc.__version__
154
 
pyobjc_version = pyobjc_version.split('.')
155
 
pyobjc_version = int(pyobjc_version[0])
156
 
 
157
 
if pyobjc_version == 2:
158
 
    qtmovie, error = QTKit.QTMovie.movieWithFile_error_(moviePath, None)
159
 
else:
160
 
    qtmovie, error = QTKit.QTMovie.movieWithFile_error_(moviePath)
161
 
if qtmovie is None or error is not objc.nil:
162
 
    sys.exit(0)
163
 
 
164
 
movie_type = get_type(qtmovie)
165
 
print "Miro-Movie-Data-Type: %s" % movie_type
166
 
 
167
 
duration = extractDuration(qtmovie)
168
 
print "Miro-Movie-Data-Length: %s" % duration
169
 
 
170
 
if movie_type == "video":
171
 
    max_load_state = 100000
172
 
    if utils.getMajorOSVersion() < 10:
173
 
        max_load_state = 20000
174
 
    while True:
175
 
        load_state = qtmovie.attributeForKey_(QTKit.QTMovieLoadStateAttribute)
176
 
        if load_state >= max_load_state  or load_state == -1:
177
 
            break
178
 
        time.sleep(0.1)
179
 
 
180
 
    thmbResult = extractThumbnail(qtmovie, thumbPath)
181
 
    print "Miro-Movie-Data-Thumbnail: %s" % thmbResult
182
 
else:
183
 
    print "Miro-Movie-Data-Thumbnail: Failure"
184
 
 
185
 
 
186
 
sys.exit(0)
187
 
 
188
 
# =============================================================================