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

« back to all changes in this revision

Viewing changes to portable/filetypes.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
 
"""``miro.filetypes`` - functions for determining things from the
30
 
filename, enclosure, content-type, and other things.
31
 
"""
32
 
 
33
 
import os
34
 
 
35
 
# NOTE: if you change VIDEO_EXTENSIONS or AUDIO_EXTENSIONS, consider writing a
36
 
# database update so that the file_type attribute of the item table gets fixed
37
 
 
38
 
VIDEO_EXTENSIONS = ['.mov', '.wmv', '.mp4', '.m4v', '.ogv', '.anx',
39
 
                    '.mpg', '.avi', '.flv', '.mpeg', '.divx', '.xvid',
40
 
                    '.rmvb', '.mkv', '.m2v', '.ogm']
41
 
AUDIO_EXTENSIONS = ['.mp3', '.m4a', '.wma', '.mka', '.flac', '.ogg']
42
 
FEED_EXTENSIONS = ['.xml', '.rss', '.atom']
43
 
OTHER_EXTENSIONS = ['.pdf', '.txt', '.html', '.doc', '.bmp', '.gif', '.jpg',
44
 
                    '.jpeg', '.png', '.psd', '.tif', '.tiff',]
45
 
SUBTITLES_EXTENSIONS = ['.srt', '.sub', '.ass', '.ssa', '.smil', '.cmml']
46
 
 
47
 
 
48
 
UNSUPPORTED_MIMETYPES = ("video/3gpp", "video/vnd.rn-realvideo",
49
 
                         "video/x-ms-asf")
50
 
 
51
 
MIMETYPES_EXT_MAP = {
52
 
    'video/quicktime':  ['.mov'],
53
 
    'video/mpeg':       ['.mpeg', '.mpg', '.m2v'],
54
 
    'video/mp4':        ['.mp4', '.m4v'],
55
 
    'video/mpeg4':      ['.mp4', '.m4v'],
56
 
    'video/flv':        ['.flv'],
57
 
    'video/x-flv':      ['.flv'],
58
 
    'video/x-ms-wmv':   ['.wmv'],
59
 
    'video/x-msvideo':  ['.avi'],
60
 
    'video/x-matroska': ['.mkv'],
61
 
    'application/ogg':  ['.ogg'],
62
 
    'video/ogg':        ['.ogv'],
63
 
 
64
 
    'audio/flac':       ['.flac'],
65
 
    'audio/mpeg':       ['.mp3'],
66
 
    'audio/mp4':        ['.m4a'],
67
 
    'audio/x-ms-wma':   ['.wma'],
68
 
    'audio/x-matroska': ['.mka'],
69
 
    
70
 
    'application/x-bittorrent': ['.torrent']
71
 
}
72
 
 
73
 
EXT_MIMETYPES_MAP = {}
74
 
for (mimetype, exts) in MIMETYPES_EXT_MAP.iteritems():
75
 
    for ext in exts:
76
 
        if ext not in EXT_MIMETYPES_MAP:
77
 
            EXT_MIMETYPES_MAP[ext] = list()
78
 
        EXT_MIMETYPES_MAP[ext].append(mimetype)
79
 
 
80
 
def is_allowed_mimetype(mimetype):
81
 
    """
82
 
    Pass a mimetype to this method and it will return a boolean
83
 
    saying if the mimetype is something Miro can handle.
84
 
    """
85
 
    return (mimetype in MIMETYPES_EXT_MAP.keys())
86
 
 
87
 
def is_allowed_filename(filename):
88
 
    """
89
 
    Pass a filename to this method and it will return a boolean
90
 
    saying if the filename represents video, audio or torrent.
91
 
    """
92
 
    return (is_video_filename(filename)
93
 
            or is_audio_filename(filename)
94
 
            or is_torrent_filename(filename))
95
 
 
96
 
def is_playable_filename(filename):
97
 
    """
98
 
    Pass a filename to this method and it will return a boolean
99
 
    saying if the filename represents video or audio.
100
 
    """
101
 
    return is_video_filename(filename) or is_audio_filename(filename)
102
 
 
103
 
def _check_filename(filename, extension_list):
104
 
    if not filename:
105
 
        return False
106
 
    filename = filename.lower()
107
 
    for ext in extension_list:
108
 
        if filename.endswith(ext):
109
 
            return True
110
 
    return False
111
 
 
112
 
def is_video_filename(filename):
113
 
    """
114
 
    Pass a filename to this method and it will return a boolean
115
 
    saying if the filename represents a video file.
116
 
    """
117
 
    return _check_filename(filename, VIDEO_EXTENSIONS)
118
 
 
119
 
def is_audio_filename(filename):
120
 
    """
121
 
    Pass a filename to this method and it will return a boolean
122
 
    saying if the filename represents an audio file.
123
 
    """
124
 
    return _check_filename(filename, AUDIO_EXTENSIONS)
125
 
 
126
 
def is_other_filename(filename):
127
 
    """
128
 
    Pass a filename to this method and it will return a boolean
129
 
    saying if the filename represents a non-audio, non-video file.
130
 
    """
