static FileMimeInfo
get_file_mime_info (NautilusFileInfo *file)
{
	FileMimeInfo file_mime_info;
	int          i;

	file_mime_info.is_archive = FALSE;
	file_mime_info.is_derived_archive = FALSE;
	file_mime_info.is_compressed_archive = FALSE;

	for (i = 0; archive_mime_types[i].mime_type != NULL; i++)
		if (nautilus_file_info_is_mime_type (file, archive_mime_types[i].mime_type)) {
			char *mime_type;
			char *content_type_mime_file;
			char *content_type_mime_compare;

			mime_type = nautilus_file_info_get_mime_type (file);

			content_type_mime_file = g_content_type_from_mime_type (mime_type);
			content_type_mime_compare = g_content_type_from_mime_type (archive_mime_types[i].mime_type);

			file_mime_info.is_archive = TRUE;
			file_mime_info.is_compressed_archive = archive_mime_types[i].is_compressed;
			if ((content_type_mime_file != NULL) && (content_type_mime_compare != NULL))
				file_mime_info.is_derived_archive = ! g_content_type_equals (content_type_mime_file, content_type_mime_compare);

			g_free (mime_type);
			g_free (content_type_mime_file);
			g_free (content_type_mime_compare);

			return file_mime_info;
		}

	return file_mime_info;
}
Exemplo n.º 2
0
int
main (int argc, char *argv[])
{
  GtkWidget *chooser;
  const char *uri;
  g_autoptr (GOptionContext) context = NULL;
  GError *error = NULL;

  gtk_init (NULL, NULL);

  chooser = cc_content_chooser_new ();

  context = g_option_context_new (NULL);
  g_option_context_add_main_entries (context, entries, "");
  if (!g_option_context_parse (context, &argc, &argv, &error))
    {
      g_printerr ("Failed to parse commandline: %s\n", error->message);
      return 1;
    }

  if (app_id)
    cc_content_chooser_set_app_id (CC_CONTENT_CHOOSER (chooser), app_id);

  if (g_strcmp0 (action, "open") == 0)
    cc_content_chooser_set_action (CC_CONTENT_CHOOSER (chooser), CC_CONTENT_CHOOSER_ACTION_OPEN);
  else if (g_strcmp0 (action, "create") == 0)
    cc_content_chooser_set_action (CC_CONTENT_CHOOSER (chooser), CC_CONTENT_CHOOSER_ACTION_CREATE);
  else
    {
      g_printerr ("Not a valid content chooser action: %s\n", action);
      return 1;
    }

  if (title)
    cc_content_chooser_set_title (CC_CONTENT_CHOOSER (chooser), title);

  if (argc > 1)
    {
      char **types;
      int i, j;

      types = g_new (char *, argc);
      for (i = 1, j = 0; i < argc; i++)
        {
          types[j] = g_content_type_from_mime_type (argv[i]);
          if (types[j] == NULL)
            {
              g_printerr ("Not a valid mime type: %s\n", argv[i]);
              continue;
            }

          j++;
        }
      types[j] = NULL;

      cc_content_chooser_set_mime_types (CC_CONTENT_CHOOSER (chooser), (const char **)types);

      g_strfreev (types);
    }
Exemplo n.º 3
0
void
zathura_plugin_add_mimetype(zathura_plugin_t* plugin, const char* mime_type)
{
  if (plugin == NULL || mime_type == NULL) {
    return;
  }

  girara_list_append(plugin->content_types, g_content_type_from_mime_type(mime_type));
}
Exemplo n.º 4
0
static GIcon *
icon_for_mimetype (const char *mimetype)
{
  char *content_type;
  GIcon *icon;

  content_type = g_content_type_from_mime_type (mimetype);
  if (!content_type)
    return NULL;

  icon = g_content_type_get_icon (content_type);
  g_free (content_type);
  return icon;
}
Exemplo n.º 5
0
GIcon *
mousepad_util_icon_for_mime_type (const gchar *mime_type)
{
  gchar *content_type;
  GIcon *icon = NULL;

  g_return_val_if_fail (mime_type != NULL, NULL);

  content_type = g_content_type_from_mime_type (mime_type);
  if (content_type != NULL)
    icon = g_content_type_get_icon (content_type);

  return icon;
}
Exemplo n.º 6
0
NS_IMETHODIMP
nsGIOService::GetDescriptionForMimeType(const nsACString& aMimeType,
                                              nsACString& aDescription)
{
  char *content_type =
    g_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
  if (!content_type)
    return NS_ERROR_FAILURE;

  char *desc = g_content_type_get_description(content_type);
  if (!desc) {
    g_free(content_type);
    return NS_ERROR_FAILURE;
  }

  aDescription.Assign(desc);
  g_free(content_type);
  g_free(desc);
  return NS_OK;
}
Exemplo n.º 7
0
NS_IMETHODIMP
nsGIOService::GetAppForMimeType(const nsACString& aMimeType,
                                nsIGIOMimeApp**   aApp)
{
  *aApp = nullptr;
  char *content_type =
    g_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
  if (!content_type)
    return NS_ERROR_FAILURE;

  GAppInfo *app_info = g_app_info_get_default_for_type(content_type, false);
  if (app_info) {
    nsGIOMimeApp *mozApp = new nsGIOMimeApp(app_info);
    NS_ENSURE_TRUE(mozApp, NS_ERROR_OUT_OF_MEMORY);
    NS_ADDREF(*aApp = mozApp);
  } else {
    g_free(content_type);
    return NS_ERROR_FAILURE;
  }
  g_free(content_type);
  return NS_OK;
}
Exemplo n.º 8
0
wxString wxGTKMimeTypesManagerImpl::GetIconFromMimeType(const wxString& mime)
{
    wxString icon;
#if GTK_CHECK_VERSION(2,14,0)
    if (!wx_is_at_least_gtk2(14))
        return icon;

    wxGtkString type(g_content_type_from_mime_type(mime.utf8_str()));

    wxGtkObject<GIcon> gicon(g_content_type_get_icon(type));
    if ( !gicon )
        return icon;

    GtkIconTheme *theme(gtk_icon_theme_get_default());
    if ( !theme )
        return icon;

    // Notice that we can't use wxGtkObject here because a special function
    // needs to be used for freeing this object prior to GTK+ 3.8.
    GtkIconInfo* const giconinfo = gtk_icon_theme_lookup_by_gicon
                                   (
                                        theme,
                                        gicon,
                                        256,
                                        GTK_ICON_LOOKUP_NO_SVG
                                   );

    if ( giconinfo )
    {
        icon = wxString::FromUTF8(gtk_icon_info_get_filename(giconinfo));

        wxGCC_WARNING_SUPPRESS(deprecated-declarations)
        gtk_icon_info_free(giconinfo);
        wxGCC_WARNING_RESTORE()
    }
#endif // GTK_CHECK_VERSION(2,14,0)
    return icon;
}
Exemplo n.º 9
0
NS_IMETHODIMP
nsGIOMimeApp::SetAsDefaultForMimeType(nsACString const& aMimeType)
{
  char *content_type =
    g_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
  if (!content_type)
    return NS_ERROR_FAILURE;
  GError *error = nullptr;
  g_app_info_set_as_default_for_type(mApp,
                                     content_type,
                                     &error);
  if (error) {
    g_warning("Cannot set application as default for MIME type (%s): %s",
              PromiseFlatCString(aMimeType).get(),
              error->message);
    g_error_free(error);
    g_free(content_type);
    return NS_ERROR_FAILURE;
  }

  g_free(content_type);
  return NS_OK;
}
Exemplo n.º 10
0
static VALUE
rg_s_from_mime_type(G_GNUC_UNUSED VALUE type)
{
        return CSTR2RVAL(g_content_type_from_mime_type(RVAL2CSTR(type)));
}
nsresult
nsIconChannel::InitWithGIO(nsIMozIconURI *aIconURI)
{
    GIcon *icon = NULL;
    nsCOMPtr<nsIURL> fileURI;

    // Read icon content
    aIconURI->GetIconURL(getter_AddRefs(fileURI));

    // Get icon for file specified by URI
    if (fileURI) {
        bool isFile;
        nsAutoCString spec;
        fileURI->GetAsciiSpec(spec);
        if (NS_SUCCEEDED(fileURI->SchemeIs("file", &isFile)) && isFile) {
            GFile *file = g_file_new_for_uri(spec.get());
            GFileInfo *fileInfo = g_file_query_info(file,
                                                    G_FILE_ATTRIBUTE_STANDARD_ICON,
                                                    G_FILE_QUERY_INFO_NONE, NULL, NULL);
            g_object_unref(file);
            if (fileInfo) {
                // icon from g_content_type_get_icon doesn't need unref
                icon = g_file_info_get_icon(fileInfo);
                if (icon)
                    g_object_ref(icon);
                g_object_unref(fileInfo);
            }
        }
    }

    // Try to get icon by using MIME type
    if (!icon) {
        nsAutoCString type;
        aIconURI->GetContentType(type);
        // Try to get MIME type from file extension by using nsIMIMEService
        if (type.IsEmpty()) {
            nsCOMPtr<nsIMIMEService> ms(do_GetService("@mozilla.org/mime;1"));
            if (ms) {
                nsAutoCString fileExt;
                aIconURI->GetFileExtension(fileExt);
                ms->GetTypeFromExtension(fileExt, type);
            }
        }
        char *ctype = NULL; // character representation of content type
        if (!type.IsEmpty()) {
            ctype = g_content_type_from_mime_type(type.get());
        }
        if (ctype) {
            icon = g_content_type_get_icon(ctype);
            g_free(ctype);
        }
    }

    // Get default icon theme
    GtkIconTheme *iconTheme = gtk_icon_theme_get_default();
    GtkIconInfo *iconInfo = NULL;
    // Get icon size
    int32_t iconSize = GetIconSize(aIconURI);

    if (icon) {
        // Use icon and theme to get GtkIconInfo
        iconInfo = gtk_icon_theme_lookup_by_gicon(iconTheme,
                   icon, iconSize,
                   (GtkIconLookupFlags)0);
        g_object_unref(icon);
    }

    if (!iconInfo) {
        // Mozilla's mimetype lookup failed. Try the "unknown" icon.
        iconInfo = gtk_icon_theme_lookup_icon(iconTheme,
                                              "unknown", iconSize,
                                              (GtkIconLookupFlags)0);
        if (!iconInfo) {
            return NS_ERROR_NOT_AVAILABLE;
        }
    }

    // Create a GdkPixbuf buffer containing icon and scale it
    GdkPixbuf* buf = gtk_icon_info_load_icon(iconInfo, NULL);
    gtk_icon_info_free(iconInfo);
    if (!buf) {
        return NS_ERROR_UNEXPECTED;
    }

    nsresult rv = ScaleIconBuf(&buf, iconSize);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = moz_gdk_pixbuf_to_channel(buf, aIconURI,
                                   getter_AddRefs(mRealChannel));
    g_object_unref(buf);
    return rv;
}
Exemplo n.º 12
0
static gboolean
video_area_expose_event_cb (GtkWidget      *widget,
			    GdkEventExpose *event,
			    gpointer        user_data)
{
	GthMediaViewerPage *self = user_data;

	if (event->count > 0)
		return FALSE;

	if (self->priv->xwin_assigned && self->priv->has_video)
		return FALSE;

	if (self->priv->icon == NULL) {
		char  *type;
		GIcon *icon;
		int    size;

		type = NULL;
		if (self->priv->file_data != NULL)
			type = g_content_type_from_mime_type (gth_file_data_get_mime_type (self->priv->file_data));
		if (type == NULL)
			type = g_content_type_from_mime_type ("text/plain");
		icon = g_content_type_get_icon (type);
		size = widget->allocation.width;
		if (size > widget->allocation.height)
			size = widget->allocation.height;
		size = size / 3;
		self->priv->icon = _g_icon_get_pixbuf (icon, size, gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget)));

		g_object_unref (icon);
		g_free (type);
	}

	gdk_draw_rectangle (gtk_widget_get_window (widget),
			    self->priv->has_video ? widget->style->black_gc : widget->style->text_gc[GTK_WIDGET_STATE (widget)],
			    TRUE,
			    event->area.x,
			    event->area.y,
			    event->area.width,
			    event->area.height);

	if (self->priv->icon != NULL) {
		int            icon_w, icon_h;
		int            icon_x, icon_y;
		PangoRectangle logical_rect;
		int            x, y;

		icon_w = gdk_pixbuf_get_width (self->priv->icon);
		icon_h = gdk_pixbuf_get_height (self->priv->icon);
		pango_layout_set_width (self->priv->caption_layout, PANGO_SCALE * (icon_w * 3 / 2));
		pango_layout_get_extents (self->priv->caption_layout, NULL, &logical_rect);
		icon_x = (widget->allocation.width - icon_w) / 2;
		x = (widget->allocation.width - PANGO_PIXELS (logical_rect.width)) / 2 + PANGO_PIXELS (logical_rect.x);
		icon_y = (widget->allocation.height - (icon_h + PANGO_PIXELS (logical_rect.height))) / 2;
		y = icon_y + icon_h;

		gdk_draw_pixbuf (gtk_widget_get_window (widget),
				 widget->style->base_gc[GTK_WIDGET_STATE (widget)],
				 self->priv->icon,
				 0, 0,
				 icon_x, icon_y,
				 icon_w, icon_h,
				 GDK_RGB_DITHER_NORMAL,
				 0, 0);
		gdk_draw_layout (gtk_widget_get_window (widget),
				 widget->style->base_gc[GTK_WIDGET_STATE (widget)],
				 x, y,
				 self->priv->caption_layout);
	}

	return FALSE;
}
Exemplo n.º 13
0
/*
 * get_document_from_uri:
 * @uri: the document URI
 * @fast: whether to use fast MIME type detection
 * @compression: a location to store the document's compression type
 * @error: a #GError location to store an error, or %NULL
 *
 * Creates a #EvDocument instance for the document at @uri, using either
 * fast or slow MIME type detection. If a document could be created,
 * @compression is filled in with the document's compression type.
 * On error, %NULL is returned and @error filled in.
 * 
 * Returns: a new #EvDocument instance, or %NULL on error with @error filled in
 */
