Added initial processor for ascii media
[mediagoblin.git] / mediagoblin / media_types / __init__.py
index 2d13f5a6ce35d4742d7daf7663d004eb2035165e..134157dcb0ca7054fdf5043bef82548137ef7373 100644 (file)
@@ -1,5 +1,5 @@
 # GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 MediaGoblin contributors.  See AUTHORS.
+# 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
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import os
-import sys
+import logging
+import tempfile
 
-from mediagoblin.util import lazy_pass_to_ugettext as _
+from mediagoblin.tools.pluginapi import hook_handle
+from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
 
+_log = logging.getLogger(__name__)
 
 class FileTypeNotSupported(Exception):
     pass
@@ -26,51 +29,72 @@ class FileTypeNotSupported(Exception):
 class InvalidFileType(Exception):
     pass
 
-# This should be more dynamic in the future. Perhaps put it in the .ini?
-# -- Joar
-MEDIA_TYPES = [
-        'mediagoblin.media_types.image',
-        'mediagoblin.media_types.video']
 
+class MediaManagerBase(object):
+    "Base class for all media managers"
 
-def get_media_types():
-    '''
-    Generator that returns the available media types
-    '''
-    for media_type in MEDIA_TYPES:
-        yield media_type
+    # Please override in actual media managers
+    media_fetch_order = None
+
+    @staticmethod
+    def sniff_handler(*args, **kwargs):
+        return False
+
+    def __init__(self, entry):
+        self.entry = entry
+
+    def __getitem__(self, i):
+        return getattr(self, i)
+
+    def __contains__(self, i):
+        return hasattr(self, i)
 
 
-def get_media_managers():
+def sniff_media(media):
     '''
-    Generator that returns all available media managers
+    Iterate through the enabled media types and find those suited
+    for a certain file.
     '''
-    for media_type in get_media_types():
-        try:
-            __import__(media_type)
-        except ImportError as e:
-            raise Exception(
-                _('ERROR: Could not import {media_type}: {exception}').format(
-                    media_type=media_type,
-                    exception=e))
-            
-        yield media_type, sys.modules[media_type].MEDIA_MANAGER
 
+    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.stream.read())
+        media.stream.seek(0)
 
-def get_media_manager(_media_type = None):
-    for media_type, manager in get_media_managers():
-        if media_type in _media_type:
-            return manager
+        media_type = hook_handle('sniff_handler', media_file, media=media)
+        if media_type:
+            _log.info('{0} accepts the file'.format(media_type))
+            return media_type, hook_handle(('media_manager', media_type))
+        else:
+            _log.debug('{0} did not accept the file'.format(media_type))
+
+    raise FileTypeNotSupported(
+        # TODO: Provide information on which file types are supported
+        _(u'Sorry, I don\'t support that file type :('))
 
 
 def get_media_type_and_manager(filename):
-    for media_type, manager in get_media_managers():
-        if filename.find('.') > 0:
-            ext = os.path.splitext(filename)[1].lower()
-        else:
-            raise InvalidFileType(
-                _('Could not find any file extension in "{filename}"').format(
-                    filename=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()
+
+        # Omit the dot from the extension and match it against
+        # the media manager
+        if hook_handle('get_media_type_and_manager', ext[1:]):
+            return hook_handle('get_media_type_and_manager', ext[1:])
+    else:
+        _log.info('File {0} has no file extension, let\'s hope the sniffers get it.'.format(
+            filename))
 
-        if ext[1:] in manager['accepted_extensions']:
-            return media_type, manager
+    raise FileTypeNotSupported(
+        _(u'Sorry, I don\'t support that file type :('))