def parse(self, file=None, url=None):
        """Return metadata for the given file or raise an error.

        :type file: :class:`cgi.FieldStorage` or None
        :param file: A freshly uploaded file object.
        :type url: unicode or None
        :param url: A remote URL string.
        :rtype: dict
        :returns: Any extracted metadata.
        :raises UnsuitableEngineError: If file information cannot be parsed.

        """
        if file is None:
            raise UnsuitableEngineError

        filename = os.path.basename(file.filename)
        name, ext = os.path.splitext(filename)
        ext = ext.lstrip('.').lower()
        container = guess_container_format(ext)

        return {
            'type': guess_media_type(container),
            'container': container,
            'display_name': u'%s.%s' % (name, container or ext),
            'size': get_file_size(file.file),
        }
Exemple #2
0
def media_file_from_url(url):
    """Create and return a MediaFile object representing a given URL.
    Also returns the URL to a suitable thumbnail image (or None) and the
    duration of the media file in seconds (or None).

    Does not add the created MediaFile to the database.
    """
    thumb_url = None
    duration = None
    title = None
    media_file = MediaFile()
    # Parse the URL checking for known embeddables like YouTube
    embed = parse_embed_url(url)
    if embed:
        media_file.type = embed['type']
        media_file.container = embed['container']
        media_file.embed = embed['id']
        title = embed['title']
        if title:
            media_file.display_name = title
        else:
            media_file.display_name = '%s ID: %s' % \
                (embed['container'].capitalize(), media_file.embed)
        thumb_url = embed['thumb_url']
        duration = embed['duration']
    else:
        # Check for types we can play ourselves
        name, ext, container = base_ext_container_from_uri(url)
        media_file.type = guess_media_type(ext)
        media_file.container = container
        media_file.url = url
        media_file.display_name = os.path.basename(url)

    return media_file, thumb_url, duration, title
Exemple #3
0
    def parse(self, file=None, url=None):
        """Return metadata for the given file or raise an error.

        :type file: :class:`cgi.FieldStorage` or None
        :param file: A freshly uploaded file object.
        :type url: unicode or None
        :param url: A remote URL string.
        :rtype: dict
        :returns: Any extracted metadata.
        :raises UnsuitableEngineError: If file information cannot be parsed.

        """
        if file is None:
            raise UnsuitableEngineError

        filename = os.path.basename(file.filename)
        name, ext = os.path.splitext(filename)
        ext = ext.lstrip('.').lower()
        container = guess_container_format(ext)

        return {
            'type': guess_media_type(container),
            'container': container,
            'display_name': u'%s.%s' % (name, container or ext),
            'size': get_file_size(file.file),
        }
Exemple #4
0
def _add_new_media_file(media, original_filename, file):
    # FIXME: I think this will raise a KeyError if the uploaded
    #        file doesn't have an extension.
    file_ext = os.path.splitext(original_filename)[1].lower()[1:]

    # set the file paths depending on the file type
    media_file = MediaFile()
    media_file.display_name = original_filename
    media_file.container = guess_container_format(file_ext)
    media_file.type = guess_media_type(media_file.container)

    # Small files are stored in memory and do not have a tmp file w/ fileno
    if hasattr(file, 'fileno'):
        media_file.size = os.fstat(file.fileno())[6]
    else:
        # The file may contain multi-byte characters, so we must seek instead of count chars
        file.seek(0, os.SEEK_END)
        media_file.size = file.tell()
        file.seek(0)

    # update media relations
    media.files.append(media_file)

    # add the media file (and its media, if new) to the database to get IDs
    DBSession.add(media_file)
    DBSession.flush()

    # copy the file to its permanent location
    file_name = '%d_%d_%s.%s' % (media.id, media_file.id, media.slug, file_ext)
    file_url = _store_media_file(file, file_name)
    media_file.file_name = file_name

    return media_file