static EvDocument *
get_document_from_uri (const char        *uri,
		       gboolean           fast,
		       EvCompressionType *compression,
		       GError           **error)
{
	EvDocument *document = NULL;
	gchar      *mime_type = NULL;
	GError     *err = NULL;

	*compression = EV_COMPRESSION_NONE;

	mime_type = ev_file_get_mime_type (uri, fast, &err);

	if (mime_type == NULL) {
		g_free (mime_type);

		if (err == NULL) {
			g_set_error_literal (error,
                                             EV_DOCUMENT_ERROR,
                                             EV_DOCUMENT_ERROR_INVALID,
                                             _("Unknown MIME Type"));
		} else {
			g_propagate_error (error, err);
		}
		
		return NULL;
	}

	document = ev_backends_manager_get_document (mime_type);
	
#ifdef ENABLE_PIXBUF
	if (!document && mime_type_supported_by_gdk_pixbuf (mime_type))
		document = ev_backends_manager_get_document ("image/*");
#endif /* ENABLE_PIXBUF */

	if (document == NULL) {
		gchar *content_type, *mime_desc = NULL;

		content_type = g_content_type_from_mime_type (mime_type);
		if (content_type)
			mime_desc = g_content_type_get_description (content_type);

		g_set_error (error,
			     EV_DOCUMENT_ERROR,	
			     EV_DOCUMENT_ERROR_INVALID,
			     _("File type %s (%s) is not supported"),
			     mime_desc ? mime_desc : "-", mime_type);
		g_free (mime_desc);
		g_free (content_type);
		g_free (mime_type);

		return NULL;
	}

	*compression = get_compression_from_mime_type (mime_type);

	g_free (mime_type);
	
        return document;
}
Exemplo n.º 14
0
static gboolean
video_area_draw_cb (GtkWidget *widget,
		    cairo_t   *cr,
		    gpointer   user_data)
{
	GthMediaViewerPage *self = user_data;
	GtkAllocation       allocation;
	GtkStyleContext    *style_context;

	if (self->priv->xwin_assigned && self->priv->has_video)
		return FALSE;

	gtk_widget_get_allocation (widget, &allocation);
	style_context = gtk_widget_get_style_context (widget);

	if (self->priv->icon == NULL) {
		char  *type;
		GIcon *icon;
		int    size;

		type = NULL;
		if (self->priv->file_data != NULL)
			type = g_content_type_from_mime_type (gth_file_data_get_mime_type (self->priv->file_data));
		if (type == NULL)
			type = g_content_type_from_mime_type ("text/plain");
		icon = g_content_type_get_icon (type);
		size = allocation.width;
		if (size > allocation.height)
			size = allocation.height;
		size = size / 3;
		self->priv->icon = _g_icon_get_pixbuf (icon, size, _gtk_widget_get_icon_theme (widget));

		g_object_unref (icon);
		g_free (type);
	}

	cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
	cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
	cairo_fill (cr);

	if (self->priv->icon != NULL) {
		int                   icon_w, icon_h;
		int                   text_w;
		int                   icon_x, icon_y;
		PangoRectangle        logical_rect;
		int                   x, y;
		PangoFontDescription *font;

		icon_w = gdk_pixbuf_get_width (self->priv->icon);
		icon_h = gdk_pixbuf_get_height (self->priv->icon);

		text_w = (icon_w * 3 / 2);
		pango_layout_set_width (self->priv->caption_layout, PANGO_SCALE * text_w);
		pango_layout_get_extents (self->priv->caption_layout, NULL, &logical_rect);

		icon_x = (allocation.width - icon_w) / 2;
		x = (allocation.width - text_w) / 2;

		icon_y = (allocation.height - (icon_h + PANGO_PIXELS (logical_rect.height))) / 2;
		y = icon_y + icon_h;

		gdk_cairo_set_source_pixbuf (cr, self->priv->icon, icon_x, icon_y);
		cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h);
		cairo_fill (cr);

		cairo_move_to (cr, x, y);
		gtk_style_context_get (style_context, gtk_widget_get_state_flags (widget), "font", &font, NULL);
		pango_layout_set_font_description (self->priv->caption_layout, font);
		pango_cairo_layout_path (cr, self->priv->caption_layout);
		cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
		cairo_fill (cr);
	}

	return TRUE;
}
Exemplo n.º 15
0
static void
render_card_init (char *card_fname)
{
	int i;
	if (render_init) {
		for (i = 0; i < 52; i++)
			g_object_unref (card_pixbuf[i]);
		cairo_surface_destroy (grey_surface);
		render_init = 0;
	}

	/* gdk_pixbuf_new_from_file doesn't seem to support .svgz (while
	 * librsvg does), so decompress it here. Code from aisleriot
	 * src/lib/ar-svg.c */
	GFile *cf = g_file_new_for_path (card_fname);
	GFileInfo *info;
	GError *error = NULL;
	if (!(info = g_file_query_info (cf,
					G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
					G_FILE_QUERY_INFO_NONE,
					NULL,
					&error))) {
		printf ("%s: %s\n", card_fname, error->message);
		g_object_unref (cf);
		g_error_free (error);
		return;
	}

	const char *type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
	char *gz_type = g_content_type_from_mime_type ("application/x-gzip");
	gboolean is_gzip = (type != NULL && g_content_type_is_a (type, gz_type));
	g_free (gz_type);
	g_object_unref (info);

	GInputStream *stream;
	if (!(stream = G_INPUT_STREAM (g_file_read (cf, NULL, &error)))) {
		printf ("%s: %s\n", card_fname, error->message);
		g_object_unref (cf);
		g_error_free (error);
		return;
	}
	g_object_unref (cf);

	if (is_gzip) {
		GZlibDecompressor *decompressor;
		GInputStream *converter_stream;

		decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
		converter_stream = g_converter_input_stream_new (stream,
				G_CONVERTER (decompressor));
		g_object_unref (stream);
		stream = converter_stream;
	}

	/* file contains cards in 13 columns (A/2..10/J/Q/K) and 5 rows (C/D/H/S/Jokers) */
	/* actual card height is computed from resulting actual size */
	GdkPixbuf *pb = gdk_pixbuf_new_from_stream_at_scale (stream,
			card_width * 13, -1, TRUE, NULL, &error);
	g_object_unref (stream);
	if (!pb) {
		printf ("%s: %s.\n", card_fname, error->message);
		g_error_free (error);
		return;
	}
	int buf_width = gdk_pixbuf_get_width (pb);
	int buf_height = gdk_pixbuf_get_height (pb);
	card_width = ceil (gdk_pixbuf_get_width (pb) / 13.0);
	card_height = ceil (gdk_pixbuf_get_height (pb) / 5.0);
	for (i = 0; i < 52; i++) {
		card_pixbuf[i] = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, card_width, card_height);
		if (!card_pixbuf[i]) {
			printf ("%s: rendering card_pixbuf failed\n", card_fname);
			return;
		}
		int col = (i + 1) % 13;
		int row = i / 13;
		gdk_pixbuf_copy_area (pb, buf_width * col / 13.0, buf_height * row / 5.0,
		//gdk_pixbuf_copy_area (pb, card_width * col, card_height * row,
			card_width, card_height, card_pixbuf[i], 0, 0);
	}
	g_object_unref (pb);

	/* construct a alpha channel in card shape for greying out cards */
	grey_surface = cairo_image_surface_create (CAIRO_FORMAT_A8, card_width, card_height);
	cairo_t *ct = cairo_create (grey_surface);
	gdk_cairo_set_source_pixbuf (ct, card_pixbuf[0], 0, 0);
	cairo_paint_with_alpha (ct, 0.3);
	cairo_destroy (ct);

	render_init = 1;
}
Exemplo n.º 16
0
static void
fill_open_with_menu (GtkTreeView *view, GtkBuilder *builder, GtkTreePath *path)
{
    GtkTreeModel *model = gtk_tree_view_get_model (view);
    if (!model) {
        return;
    }
    GtkTreeIter iter;
    if (!gtk_tree_model_get_iter(model, &iter, path)) {
        return;
    }
    DatabaseSearchEntry *entry = (DatabaseSearchEntry *)iter.user_data;
    if (!entry) {
        return;
    }

    BTreeNode * node = db_search_entry_get_node (entry);

    GList *app_list = NULL;
    char *content_type = NULL;

    if (node->is_dir) {
        content_type = g_content_type_from_mime_type ("inode/directory");
    }
    else {
        content_type = g_content_type_guess (node->name, NULL, 0, NULL);
    }

    if (!content_type) {
        goto clean_up;
    }

    app_list = g_app_info_get_all_for_type (content_type);
    if (!app_list) {
        goto clean_up;
    }

    GMenu *menu_mime = G_MENU (gtk_builder_get_object (builder,
                                                       "fsearch_listview_menu_open_with_mime_section"));

    for (GList *list_iter = app_list; list_iter; list_iter = list_iter->next) {
        GAppInfo *app_info = list_iter->data;
        const char *display_name = g_app_info_get_display_name (app_info);
        const char *app_id = g_app_info_get_id (app_info);

        char detailed_action[1024] = "";
        snprintf (detailed_action, sizeof (detailed_action), "win.open_with('%s')", app_id);

        GMenuItem *menu_item = g_menu_item_new (display_name, detailed_action);
        g_menu_item_set_icon (menu_item, g_app_info_get_icon (app_info));
        g_menu_append_item (menu_mime, menu_item);
        g_object_unref (menu_item);
    }

clean_up:
    if (content_type) {
        g_free (content_type);
        content_type = NULL;
    }
    if (app_list) {
        g_list_free_full (app_list, g_object_unref);
        app_list = NULL;
    }
}
Exemplo n.º 17
0
static gchar *
get_default_content_type (void)
{
	return g_content_type_from_mime_type ("text/plain");
}
Exemplo n.º 18
0
static EvDocument *
ev_document_factory_new_document_for_mime_type (const gchar *mime_type,
                                                GError **error)
{
        EvDocument    *document;
        EvBackendInfo *info;
        GTypeModule *module = NULL;

        g_return_val_if_fail (mime_type != NULL, NULL);

        info = get_backend_info_for_mime_type (mime_type);
        if (info == NULL) {
                char *content_type, *mime_desc = NULL;

                content_type = g_content_type_from_mime_type (mime_type);
                if (content_type)
                        mime_desc = g_content_type_get_description (content_type);

                g_set_error (error,
                             EV_DOCUMENT_ERROR,
                             EV_DOCUMENT_ERROR_INVALID,
                             _("File type %s (%s) is not supported"),
                             mime_desc ? mime_desc : "(unknown)", mime_type);
                g_free (mime_desc);
                g_free (content_type);

                return NULL;
        }

        if (ev_module_hash != NULL) {
                module = g_hash_table_lookup (ev_module_hash, info->module_name);
        }
        if (module == NULL) {
                gchar *path;

                path = g_module_build_path (ev_backends_dir, info->module_name);
                module = G_TYPE_MODULE (_ev_module_new (path, info->resident));
                g_free (path);

                if (ev_module_hash == NULL) {
                        ev_module_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                                g_free,
                                                                NULL /* leaked on purpose */);
                }
                g_hash_table_insert (ev_module_hash, g_strdup (info->module_name), module);
        }

        if (!g_type_module_use (module)) {
                const char *err;

                err = g_module_error ();
                g_set_error (error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_INVALID,
                             "Failed to load backend for '%s': %s",
                             mime_type, err ? err : "unknown error");
                return NULL;
        }

        document = EV_DOCUMENT (_ev_module_new_object (EV_MODULE (module)));
        g_type_module_unuse (module);

        g_object_set_data_full (G_OBJECT (document), BACKEND_DATA_KEY,
                                _ev_backend_info_ref (info),
                                (GDestroyNotify) _ev_backend_info_unref);

        return document;
}