Iterate through the enabled media types and find those suited
for a certain file.
'''
- media_file = tempfile.NamedTemporaryFile()
- media_file.write(media.file.read())
- media.file.seek(0)
- for media_type, manager in get_media_managers():
- _log.info('Sniffing {0}'.format(media_type))
- if manager['sniff_handler'](media_file, media=media):
- _log.info('{0} accepts the file'.format(media_type))
- return media_type, manager
- else:
- _log.debug('{0} did not accept the file'.format(media_type))
+
+ try:
+ return get_media_type_and_manager(media.filename)
+ except FileTypeNotSupported:
+ _log.info('No media handler found by file extension. Doing it the expensive way...')
+ # Create a temporary file for sniffers suchs as GStreamer-based
+ # Audio video
+ media_file = tempfile.NamedTemporaryFile()
+ media_file.write(media.file.read())
+ media.file.seek(0)
+
+ for media_type, manager in get_media_managers():
+ _log.info('Sniffing {0}'.format(media_type))
+ if manager['sniff_handler'](media_file, media=media):
+ _log.info('{0} accepts the file'.format(media_type))
+ return media_type, manager
+ else:
+ _log.debug('{0} did not accept the file'.format(media_type))
raise FileTypeNotSupported(
# TODO: Provide information on which file types are supported
'''
for media_type in get_media_types():
__import__(media_type)
-
+
yield media_type, sys.modules[media_type].MEDIA_MANAGER
def get_media_type_and_manager(filename):
'''
- Get the media type and manager based on a filename
+ Try to find the media type based on the file name, extension
+ specifically. This is used as a speedup, the sniffing functionality
+ then falls back on more in-depth bitsniffing of the source file.
'''
if filename.find('.') > 0:
# Get the file extension
ext = os.path.splitext(filename)[1].lower()
- else:
- raise InvalidFileType(
- _(u'Could not extract any file extension from "{filename}"').format(
- filename=filename))
- for media_type, manager in get_media_managers():
- # Omit the dot from the extension and match it against
- # the media manager
- if ext[1:] in manager['accepted_extensions']:
- return media_type, manager
+ for media_type, manager in get_media_managers():
+ # Omit the dot from the extension and match it against
+ # the media manager
+ if ext[1:] in manager['accepted_extensions']:
+ return media_type, manager
else:
- raise FileTypeNotSupported(
- # TODO: Provide information on which file types are supported
- _(u'Sorry, I don\'t support that file type :('))
+ _log.info('File {0} has no file extension, let\'s hope the sniffers get it.'.format(
+ filename))
+
+ raise FileTypeNotSupported(
+ _(u'Sorry, I don\'t support that file type :('))
"display_template": "mediagoblin/media_displays/video.html",
"default_thumb": "images/media_thumbs/video.jpg",
"accepted_extensions": [
- "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "ogg"]}
+ "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv"]}
--- /dev/null
+.audio-spectrogram {
+ position: relative;
+}
+.playhead {
+ position: absolute;
+ top: 0;
+ left: 0;
+ background: rgba(134, 212, 177, 0.3);
+ border-right: thin solid #ffaa00;
+ height: 100%;
+ -webkit-transition: width .1s ease-out;
+ -moz-transition: width .1s ease-out;
+}
+.audio-control-play-pause {
+ position: absolute;
+ bottom: 0;
+ left: 5px;
+ cursor: pointer;
+ /* background: rgba(0, 0, 0, 0.7); */
+ font-size: 40px;
+ width: 50px;
+ text-shadow: 0 0 10px black;
+}
+ .audio-control-play-pause.playing {
+ color: #b71500;
+ }
+ .audio-control-play-pause.paused {
+ color: rgb(134, 212, 177);
+ }
+.buffered {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ height: 2px;
+ width: 0;
+ -webkit-transition: width 1s ease-out;
+ -moz-transition: width 1s ease-out;
+ background: rgba(134, 177, 212, 1);
+ cursor: pointer;
+}
+.seekbar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+.audio-currentTime {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ background: rgba(0, 0, 0, 0.7);
+}
--- /dev/null
+/**
+ * GNU MediaGoblin -- federated, autonomous media hosting
+ * Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+var audioPlayer = new Object();
+
+(function (audioPlayer) {
+ audioPlayer.init = function (audioElement) {
+ audioPlayer.audioElement = audioElement;
+ console.log(audioElement);
+ attachEvents();
+ $(audioElement).hide();
+ };
+
+ function attachEvents () {
+ audioPlayer.audioElement.addEventListener('durationchange', audioPlayer.durationChange, true);
+ audioPlayer.audioElement.addEventListener('timeupdate', audioPlayer.timeUpdate, true);
+ audioPlayer.audioElement.addEventListener('progress', audioPlayer.onProgress, true);
+ $(document).ready( function () {
+ $('.audio-spectrogram').delegate('.seekbar', 'click', audioPlayer.onSeek);
+ $('.audio-spectrogram').delegate('.audio-control-play-pause', 'click', audioPlayer.playPause);
+ });
+ }
+
+ audioPlayer.onProgress = function(a, b, c) {
+ console.log(a, b, c);
+ buffered = audioPlayer.audioElement.buffered;
+
+ ranges = new Array();
+
+ for (i = 0; i < buffered.length; i++) {
+ ranges[i] = new Array();
+ ranges[i][0] = buffered.start(i);
+ ranges[i][1] = buffered.end(i);
+ }
+ console.log('ranges', ranges);
+ $('.audio-spectrogram .buffered').width(
+ (ranges[0][1] / audioPlayer.audioElement.duration) * audioPlayer.imageElement.width());
+ };
+
+ audioPlayer.onSeek = function (e) {
+ console.log('onSeek', e);
+ im = audioPlayer.imageElement;
+ pos = e.offsetX / im.width();
+ audioPlayer.audioElement.currentTime = pos * audioPlayer.audioElement.duration;
+ audioPlayer.audioElement.play();
+ audioPlayer.setState(audioPlayer.PLAYING);
+ };
+
+ audioPlayer.playPause = function (e) {
+ console.log('playPause', e);
+ if (audioPlayer.audioElement.paused) {
+ audioPlayer.audioElement.play();
+ audioPlayer.setState(audioPlayer.PLAYING);
+ } else {
+ audioPlayer.audioElement.pause();
+ audioPlayer.setState(audioPlayer.PAUSED);
+ }
+ };
+
+ audioPlayer.NULL = null;
+ audioPlayer.PLAYING = 2;
+ audioPlayer.PAUSED = 4;
+
+ audioPlayer.state = audioPlayer.NULL;
+
+ audioPlayer.setState = function (state) {
+ if (state == audioPlayer.state) {
+ return;
+ }
+
+ switch (state) {
+ case audioPlayer.PLAYING:
+ $('.audio-spectrogram .audio-control-play-pause')
+ .removeClass('paused').addClass('playing')
+ .text('■');
+ break;
+ case audioPlayer.PAUSED:
+ $('.audio-spectrogram .audio-control-play-pause')
+ .removeClass('playing').addClass('paused')
+ .text('▶');
+ break;
+ }
+ };
+
+ audioPlayer.durationChange = function () {
+ duration = audioPlayer.audioElement.duration;
+ };
+
+ audioPlayer.timeUpdate = function () {
+ currentTime = audioPlayer.audioElement.currentTime;
+ playhead = audioPlayer.imageElement.parent().find('.playhead');
+ playhead.css('width', (currentTime / audioPlayer.audioElement.duration) * audioPlayer.imageElement.width());
+ time = formatTime(currentTime);
+ duration = formatTime(audioPlayer.audioElement.duration);
+ audioPlayer.imageElement.parent().find('.audio-currentTime').text(time + '/' + duration);
+ };
+
+ function formatTime(seconds) {
+ var h = Math.floor(seconds / (60 * 60));
+ var m = Math.floor((seconds - h * 60 * 60) / 60);
+ var s = Math.round(seconds - h * 60 * 60 - m * 60);
+ return '' + (h ? (h < 10 ? '0' + h : h) + ':' : '') + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
+ }
+
+ audioPlayer.attachToImage = function (imageElement) {
+ /**
+ * Attach the player to an image element
+ */
+ console.log(imageElement);
+ im = $(imageElement);
+ audioPlayer.imageElement = im;
+ $('<div class="playhead"></div>').appendTo(im.parent());
+ $('<div class="buffered"></div>').appendTo(im.parent());
+ $('<div class="seekbar"></div>').appendTo(im.parent());
+ $('<div class="audio-control-play-pause paused">▶</div>').appendTo(im.parent());
+ $('<div class="audio-currentTime">00:00</div>').appendTo(im.parent());
+ };
+})(audioPlayer);
+
+$(document).ready(function () {
+ audioElements = $('.audio-media .audio-player');
+ audioPlayer.init(audioElements[0]);
+ audioPlayer.attachToImage($('.audio-spectrogram img')[0]);
+});
+
{% extends 'mediagoblin/user_pages/media.html' %}
+{% block mediagoblin_head %}
+ {{ super() }}
+ <link rel="stylesheet" type="text/css" href="{{ request.staticdirect('/css/audio.css') }}" />
+ <script type="text/javascript" src="{{ request.staticdirect(
+ '/js/audio.js') }}"></script>
+{% endblock %}
+
{% block mediagoblin_media %}
<div class="audio-media">
{% if 'spectrogram' in media.media_files %}
request.db.MediaEntry.find(
{'_id': media._id}).count())
+ def test_sniffing(self):
+ '''
+ Test sniffing mechanism to assert that regular uploads work as intended
+ '''
+ template.clear_test_template_context()
+ response = self.test_app.post(
+ '/submit/', {
+ 'title': 'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE'
+ }, upload_files=[(
+ 'file', GOOD_JPG)])
+
+ response.follow()
+
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html']
+
+ request = context['request']
+
+ media = request.db.MediaEntry.find_one({
+ u'title': u'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE'})
+
+ assert media.media_type == 'mediagoblin.media_types.image'
+
def test_malicious_uploads(self):
# Test non-suppoerted file with non-supported extension
# -----------------------------------------------------