Exemple #5
0
    def parse(self, file=None, url=None):
        """Return metadata for the given file or raise an error.

        :type file: :class:`cgi.FieldStorage` or None
        :param file: A freshly uploaded file object.
        :type url: unicode or None
        :param url: A remote URL string.
        :rtype: dict
        :returns: Any extracted metadata.
        :raises UnsuitableEngineError: If file information cannot be parsed.

        """
        if url is None:
            raise UnsuitableEngineError

        if url.startswith('rtmp://'):
            known_server_uris = self._data.setdefault(RTMP_SERVER_URIS, ())

            if RTMP_URI_DIVIDER in url:
                # Allow the user to explicitly mark the server/file separation
                parts = url.split(RTMP_URI_DIVIDER)
                server_uri = parts[0].rstrip('/')
                file_uri = ''.join(parts[1:]).lstrip('/')
                if server_uri not in known_server_uris:
                    known_server_uris.append(server_uri)
            else:
                # Get the rtmp server from our list of known servers or fail
                for server_uri in known_server_uris:
                    if url.startswith(server_uri):
                        file_uri = url[len(server_uri.rstrip('/') + '/'):]
                        break
                else:
                    raise UserStorageError(
                        _('This RTMP server has not been configured. Add it '
                          'by going to Settings > Storage Engines > '
                          'Remote URLs.'))
            unique_id = ''.join((server_uri, RTMP_URI_DIVIDER, file_uri))
        else:
            unique_id = url

        filename = os.path.basename(url)
        name, ext = os.path.splitext(filename)
        ext = ext.lstrip('.').lower()

        container = guess_container_format(ext)

        # FIXME: Replace guess_container_format with something that takes
        #        into consideration the supported formats of all the custom
        #        players that may be installed.
        #        if not container or container == 'unknown':
        #            raise UnsuitableEngineError

        return {
            'type': guess_media_type(ext),
            'container': container,
            'display_name': u'%s.%s' % (name, container or ext),
            'unique_id': unique_id,
        }
    def parse(self, file=None, url=None):
        """Return metadata for the given file or raise an error.

        :type file: :class:`cgi.FieldStorage` or None
        :param file: A freshly uploaded file object.
        :type url: unicode or None
        :param url: A remote URL string.
        :rtype: dict
        :returns: Any extracted metadata.
        :raises UnsuitableEngineError: If file information cannot be parsed.

        """
        if url is None:
            raise UnsuitableEngineError

        if url.startswith('rtmp://'):
            known_server_uris = self._data.setdefault(RTMP_SERVER_URIS, ())

            if RTMP_URI_DIVIDER in url:
                # Allow the user to explicitly mark the server/file separation
                parts = url.split(RTMP_URI_DIVIDER)
                server_uri = parts[0].rstrip('/')
                file_uri = ''.join(parts[1:]).lstrip('/')
                if server_uri not in known_server_uris:
                    known_server_uris.append(server_uri)
            else:
                # Get the rtmp server from our list of known servers or fail
                for server_uri in known_server_uris:
                    if url.startswith(server_uri):
                        file_uri = url[len(server_uri.rstrip('/') + '/'):]
                        break
                else:
                    raise UserStorageError(
                        _('This RTMP server has not been configured. Add it '
                          'by going to Settings > Storage Engines > '
                          'Remote URLs.'))
            unique_id = ''.join((server_uri, RTMP_URI_DIVIDER, file_uri))
        else:
            unique_id = url

        filename = os.path.basename(url)
        name, ext = os.path.splitext(filename)
        ext = unicode(ext).lstrip('.').lower()

        container = guess_container_format(ext)

        # FIXME: Replace guess_container_format with something that takes
        #        into consideration the supported formats of all the custom
        #        players that may be installed.
#        if not container or container == 'unknown':
#            raise UnsuitableEngineError

        return {
            'type': guess_media_type(ext),
            'container': container,
            'display_name': u'%s.%s' % (name, container or ext),
            'unique_id': unique_id,
        }
Exemple #7
0
    def _save_media_obj(self, name, email, title, description, tags, file, url):
        # create our media object as a status-less placeholder initially
        media_obj = Media()
        media_obj.author = Author(name, email)
        media_obj.title = title
        media_obj.slug = get_available_slug(Media, title)
        media_obj.description = description
        media_obj.notes = fetch_setting('wording_additional_notes')
        media_obj.set_tags(tags)

        # Create a media object, add it to the media_obj, and store the file permanently.
        if file is not None:
            media_file = _add_new_media_file(media_obj, file.filename, file.file)
        else:
            media_file = MediaFile()
            url = unicode(url)
            embed = parse_embed_url(url)
            if embed:
                media_file.type = embed['type']
                media_file.container = embed['container']
                media_file.embed = embed['id']
                media_file.display_name = '%s ID: %s' % \
                    (embed['container'].capitalize(), media_file.embed)
            else:
                # Check for types we can play ourselves
                ext = os.path.splitext(url)[1].lower()[1:]
                container = guess_container_format(ext)
                if container in accepted_extensions():
                    media_file.type = guess_media_type(container)
                    media_file.container = container
                    media_file.url = url
                    media_file.display_name = os.path.basename(url)
                else:
                    # Trigger a validation error on the whole form.
                    raise formencode.Invalid('Please specify a URL or upload a file below.', None, None)
            media_obj.files.append(media_file)

        # Add the final changes.
        media_obj.update_status()
        DBSession.add(media_obj)
        DBSession.flush()

        create_default_thumbs_for(media_obj)

        return media_obj
Exemple #8
0
def media_file_from_filename(filename):
    """Create and return a MediaFile object representing a given filename.

    Does not store the file, or add the created MediaFile to the database.
    """
    name, ext, container = base_ext_container_from_uri(filename)

    # set the file paths depending on the file type
    media_file = MediaFile()
    media_file.display_name = '%s.%s' % (name, container)
    media_file.container = container
    media_file.type = guess_media_type(ext)

    # File has not been stored. It has neither URL nor Filename.
    media_file.url = None
    media_file.file_name = None

    return media_file