131
 
    return _check_filename(filename, OTHER_EXTENSIONS)
132
 
 
133
 
def is_media_filename(filename):
134
 
    """Check if a filename is a video or audio filename"""
135
 
    return is_video_filename(filename) or is_audio_filename(filename)
136
 
 
137
 
def is_torrent_filename(filename):
138
 
    """
139
 
    Pass a filename to this method and it will return a boolean
140
 
    saying if the filename represents a torrent file.
141
 
    """
142
 
    return _check_filename(filename, ['.torrent'])
143
 
 
144
 
def is_feed_filename(filename):
145
 
    """
146
 
    Pass a filename to this method and it will return a boolean saying if the
147
 
    filename possibly represents an Atom or RSS feed URL.
148
 
    """
149
 
    return _check_filename(filename, FEED_EXTENSIONS)
150
 
 
151
 
def is_subtitle_filename(filename):
152
 
    """
153
 
    Pass a filename to this method and it will return a boolean saying if the
154
 
    filename possibly represents a sidecar subtitle file.
155
 
    """
156
 
    return _check_filename(filename, SUBTITLES_EXTENSIONS)
157
 
 
158
 
def is_video_enclosure(enclosure):
159
 
    """
160
 
    Pass an enclosure dictionary to this method and it will return a boolean
161
 
    saying if the enclosure is a video or not.
162
 
    """
163
 
    return (_has_video_type(enclosure)
164
 
            or _has_video_extension(enclosure, 'url')
165
 
            or _has_video_extension(enclosure, 'href'))
166
 
 
167
 
def _has_video_type(enclosure):
168
 
    return ('type' in enclosure
169
 
            and (enclosure['type'].startswith(u'video/')
170
 
                 or enclosure['type'].startswith(u'audio/')
171
 
                 or enclosure['type'] == u"application/ogg"
172
 
                 or enclosure['type'] == u"application/x-annodex"
173
 
                 or enclosure['type'] == u"application/x-bittorrent"
174
 
                 or enclosure['type'] == u"application/x-shockwave-flash")
175
 
            and (enclosure['type'] not in UNSUPPORTED_MIMETYPES))
176
 
 
177
 
def _has_video_extension(enclosure, key):
178
 
    from miro import download_utils
179
 
    if key in enclosure:
180
 
        elems = download_utils.parse_url(enclosure[key], split_path=True)
181
 
        return is_allowed_filename(elems[3])
182
 
    return False
183
 
 
184
 
def is_feed_content_type(content_type):
185
 
    """Is a content-type for a RSS feed?"""
186
 
 
187
 
    feed_types = [u'application/rdf+xml', u'application/atom+xml',
188
 
                  u'application/rss+xml', u'application/podcast+xml',
189
 
                  u'text/xml', u'application/xml', 
190
 
                  ]
191
 
    for type_ in feed_types:
192
 
        if content_type.startswith(type_):
193
 
            return True
194
 
    return False
195
 
 
196
 
def is_maybe_feed_content_type(content_type):
197
 
    """Could the content type contain a feed?
198
 
    """
199
 
    return content_type.startswith(u"text/")
200
 
 
201
 
def is_maybe_rss(body):
202
 
    """Sniffs the body to determine whether it's a feed or not.
203
 
 
204
 
    this is very loosely taken from Firefox nsFeedSniffer.cpp and ideas in
205
 
    http://blogs.msdn.com/rssteam/articles/PublishersGuide.aspx
206
 
    """
207
 
    if len(body) > 512:
208
 
        body = body[0:512]
209
 
 
210
 
    for mem in ("<rss", "<feed", "<rdf:RDF"):
211
 
        if body.find(mem) != -1:
212
 
            return True
213
 
    return False
214
 
 
215
 
def is_maybe_rss_url(url):
216
 
    return (url.startswith("http")
217
 
            and (url.startswith("http://feeds.feedburner.com")
218
 
                 or "rss" in url))
219
 
 
220
 
def guess_extension(mimetype):
221
 
    """
222
 
    Pass a mime type to this method and it will return a corresponding
223
 
    file extension, or None if it doesn't know about the type.
224
 
    """
225
 
    possible_extensions = MIMETYPES_EXT_MAP.get(mimetype)
226
 
    if possible_extensions is None:
227
 
        return None
228
 
    return possible_extensions[0]
229
 
 
230
 
def guess_mime_type(filename):
231
 
    """
232
 
    Pass a filename to this method and it will return a corresponding
233
 
    mime type, or 'video/unknown' if the filename has a known video
234
 
    extension but no corresponding mime type, or None if it doesn't
235
 
    know about the file extension.
236
 
    """
237
 
    root, ext = os.path.splitext(filename)
238
 
    possible_types = EXT_MIMETYPES_MAP.get(ext)
239
 
    if possible_types is None:
240
 
        if is_video_filename(filename):
241
 
            return 'video/unknown'
242
 
        elif is_audio_filename(filename):
243
 
            return 'audio/unknown'
244
 
        else:
245
 
            return None
246
 
    return possible_types[0]