aboutsummaryrefslogtreecommitdiffstats
path: root/modules/audio-inline
diff options
context:
space:
mode:
Diffstat (limited to 'modules/audio-inline')
-rw-r--r--modules/audio-inline/Makefile.am31
-rw-r--r--modules/audio-inline/e-mail-formatter-audio-inline.c383
-rw-r--r--modules/audio-inline/e-mail-formatter-audio-inline.h30
-rw-r--r--modules/audio-inline/e-mail-parser-audio-inline.c199
-rw-r--r--modules/audio-inline/e-mail-parser-audio-inline.h30
-rw-r--r--modules/audio-inline/e-mail-part-audio-inline.h46
-rw-r--r--modules/audio-inline/evolution-module-audio-inline.c54
7 files changed, 773 insertions, 0 deletions
diff --git a/modules/audio-inline/Makefile.am b/modules/audio-inline/Makefile.am
new file mode 100644
index 0000000000..152086ba08
--- /dev/null
+++ b/modules/audio-inline/Makefile.am
@@ -0,0 +1,31 @@
+module_LTLIBRARIES = module-audio-inline.la
+
+module_audio_inline_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/widgets \
+ -DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\" \
+ -DG_LOG_DOMAIN=\"evolution-module-audio-inline\" \
+ $(EVOLUTION_DATA_SERVER_CFLAGS) \
+ $(GNOME_PLATFORM_CFLAGS) \
+ $(GSTREAMER_CFLAGS)
+
+module_audio_inline_la_SOURCES = \
+ e-mail-formatter-audio-inline.c \
+ e-mail-formatter-audio-inline.h \
+ e-mail-parser-audio-inline.c \
+ e-mail-parser-audio-inline.h \
+ evolution-module-audio-inline.c
+
+module_audio_inline_la_LIBADD = \
+ $(top_builddir)/e-util/libeutil.la \
+ $(top_builddir)/mail/libevolution-mail.la \
+ $(top_builddir)/em-format/libemformat.la \
+ $(EVOLUTION_DATA_SERVER_LIBS) \
+ $(GNOME_PLATFORM_LIBS) \
+ $(GSTREAMER_LIBS)
+
+module_audio_inline_la_LDFLAGS = \
+ -avoid-version -module $(NO_UNDEFINED)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/audio-inline/e-mail-formatter-audio-inline.c b/modules/audio-inline/e-mail-formatter-audio-inline.c
new file mode 100644
index 0000000000..4116748923
--- /dev/null
+++ b/modules/audio-inline/e-mail-formatter-audio-inline.c
@@ -0,0 +1,383 @@
+/*
+ * e-mail-formatter-audio-inline.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-formatter-audio-inline.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/libebackend.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+
+#include "e-util/e-mktemp.h"
+
+#include <camel/camel.h>
+#include <gst/gst.h>
+
+#include "e-mail-part-audio-inline.h"
+
+#define d(x)
+
+typedef struct _EMailFormatterAudioInline {
+ EExtension parent;
+} EMailFormatterAudioInline;
+
+typedef struct _EMailFormatterAudioInlineClass {
+ EExtensionClass parent_class;
+} EMailFormatterAudioInlineClass;
+
+GType e_mail_formatter_audio_inline_get_type (void);
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+ EMailFormatterAudioInline,
+ e_mail_formatter_audio_inline,
+ E_TYPE_EXTENSION,
+ 0,
+ G_IMPLEMENT_INTERFACE_DYNAMIC (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE_DYNAMIC (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init));
+
+static const gchar* formatter_mime_types[] = { "application/vnd.evolution.widget.audio-inline",
+ "audio/ac3", "audio/x-ac3",
+ "audio/basic", "audio/mpeg",
+ "audio/x-mpeg", "audio/mpeg3",
+ "audio/x-mpeg3", "audio/mp3",
+ "audio/x-mp3", "audio/mp4",
+ "audio/flac", "audio/x-flac",
+ "audio/mod", "audio/x-mod",
+ "audio/x-wav", "audio/microsoft-wav",
+ "audio/x-wma", "audio/x-ms-wma",
+ "application/ogg", "application/x-ogg",
+ NULL };
+
+static void
+pause_clicked (GtkWidget *button,
+ EMailPartAudioInline *part)
+{
+ if (part->playbin) {
+ /* pause playing */
+ gst_element_set_state (part->playbin, GST_STATE_PAUSED);
+ }
+}
+
+static void
+stop_clicked (GtkWidget *button,
+ EMailPartAudioInline *part)
+{
+ if (part->playbin) {
+ /* ready to play */
+ gst_element_set_state (part->playbin, GST_STATE_READY);
+ part->target_state = GST_STATE_READY;
+ }
+}
+
+static void
+set_audiosink (GstElement *playbin)
+{
+ GstElement *audiosink;
+
+ /* now it's time to get the audio sink */
+ audiosink = gst_element_factory_make ("gconfaudiosink", "play_audio");
+ if (audiosink == NULL) {
+ audiosink = gst_element_factory_make ("autoaudiosink", "play_audio");
+ }
+
+ if (audiosink) {
+ g_object_set (playbin, "audio-sink", audiosink, NULL);
+ }
+}
+
+static gboolean
+gst_callback (GstBus *bus,
+ GstMessage *message,
+ gpointer data)
+{
+ EMailPartAudioInline *part = data;
+ GstMessageType msg_type;
+
+ g_return_val_if_fail (part != NULL, TRUE);
+ g_return_val_if_fail (part->playbin != NULL, TRUE);
+
+ msg_type = GST_MESSAGE_TYPE (message);
+
+ switch (msg_type) {
+ case GST_MESSAGE_ERROR:
+ gst_element_set_state (part->playbin, GST_STATE_NULL);
+ break;
+ case GST_MESSAGE_EOS:
+ gst_element_set_state (part->playbin, GST_STATE_READY);
+ break;
+ case GST_MESSAGE_STATE_CHANGED:
+ {
+ GstState old_state, new_state;
+
+ if (GST_MESSAGE_SRC (message) != GST_OBJECT (part->playbin))
+ break;
+
+ gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
+
+ if (old_state == new_state)
+ break;
+
+ if (part->play_button)
+ gtk_widget_set_sensitive (
+ part->play_button,
+ new_state <= GST_STATE_PAUSED);
+ if (part->pause_button)
+ gtk_widget_set_sensitive (
+ part->pause_button,
+ new_state > GST_STATE_PAUSED);
+ if (part->stop_button)
+ gtk_widget_set_sensitive (
+ part->stop_button,
+ new_state >= GST_STATE_PAUSED);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+play_clicked (GtkWidget *button,
+ EMailPartAudioInline *part)
+{
+ GstState cur_state;
+
+ d(printf ("audio inline formatter: play\n"));
+
+ if (!part->filename) {
+ CamelStream *stream;
+ CamelDataWrapper *data;
+ GError *error = NULL;
+ gint argc = 1;
+ const gchar *argv [] = { "org_gnome_audio_inline", NULL };
+
+ /* FIXME this is ugly, we should stream this directly to gstreamer */
+ part->filename = e_mktemp ("org-gnome-audio-inline-file-XXXXXX");
+
+ d(printf ("audio inline formatter: write to temp file %s\n", po->filename));
+
+ stream = camel_stream_fs_new_with_name (
+ part->filename, O_RDWR | O_CREAT | O_TRUNC, 0600, NULL);
+ data = camel_medium_get_content (CAMEL_MEDIUM (part->parent.part));
+ camel_data_wrapper_decode_to_stream_sync (data, stream, NULL, NULL);
+ camel_stream_flush (stream, NULL, NULL);
+ g_object_unref (stream);
+
+ d(printf ("audio inline formatter: init gst playbin\n"));
+
+ if (gst_init_check (&argc, (gchar ***) &argv, &error)) {
+ gchar *uri;
+ GstBus *bus;
+
+ /* create a disk reader */
+ part->playbin = gst_element_factory_make ("playbin", "playbin");
+ if (part->playbin == NULL) {
+ g_printerr ("Failed to create gst_element_factory playbin; check your installation\n");
+ return;
+
+ }
+
+ uri = g_filename_to_uri (part->filename, NULL, NULL);
+ g_object_set (part->playbin, "uri", uri, NULL);
+ g_free (uri);
+ set_audiosink (part->playbin);
+
+ bus = gst_element_get_bus (part->playbin);
+ part->bus_id = gst_bus_add_watch (bus, gst_callback, part);
+ gst_object_unref (bus);
+
+ } else {
+ g_printerr ("GStreamer failed to initialize: %s",error ? error->message : "");
+ g_error_free (error);
+ }
+ }
+
+ gst_element_get_state (part->playbin, &cur_state, NULL, 0);
+
+ if (cur_state >= GST_STATE_PAUSED) {
+ gst_element_set_state (part->playbin, GST_STATE_READY);
+ }
+
+ if (part->playbin) {
+ /* start playing */
+ gst_element_set_state (part->playbin, GST_STATE_PLAYING);
+ }
+}
+
+static GtkWidget *
+add_button (GtkWidget *box,
+ const gchar *stock_icon,
+ GCallback cb,
+ gpointer data,
+ gboolean sensitive)
+{
+ GtkWidget *button;
+
+ button = gtk_button_new_from_stock (stock_icon);
+ gtk_widget_set_sensitive (button, sensitive);
+ g_signal_connect (button, "clicked", cb, data);
+
+ gtk_widget_show (button);
+ gtk_box_pack_end (GTK_BOX (box), button, TRUE, TRUE, 0);
+
+ return button;
+}
+
+static gboolean
+emfe_audio_inline_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ gchar *str;
+
+ str = g_strdup_printf (
+ "<object type=\"application/vnd.evolution.widget.audio-inline\" "
+ "width=\"100%%\" height=\"auto\" data=\"%s\" id=\"%s\"></object>",
+ part->id, part->id);
+
+ camel_stream_write_string (stream, str, cancellable, NULL);
+
+ g_free (str);
+
+ return TRUE;
+}
+
+static GtkWidget *
+emfe_audio_inline_get_widget (EMailFormatterExtension *extension,
+ EMailPartList *context,
+ EMailPart *part,
+ GHashTable *params)
+{
+ GtkWidget *box;
+ EMailPartAudioInline *ai_part;
+
+ g_return_val_if_fail (E_MAIL_PART_IS (part, EMailPartAudioInline), NULL);
+ ai_part = (EMailPartAudioInline *) part;
+
+ /* it is OK to call UI functions here, since we are called from UI thread */
+ box = gtk_hbutton_box_new ();
+ ai_part->play_button = g_object_ref (
+ add_button (box, GTK_STOCK_MEDIA_PLAY,
+ G_CALLBACK (play_clicked), part, TRUE));
+ ai_part->pause_button = g_object_ref (
+ add_button (box, GTK_STOCK_MEDIA_PAUSE,
+ G_CALLBACK (pause_clicked), part, FALSE));
+ ai_part->stop_button = g_object_ref (
+ add_button (box, GTK_STOCK_MEDIA_STOP,
+ G_CALLBACK (stop_clicked), part, FALSE));
+
+ gtk_widget_show (box);
+
+ return box;
+}
+
+static const gchar *
+emfe_audio_inline_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("Audio Player");
+}
+
+static const gchar *
+emfe_audio_inline_get_description (EMailFormatterExtension *extension)
+{
+ return _("Play the attachment in embedded audio player");
+}
+
+static const gchar **
+emfe_audio_inline_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_audio_inline_constructed (GObject *object)
+{
+ EExtensible *extensible;
+ EMailExtensionRegistry *reg;
+
+ extensible = e_extension_get_extensible (E_EXTENSION (object));
+ reg = E_MAIL_EXTENSION_REGISTRY (extensible);
+
+ e_mail_extension_registry_add_extension (reg, E_MAIL_EXTENSION (object));
+}
+
+static void
+e_mail_formatter_audio_inline_class_init (EMailFormatterAudioInlineClass *klass)
+{
+ GObjectClass *object_class;
+ EExtensionClass *extension_class;
+
+ e_mail_formatter_audio_inline_parent_class = g_type_class_peek_parent (klass);
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = e_mail_formatter_audio_inline_constructed;
+
+ extension_class = E_EXTENSION_CLASS (klass);
+ extension_class->extensible_type = E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY;
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_audio_inline_format;
+ iface->get_widget = emfe_audio_inline_get_widget;
+ iface->get_display_name = emfe_audio_inline_get_display_name;
+ iface->get_description = emfe_audio_inline_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_audio_inline_mime_types;
+}
+
+static void
+e_mail_formatter_audio_inline_init (EMailFormatterAudioInline *formatter)
+{
+
+}
+
+void
+e_mail_formatter_audio_inline_type_register (GTypeModule *type_module)
+{
+ e_mail_formatter_audio_inline_register_type (type_module);
+}
+
+static void
+e_mail_formatter_audio_inline_class_finalize (EMailFormatterAudioInlineClass *klass)
+{
+
+}
diff --git a/modules/audio-inline/e-mail-formatter-audio-inline.h b/modules/audio-inline/e-mail-formatter-audio-inline.h
new file mode 100644
index 0000000000..1960f382da
--- /dev/null
+++ b/modules/audio-inline/e-mail-formatter-audio-inline.h
@@ -0,0 +1,30 @@
+/*
+ * e-mail-formatter-audio-inline.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_FORMATTER_AUDIO_INLINE_H
+#define E_MAIL_FORMATTER_AUDIO_INLINE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_mail_formatter_audio_inline_type_register (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_FORMATTER_AUDIO_INLINE_H */
diff --git a/modules/audio-inline/e-mail-parser-audio-inline.c b/modules/audio-inline/e-mail-parser-audio-inline.c
new file mode 100644
index 0000000000..0e872971f4
--- /dev/null
+++ b/modules/audio-inline/e-mail-parser-audio-inline.c
@@ -0,0 +1,199 @@
+/*
+ * e-mail-parser-audio-inline.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include "e-mail-parser-audio-inline.h"
+#include "e-mail-part-audio-inline.h"
+
+#include <camel/camel.h>
+
+#include <em-format/e-mail-extension-registry.h>
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-part.h>
+
+#include <libebackend/libebackend.h>
+
+#define d(x)
+
+typedef struct _EMailParserInlineAudio {
+ EExtension parent;
+} EMailParserAudioInline;
+
+typedef struct _EMailParserAudioInlineClass {
+ EExtensionClass parent_class;
+} EMailParserAudioInlineClass;
+
+GType e_mail_parser_audio_inline_get_type (void);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+ EMailParserAudioInline,
+ e_mail_parser_audio_inline,
+ E_TYPE_EXTENSION,
+ 0,
+ G_IMPLEMENT_INTERFACE_DYNAMIC (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE_DYNAMIC (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "audio/ac3", "audio/x-ac3",
+ "audio/basic", "audio/mpeg",
+ "audio/x-mpeg", "audio/mpeg3",
+ "audio/x-mpeg3", "audio/mp3",
+ "audio/x-mp3", "audio/mp4",
+ "audio/flac", "audio/x-flac",
+ "audio/mod", "audio/x-mod",
+ "audio/x-wav", "audio/microsoft-wav",
+ "audio/x-wma", "audio/x-ms-wma",
+ "application/ogg", "application/x-ogg",
+ NULL };
+
+static void
+mail_part_audio_inline_free (EMailPart *mail_part)
+{
+ EMailPartAudioInline *ai_part = (EMailPartAudioInline *) mail_part;
+
+ g_clear_object (&ai_part->play_button);
+ g_clear_object (&ai_part->pause_button);
+ g_clear_object (&ai_part->stop_button);
+
+ if (ai_part->filename) {
+ g_unlink (ai_part->filename);
+ g_free (ai_part->filename);
+ ai_part->filename = NULL;
+ }
+
+ if (ai_part->bus_id) {
+ g_source_remove (ai_part->bus_id);
+ ai_part->bus_id = 0;
+ }
+
+ if (ai_part->playbin) {
+ gst_element_set_state (ai_part->playbin, GST_STATE_NULL);
+ gst_object_unref (ai_part->playbin);
+ ai_part->playbin = NULL;
+ }
+}
+
+static GSList *
+empe_audio_inline_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPartAudioInline *mail_part;
+ gint len;
+
+ len = part_id->len;
+ g_string_append (part_id, ".org-gnome-audio-inline-button-panel");
+
+ d(printf ("audio inline formatter: format classid %s\n", part_id->str));
+
+ mail_part = (EMailPartAudioInline *) e_mail_part_subclass_new (
+ part, part_id->str, sizeof (EMailPartAudioInline),
+ (GFreeFunc) mail_part_audio_inline_free);
+ mail_part->parent.mime_type = camel_content_type_simple (
+ camel_mime_part_get_content_type (part));
+ mail_part->parent.is_attachment = TRUE;
+ g_string_truncate (part_id, len);
+
+ return e_mail_parser_wrap_as_attachment (
+ parser, part, g_slist_append (NULL, mail_part),
+ part_id, cancellable);
+}
+
+static guint32
+empe_audio_inline_get_flags (EMailParserExtension *extension)
+{
+ return E_MAIL_PARSER_EXTENSION_INLINE_DISPOSITION;
+}
+
+static const gchar **
+empe_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+void
+e_mail_parser_audio_inline_type_register (GTypeModule *type_module)
+{
+ e_mail_parser_audio_inline_register_type (type_module);
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mime_types;
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_audio_inline_parse;
+ iface->get_flags = empe_audio_inline_get_flags;
+}
+
+static void
+e_mail_parser_audio_inline_constructed (GObject *object)
+{
+ EExtensible *extensible;
+ EMailExtensionRegistry *reg;
+
+ extensible = e_extension_get_extensible (E_EXTENSION (object));
+ reg = E_MAIL_EXTENSION_REGISTRY (extensible);
+
+ e_mail_extension_registry_add_extension (reg, E_MAIL_EXTENSION (object));
+}
+
+static void
+e_mail_parser_audio_inline_class_init (EMailParserAudioInlineClass *klass)
+{
+ GObjectClass *object_class;
+ EExtensionClass *extension_class;
+
+ e_mail_parser_audio_inline_parent_class = g_type_class_peek_parent (klass);
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = e_mail_parser_audio_inline_constructed;
+
+ extension_class = E_EXTENSION_CLASS (klass);
+ extension_class->extensible_type = E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY;
+}
+
+static void
+e_mail_parser_audio_inline_class_finalize (EMailParserAudioInlineClass *klass)
+{
+
+}
+
+static void
+e_mail_parser_audio_inline_init (EMailParserAudioInline *self)
+{
+}
diff --git a/modules/audio-inline/e-mail-parser-audio-inline.h b/modules/audio-inline/e-mail-parser-audio-inline.h
new file mode 100644
index 0000000000..8c80becb20
--- /dev/null
+++ b/modules/audio-inline/e-mail-parser-audio-inline.h
@@ -0,0 +1,30 @@
+/*
+ * e-mail-parser-audio-inline.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PARSER_AUDIO_INLINE_H
+#define E_MAIL_PARSER_AUDIO_INLINE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_mail_parser_audio_inline_type_register (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PARSER_AUDIO_INLINE_H */
diff --git a/modules/audio-inline/e-mail-part-audio-inline.h b/modules/audio-inline/e-mail-part-audio-inline.h
new file mode 100644
index 0000000000..e087ecdff6
--- /dev/null
+++ b/modules/audio-inline/e-mail-part-audio-inline.h
@@ -0,0 +1,46 @@
+/*
+ * e-mail-part-audio-inline.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PART_AUDIO_INLINE_H
+#define E_MAIL_PART_AUDIO_INLINE_H
+
+#include <glib-object.h>
+
+#include <em-format/e-mail-part.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+typedef struct _EMailPartAudioInline EMailPartAudioInline;
+
+struct _EMailPartAudioInline {
+ EMailPart parent;
+
+ gchar *filename;
+ GstElement *playbin;
+ gulong bus_id;
+ GstState target_state;
+ GtkWidget *play_button;
+ GtkWidget *pause_button;
+ GtkWidget *stop_button;
+};
+
+G_END_DECLS
+
+#endif /* E_MAIL_PART_AUDIO_INLINE_H */
+
diff --git a/modules/audio-inline/evolution-module-audio-inline.c b/modules/audio-inline/evolution-module-audio-inline.c
new file mode 100644
index 0000000000..b5dffb183e
--- /dev/null
+++ b/modules/audio-inline/evolution-module-audio-inline.c
@@ -0,0 +1,54 @@
+/*
+ * evolution-module-audio-inline.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-formatter-audio-inline.h"
+#include "e-mail-parser-audio-inline.h"
+
+#include <gmodule.h>
+
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+const gchar * g_module_check_init (GModule *module);
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+ /* Register dynamically loaded types. */
+
+ e_mail_parser_audio_inline_type_register (type_module);
+ e_mail_formatter_audio_inline_type_register (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
+
+G_MODULE_EXPORT const gchar *
+g_module_check_init (GModule *module)
+{
+ /* FIXME Until mail is split into a module library and a
+ * reusable shared library, prevent the module from
+ * being unloaded. Unloading the module resets all
+ * static variables, which screws up foo_get_type()
+ * functions among other things. */
+ g_module_make_resident (module);
+
+ return NULL;
+}
+