Exemple #9
0
    def _save_media_obj(self, name, email, title, description, tags, file, url):
        # create our media object as a status-less placeholder initially
        media_obj = Media()
        media_obj.author = Author(name, email)
        media_obj.title = title
        media_obj.slug = get_available_slug(Media, title)
        media_obj.description = description
        media_obj.notes = fetch_setting('wording_additional_notes')
        media_obj.set_tags(tags)

        # Create a media object, add it to the media_obj, and store the file permanently.
        if file is not None:
            media_file = _add_new_media_file(media_obj, file.filename, file.file)
        else:
            # FIXME: For some reason the media.type isn't ever set to video
            #        during this request. On subsequent requests, when
            #        media_obj.update_type() is called, it is set properly.
            #        This isn't too serious an issue right now because
            #        it is called the first time a moderator goes to review
            #        the new media_obj.
            media_file = MediaFile()
            url = unicode(url)
            for type, info in external_embedded_containers.iteritems():
                match = info['pattern'].match(url)
                if match:
                    media_file.type = guess_media_type(type)
                    media_file.container = type
                    media_file.embed = match.group('id')
                    media_file.display_name = type.capitalize() + ' ID: ' + media_file.embed
                    break
            else:
                # Trigger a validation error on the whole form.
                raise formencode.Invalid('Please specify a URL or upload a file below.', None, None)
            media_obj.files.append(media_file)

        # Add the final changes.
        media_obj.update_type()
        media_obj.update_status()
        DBSession.add(media_obj)
        DBSession.flush()

        create_default_thumbs_for(media_obj)

        return media_obj
Exemple #10
0
    def add_file(self, id, file=None, url=None, **kwargs):
        """Save action for the :class:`~mediacore.forms.admin.media.AddFileForm`.

        Creates a new :class:`~mediacore.model.media.MediaFile` from the
        uploaded file or the local or remote URL.

        :param id: Media ID. If ``"new"`` a new Media stub is created with
            :func:`~mediacore.model.media.create_media_stub`.
        :type id: :class:`int` or ``"new"``
        :param file: The uploaded file
        :type file: :class:`cgi.FieldStorage` or ``None``
        :param url: A URL to a recognizable audio or video file
        :type url: :class:`unicode` or ``None``
        :rtype: JSON dict
        :returns:
            success
                bool
            message
                Error message, if unsuccessful
            media_id
                The :attr:`~mediacore.model.media.Media.id` which is
                important if new media has just been created.
            file_id
                The :attr:`~mediacore.model.media.MediaFile.id` for the newly
                created file.
            edit_form
                The rendered XHTML :class:`~mediacore.forms.admin.media.EditFileForm`
                for this file.
            status_form
                The rendered XHTML :class:`~mediacore.forms.admin.media.UpdateStatusForm`

        """
        if id == 'new':
            media = create_media_stub()
        else:
            media = fetch_row(Media, id)

        data = dict(success=False)

        if file is not None:
            # Create a media object, add it to the video, and store the file permanently.
            media_file = _add_new_media_file(media, file.filename, file.file)
            data['success'] = True
        elif url:
            media_file = MediaFile()
            # Parse the URL checking for known embeddables like YouTube
            for type, info in external_embedded_containers.iteritems():
                match = info['pattern'].match(url)
                if match:
                    media_file.type = guess_media_type(type)
                    media_file.container = type
                    media_file.embed = match.group('id')
                    media_file.display_name = type.capitalize() + ' ID: ' + media_file.embed
                    data['success'] = True
                    break
            else:
                # Check for types we can play ourselves
                try:
                    ext = os.path.splitext(url)[1].lower()[1:]
                    container = guess_container_format(ext)
                except KeyError:
                    container = None
                for conts in playable_containers.itervalues():
                    if container in conts:
                        media_file.type = guess_media_type(container)
                        media_file.container = container
                        media_file.url = url
                        media_file.display_name = os.path.basename(url)
                        data['success'] = True
                        break
                else:
                    data['message'] = 'Unsupported URL'
        else:
            data['message'] = 'No action to perform.'

        if data['success']:
            media.files.append(media_file)
            media.update_type()
            media.update_status()
            DBSession.add(media)
            DBSession.flush()

            if id == 'new':
                helpers.create_default_thumbs_for(media)

            # Render some widgets so the XHTML can be injected into the page
            edit_form_xhtml = unicode(edit_file_form.display(
                action=url_for(action='edit_file', id=media.id),
                file=media_file))
            status_form_xhtml = unicode(update_status_form.display(
                action=url_for(action='update_status', id=media.id),
                media=media))

            data.update(dict(
                media_id = media.id,
                file_id = media_file.id,
                file_type = media_file.type,
                edit_form = edit_form_xhtml,
                status_form = status_form_xhtml,
            ))

        return data