[mistelix] Get rid of MistelixLib and introduce Backend.GStreamer. Better separation of libmistelix



commit e49e13ffd1d1c886a20bd0a2ac492c9a90400561
Author: Jordi Mas <jmas softcatala org>
Date:   Sun Jul 26 15:25:44 2009 +0200

    Get rid of MistelixLib and introduce Backend.GStreamer. Better separation of libmistelix

 libmistelix/Makefile.am              |    5 +-
 libmistelix/mistelix.c               |  670 +---------------------------------
 libmistelix/mistelix.h               |   26 +-
 libmistelix/plugins.c                |  111 ++++++
 libmistelix/slideshow.c              |  551 ++++++++++++++++++++++++++++
 libmistelix/typefind.c               |   92 +++++
 libmistelix/video.c                  |  109 +++---
 po/POTFILES.in                       |    2 +-
 src/Backends/GStreamer/Plugins.cs    |   69 ++++
 src/Backends/GStreamer/SlideShow.cs  |  125 +++++++
 src/Backends/GStreamer/Thumbnail.cs  |   58 +++
 src/Backends/GStreamer/Video.cs      |  123 +++++++
 src/Backends/OS/Unix.cs              |   93 +++++
 src/Core/Dependencies.cs             |    3 +-
 src/Core/DvdProjectBuilder.cs        |    5 +-
 src/Core/MistelixLib.cs              |  260 -------------
 src/Core/Preferences.cs              |   45 +---
 src/Core/SlideShow.cs                |   14 +-
 src/Core/Video.cs                    |    5 +-
 src/DataModel/VideoProjectElement.cs |    5 +-
 src/Makefile.am                      |    8 +-
 src/Widgets/VideosFileView.cs        |    6 +-
 22 files changed, 1330 insertions(+), 1055 deletions(-)
---
diff --git a/libmistelix/Makefile.am b/libmistelix/Makefile.am
index 628e5c9..2dae415 100644
--- a/libmistelix/Makefile.am
+++ b/libmistelix/Makefile.am
@@ -10,7 +10,10 @@ dolib_LTLIBRARIES = libmistelix.la
 libmistelix_la_SOURCES =		\
 	mistelix.c	\
 	thumbnail.c	\
-	video.c
+	video.c		\
+	slideshow.c	\
+	plugins.c	\
+	typefind.c
 
 noinst_HEADERS =  \
 	mistelix.h
diff --git a/libmistelix/mistelix.c b/libmistelix/mistelix.c
index 7190efc..6b9a2cd 100644
--- a/libmistelix/mistelix.c
+++ b/libmistelix/mistelix.c
@@ -21,217 +21,21 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#include <stdio.h>
-#include <netdb.h>
 #include <unistd.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <gst/gst.h>
 #include <sys/wait.h>
 
 #include "mistelix.h"
 
+static gboolean gstreamer_init = 0;
 
-typedef struct 
-{	
-	gchar filename [1024];
-	unsigned int weight;
-	unsigned int height;
-	unsigned int frames_sec;
-	unsigned int total_frames;
-	unsigned int type;
-} ThreadParams;
-
-typedef enum 
-{
-	None	 	= 0,
-	InitParams	= 1, 	/* Length (4 bytes) + pixels */
-	NewImage	= 2,	/* Length (4 bytes) seconds  */
-	FixedImage	= 3,	/* Length (4 bytes) + nframes + pixels */
-	End		= 4
-} Command;
-
-
-const gchar* address = "localhost";
-const int port = 2048;
-static int mis_socket;
-ThreadParams params;
-char audio[1024];
-int started;
-GThread* thread;
-gboolean gstreamer_init = 0;
-
-// It is assumed that there is only one client using the library at the time
-// There are no handles for session, just the active session
-
-void
-mistelix_slideshow_createstream (const gchar* filename, unsigned int type, unsigned int weight, unsigned int height, unsigned int frames_sec, unsigned int total_frames)
-{
-#ifdef _DEBUG
-	printf ("*** mistelix_slideshow_createstream: %s, %u, %u, %u, %u\n", filename, type, weight, height, frames_sec);
-#endif
-	thread =  NULL;
-	started = 0;
-	*audio = '\x0';
-	strcpy ((char*) params.filename,filename);
-	params.weight = weight;
-	params.height = height;
-	params.frames_sec = frames_sec;
-	params.total_frames = total_frames;
-	params.type = type;
-}
-
-void
-mistelix_slideshow_add_image (unsigned char* bytes, unsigned int len)
-{
-	unsigned char header[6];
-	unsigned char* pos = (unsigned char*) &len;
-	int i;
-#ifdef _DEBUG
-	printf ("*** mistelix_slideshow_add_image %x\n", len);
-#endif
-	mistelix_check_started ();
-
-	// Command
-	header[0] = 0xff;
-	header[1] = NewImage;
-
-	// Len
-	for (i = 0; i < sizeof (unsigned int); i++) {
-		header[2 + i] = *pos;
-		pos++;
-	}
-
-	mistelix_socket_send (header, 6);
-	mistelix_socket_send (bytes, len);
-}
-
-void
-mistelix_slideshow_add_imagefixed (unsigned char* bytes, unsigned int len, unsigned int frames)
-{
-	unsigned char header[10]; // 2 bytes header, 4 length buffer, 4 number of frames
-	unsigned char* pos = (unsigned char*) &len;
-	int i;
-#ifdef _DEBUG
-	printf ("*** mistelix_slideshow_add_image_fixed %x %u\n", len, frames);
-#endif
-	mistelix_check_started ();
-
-	// Command
-	header[0] = 0xff;
-	header[1] = FixedImage;
-
-	// Len
-	for (i = 0; i < sizeof (unsigned int); i++) {	
-		header[2 + i] = *pos;
-		pos++;
-	}
-
-	// Frames
-	pos = (unsigned char*) &frames;
-	for (i = 0; i < sizeof (unsigned int); i++) {
-		header[6 + i] = *pos;
-		pos++;
-	}
-
-	mistelix_socket_send (header, 10);
-	mistelix_socket_send (bytes, len);
-}
-
-
-void
-mistelix_slideshow_close ()
-{
-	// Wait until the pipe line completes
-	g_thread_join (thread);
-}
-
-
-void
-mistelix_slideshow_add_audio (const gchar* filename)
-{
-	strcpy (audio, filename);
-}
-
-unsigned int
-mistelix_get_codecs_count ()
-{
-	GList *plugins, *plugins_org, *features;
-	GstPluginFeature *feature;
-	GstPlugin *plugin;
-	unsigned int count = 0;
-	gboolean was_init;
-
-	was_init = gstreamer_init;
-	mistelix_check_init ();
-
-#ifdef _GSTREAMER_BUG 
-	/*  This code can be enabled when gst-ffmpeg bug fix http://bugzilla.gnome.org/show_bug.cgi?id=584291
-	    becomes widely available */
-
-	if (was_init)
-		gst_update_registry (); /* Detect new plugins added since we started GStreamer */
-#endif
-
-	plugins_org = plugins = gst_default_registry_get_plugin_list ();
-
-	while (plugins) {
-		plugin = (GstPlugin *) (plugins->data);
-		count++;
-		features = gst_registry_get_feature_list_by_plugin (gst_registry_get_default (), plugin->desc.name);
-		while (features) {
-			feature = GST_PLUGIN_FEATURE (features->data);
-			if (GST_IS_ELEMENT_FACTORY (feature))
-				count++;
-	
-			features = g_list_next (features);
-		}
-		gst_plugin_list_free (features);
-		plugins = g_list_next (plugins);
-	}
-	gst_plugin_list_free (plugins_org);
-	return count;
-}
-
-// TODO: These are not really codec are plug-ins
 void
-mistelix_get_codecs (char *codecs[])
+mistelix_check_init ()
 {
-	GList *plugins, *features;
-	GstPlugin *plugin;
-	GstPluginFeature *feature;
-	const char *name;
-	int cnt = 0;
-
-	mistelix_check_init ();
-	plugins = gst_default_registry_get_plugin_list ();
-
-	while (plugins) {
-		plugin = (GstPlugin *) (plugins->data);
-		codecs[cnt] = malloc (strlen (plugin->desc.name) + 1);
-		strcpy (codecs[cnt], plugin->desc.name);
-		cnt++;
-
-		features = gst_registry_get_feature_list_by_plugin (gst_registry_get_default (), plugin->desc.name);
-
-		while (features) {
-			feature = GST_PLUGIN_FEATURE (features->data);
-			name = gst_plugin_feature_get_name (feature);
-							
-			if (GST_IS_ELEMENT_FACTORY (feature)) {
-				codecs[cnt] = malloc (strlen (name) + 1);
-				strcpy (codecs[cnt], name);
-				cnt++;
-			}
+	if (gstreamer_init == TRUE)
+		return;
 
-			features = g_list_next (features);
-		}
-		gst_plugin_list_free (features);
-		plugins = g_list_next (plugins);
-	}
-	gst_plugin_list_free (plugins);
+	gst_init (NULL, NULL);
+	gstreamer_init = TRUE;
 }
 
 //
@@ -305,465 +109,3 @@ void mistelix_launchtool (const char* app, const char* args, const char* in_file
 	execvp (app, parmList);
 }
 
-void
-mistelix_check_init ()
-{
-	if (gstreamer_init == TRUE)
-		return;
-
-	gst_init (NULL, NULL);
-	gstreamer_init = TRUE;
-}
-
-/*
-	Do not want to start the thread until is necessary
-	to allow for example to add an audio channel before launching it
-*/
-void
-mistelix_check_started ()
-{
-	if (started != 0)
-		return;
-
-	started = 1;
-
-	thread = g_thread_create (mistelix_launch_gstreamer, (gpointer) &params, TRUE, NULL);
-	// TODO: To be replaced by socket timeout
-	sleep (2);
-	mistelix_socket_connect ();
-}
-
-/*
-	Sends a seek event to a pad
-*/
-void
-send_seek_event (GstElement* pipeline, GstPad* pad, gboolean flush)
-{
-	gboolean res = FALSE;
-	GstEvent *event;
-	GstSeekFlags flags;
-
-	flags = GST_SEEK_FLAG_SEGMENT;
-
-	if (flush)
-		flags |= GST_SEEK_FLAG_FLUSH;
-
-	/* Seek from the begining */
-	event = gst_event_new_seek (1, GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1);
-	res = gst_pad_send_event (pad, event);
-	if (res)
-		gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, SEEK_TIMEOUT);
-	else 
-		printf ("send_seek_event: error sending seek event\n");
-}
-
-/*
-	Monitor the EOS event for the sink pad
-	and resend it to the pipeline to finish it
-*/
-static gboolean
-gst_handle_sink_event (GstPad * pad, GstEvent * event)
-{
-	GstElement* element = (GstElement *) gst_object_get_parent (GST_OBJECT (pad));
-
-#ifdef _DEBUG
-	printf ("--->* gst_handle_sink_event %s %s -> %s (%u)\n", 
-		 gst_element_get_name (element),
-		 gst_element_get_name (pad),
-		 gst_event_type_get_name (event->type),
-		 event->type);
-#endif
-	if (event->type == GST_EVENT_EOS) {
-		GstElement* pipe = (GstElement *) gst_object_get_parent (GST_OBJECT (element));
-		GstBus *bus = gst_element_get_bus (pipe);
-		gst_bus_post (bus, gst_message_new_eos (GST_OBJECT (pipe)));
-#ifdef _DEBUG
-		printf ("Posted EOS\n");
-#endif
-	}
-	return gst_pad_event_default (pad, event);
-}
-
-#ifdef _DEBUG
-
-/*
-	Lists all the elements in a pipeline
-*/
-void
-listelements (GstBin* bin)
-{
-	gpointer point, point_pad;
-	GstIterator *it, *it_pads;
-
-	it = gst_bin_iterate_elements (bin);
-
-	printf ("----\n");
-	while (gst_iterator_next (it, &point) == GST_ITERATOR_OK) {
-		GstElement* element = GST_ELEMENT (point);
-
-		it_pads = gst_element_iterate_pads (element);
-		printf ("element -> %s\n", gst_element_get_name (element));
-
-		while (gst_iterator_next (it_pads, &point_pad) == GST_ITERATOR_OK) {
-			GstPad * pad = GST_PAD (point_pad);
-			printf ("pad-> %s\n", gst_element_get_name (pad));
-		}
-	}
-	printf ("----\n");
-}
-#endif
-
-gboolean
-mistelix_is_codec (const char* name)
-{
-	int ncodecs, i;
-	gboolean found = FALSE;
-
-	ncodecs = mistelix_get_codecs_count ();
-
-	char *codecs[ncodecs];
-	mistelix_get_codecs (codecs);
-
-	for (i = 0; i < ncodecs; i++ )
-	{
-		if (strcmp (name, codecs[i]) == 0) {
-			found = TRUE;
-			break;
-		}
-	}
-
-	for (i = 0; i < ncodecs; i++)
-		free (codecs [i]);
-
-#ifdef _DEBUG
-	printf ("Codec %s, found %d\n", name, found);
-#endif
-	return found;
-}
-
-/*
-	Get the element name within the pipeline
-	Caller is responsible for freezing the allocated memory
-*/
-char *
-mistelix_get_element_name_from_pipeline (GstBin* pipe, char* generic_name)
-{
-	char* result = NULL;
-	gpointer point;
-	GstIterator* it;
-	int len;
-
-	len = strlen (generic_name);
-	it = gst_bin_iterate_elements (pipe);
-
-	while (gst_iterator_next (it, &point) == GST_ITERATOR_OK) {
-		GstElement* element = GST_ELEMENT (point);
-		char* name;
-
-		name = gst_element_get_name (element);
-
-		if (strncmp (name, generic_name, len) == 0) {
-			result = malloc (strlen (name) + 1);
-			strcpy (result, name);
-			break;
-		}
-	}
-#ifdef _DEBUG	
-	printf ("Seached %s, found %s\n", generic_name, result);
-#endif
-	return result;
-}
-
-/* Method to launch gstreamer thread. Method signature as required by g_thread_create */
-gpointer 
-mistelix_launch_gstreamer  (gpointer data)
-{
-	char desc [1024];
-	GstElement* pipe, *element;
-	ThreadParams* params = (ThreadParams *) data;
-	gboolean has_audio;
-	GstBus *bus;
-	GstMessage *message;
-	GstStateChangeReturn ret;
-	GstPad* seekable_pad;
-	gpointer point_pad;
-	GstIterator *it_pads;
-	char* element_name;
-	int sink = 0;
-	gboolean vorbis;
-	char media [2048];
-
-	mistelix_check_init ();
-
-	has_audio = (*audio != '\x0');
-
-	if (has_audio) {
-		mistelix_detect_media (audio, media);
-
-		if (strcmp (media, "application/ogg") == 0) {
-			if (mistelix_is_codec ("vorbisdec"))
-				vorbis = TRUE;
-			else 
-				has_audio = FALSE;
-		} else {
-			if (strcmp (media, "application/x-id3") == 0) {
-				if (mistelix_is_codec ("flump3dec"))
-					vorbis = FALSE;
-				else 
-					has_audio = FALSE;
-			} else {
-				printf ("mistelix: unsupported audio format: %s\n", media);
-				has_audio = FALSE;
-			}
-		}
-	}
-
-	if (params->type == 0)  {/* Theora output format */
-		if (has_audio) {
-			if (vorbis) { /* Source audio in Vorbis */
-				sprintf (desc, 
-					"mistelixvideosrc num-buffers=%u ! video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=(fraction)%u/1 !"
-					"theoraenc ! mux. filesrc location=\"%s\" ! oggdemux ! vorbisdec ! audioconvert ! vorbisenc ! "
-					"oggmux name=mux ! filesink location=\"%s\"",
-					params->total_frames, params->weight, params->height, params->frames_sec, audio, params->filename);
-			} else { /* Source audio in MP3 */
-				sprintf (desc, 
-					"mistelixvideosrc num-buffers=%u ! video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=(fraction)%u/1 !"
-					"theoraenc ! mux. filesrc location=\"%s\" ! flump3dec ! audioconvert ! vorbisenc ! "
-					"oggmux name=mux ! filesink location=\"%s\"",
-					params->total_frames, params->weight, params->height, params->frames_sec, audio, params->filename);
-			}
-		} else {
-			sprintf (desc, 
-				"mistelixvideosrc num-buffers=%u ! video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=(fraction)%u/1 !"
-				"theoraenc ! oggmux !filesink location=\"%s\"", 
-				params->total_frames, params->weight, params->height, params->frames_sec, params->filename);
-		}
-	}	
-	else { /* DVD output format */
-
-		/*
-		 * ffenc_mpeg2video
-		 *    We use 'bitrate'element to set the quality of the generated MPEG2 video. 
-		 *    Every additional 10000 bits/s represent approximately 10% additional time 
-		 *    to generate the video
-		 *
-		 * ffmux_dvd
-		 *    We use maxdelay and preload to generate MPEG2 compatible streams with DVD
-		*/
-		
-		/* No audio support for now */
-		sprintf (desc, 
-			"mistelixvideosrc num-buffers=%u ! video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=(fraction)%u/1 !"
-			"ffenc_mpeg2video bitrate=500000 ! ffmux_dvd preload=500000 maxdelay=699999 !filesink location=\"%s\"", 
-			params->total_frames, params->weight, params->height, params->frames_sec, params->filename);
-	}	
-#ifdef _DEBUG
-	printf ("mistelix_launch_gstreamer: %s\n", desc);
-#endif
-	pipe = gst_parse_launch (desc, NULL);
-
-	/* Launch pipeline */
-
-#ifdef _DEBUG
-	listelements (GST_BIN (pipe));
-	printf ("*** run_pipeline start\n");
-#endif
-
-	g_assert (pipe);
-	bus = gst_element_get_bus (pipe);
-	g_assert (bus);
-
-	gst_element_set_state (pipe, GST_STATE_PLAYING);
-
-	/* Wait for status change */
-	gst_element_get_state (pipe, NULL, NULL, SEEK_TIMEOUT);
-
-	if (has_audio) {
-
-		/* Find the pad of the audio decoder to send the audio seek events */
-		if (vorbis)
-			element_name = mistelix_get_element_name_from_pipeline (GST_BIN (pipe), "vorbisdec");
-		else
-			element_name = mistelix_get_element_name_from_pipeline (GST_BIN (pipe), "flump3dec");
-
-		g_assert (element_name);
-		element = gst_bin_get_by_name (GST_BIN (pipe), element_name);
-		free (element_name);
-
-		g_assert (element);
-		seekable_pad = gst_element_get_pad (element, "src");
-		g_assert (seekable_pad);
-
-		/* Find the muxer's sink's and set callback function  */
-		element = gst_bin_get_by_name (GST_BIN (pipe), "mux");
-		g_assert (element);
-
-		it_pads = gst_element_iterate_pads (element);
-		while (gst_iterator_next (it_pads, &point_pad) == GST_ITERATOR_OK) {
-			GstPad * pad = GST_PAD (point_pad);
-	
-			if (strncmp (gst_element_get_name (pad), "src", 3) == 0)
-				continue;
-
-			sink++;
-			if (sink < 2)
-				continue;
-
-			/* The second sink is the video sink */
-	#ifdef _DEBUG
-			printf ("Setting handler for %s\n", gst_element_get_name (pad));
-	#endif
-			gst_pad_set_event_function (pad, gst_handle_sink_event);
-			break;
-		}
-
-		send_seek_event (pipe, seekable_pad, FALSE);
-	}
-	/* We get a GST_MESSAGE_EOS when the pipe is finished */
-	while (1) {
-		GstMessageType revent;
-
-		message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
-
-		if (message) {
-			revent = GST_MESSAGE_TYPE (message);
-#ifdef _DEBUG
-			printf ("*** run_pipeline message: %s (%x)\n", gst_message_type_get_name (revent), revent);
-#endif
-			gst_message_unref (message);
-		} else
-			revent = GST_MESSAGE_UNKNOWN;
-
-		if (revent == GST_MESSAGE_SEGMENT_DONE) {
-			/* Send audio segment again */
-			send_seek_event (pipe, seekable_pad, TRUE);
-			continue;
-		}
-
-		if (revent == GST_MESSAGE_ERROR) {
-#ifdef _DEBUG
-			printf ("*** run_pipeline exiting reason GST_MESSAGE_ERROR\n");
-#endif
-			break;
-		}
-
-		if (revent == GST_MESSAGE_EOS) {
-#ifdef _DEBUG
-			printf ("*** run_pipeline exiting reason: GST_MESSAGE_EOS\n");
-#endif
-			break;
-		}
-	}
-	
-	/* Need to explicitly set elements to the NULL state before dropping the final reference */
-	gst_element_set_state (pipe, GST_STATE_NULL);
-	gst_element_get_state (pipe, NULL, NULL, SEEK_TIMEOUT);
-	gst_object_unref (pipe);
-	gst_object_unref (bus);
-
-#ifdef _DEBUG
-	printf ("*** run_pipeline end\n");
-#endif
-	return NULL;
-}
-
-void 
-mistelix_socket_connect ()
-{
-	struct sockaddr_in serveraddr;
-	int yes = 1;
-#ifdef _DEBUG
-	printf ("*** mistelix_socket_connect %s %u\n", address, port);
-#endif
-	if ((mis_socket = socket (AF_INET, SOCK_STREAM, 0)) == -1)
-		return;
-
-	if (setsockopt (mis_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
-	{
-		close (mis_socket);
-		return;
-	}
-
-	serveraddr.sin_family = AF_INET;
-	serveraddr.sin_addr.s_addr = INADDR_ANY;
-	serveraddr.sin_port = htons (port);
-	memset (&(serveraddr.sin_zero), '\0', 8);
-
-	if (connect (mis_socket,(struct sockaddr *)&serveraddr,sizeof (serveraddr)) < 0)
-	{
-		printf ("*** mistelix_socket_connect error. It may be caused because not all the assumed pipe elements are present\n");
-		return;
-	}
-
-	printf ("*** mistelix_socket_connect %d\n", mis_socket);
-}
-
-void 
-mistelix_socket_send (unsigned char* data, unsigned int bytes)
-{
-	write (mis_socket, data, bytes);
-}
-
-
-/*
-	Runs standard pipline that ends by an EOS event
-*/	
-void
-run_pipeline (GstElement * pipe)
-{
-	GstBus *bus;
-	GstMessage *message;
-	GstMessageType revent;
-	GstStateChangeReturn ret;
-
-#ifdef _DEBUG
-	printf ("*** run_pipeline start\n");
-#endif
-	g_assert (pipe);
-	bus = gst_element_get_bus (pipe);
-	g_assert (bus);
-
-	gst_element_set_state (pipe, GST_STATE_PLAYING);
-
-	/* Wait for status change */
-	gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
-
-	/* We get a GST_MESSAGE_EOS when the pipe is finished */
-	while (1) {
-		message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
-
-		if (message) {
-			revent = GST_MESSAGE_TYPE (message);
-#ifdef _DEBUG
-			printf ("*** run_pipeline message: %s (%x)\n", gst_message_type_get_name (revent), revent);
-#endif
-			gst_message_unref (message);
-		} else
-			revent = GST_MESSAGE_UNKNOWN;
-
-		if (revent == GST_MESSAGE_ERROR) {
-#ifdef _DEBUG
-			printf ("*** run_pipeline exiting reason GST_MESSAGE_ERROR\n");
-#endif
-			break;
-		}
-
-		if (revent == GST_MESSAGE_EOS) {
-#ifdef _DEBUG
-			printf ("*** run_pipeline exiting reason: GST_MESSAGE_EOS\n");
-#endif
-			break;
-		}
-	}
-
-	gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
-	//gst_object_unref (pipe);
-
-	gst_bus_set_flushing (bus, TRUE);
-	//gst_object_unref (bus);
-#ifdef _DEBUG
-	printf ("*** run_pipeline end\n");
-#endif
-}
-
diff --git a/libmistelix/mistelix.h b/libmistelix/mistelix.h
index f952439..7397296 100644
--- a/libmistelix/mistelix.h
+++ b/libmistelix/mistelix.h
@@ -34,6 +34,7 @@
 #include <gst/check/gstcheck.h>
 
 /* Public API */
+
 void mistelix_slideshow_createstream (const gchar* filename, unsigned int type, unsigned int weight, unsigned int height, unsigned int framessec, unsigned int total_frames);
 
 void mistelix_slideshow_add_image (unsigned char* bytes, unsigned int len);
@@ -46,34 +47,23 @@ void mistelix_slideshow_close ();
 
 void mistelix_launchtool (const char* app, const char* args, const char* in, const char* out, const char* err);
 
-int mistelix_convert_media (const char* filein, const char* fileout, unsigned int frames_sec);
-
-void mistelix_video_screenshot (const char* filein, void** image);
-
-unsigned int mistelix_get_codecs_count ();
+int mistelix_video_convert (const char* filein, const char* fileout, unsigned int frames_sec);
 
-void mistelix_get_codecs (char *codecs[]);
+int mistelix_video_supported (const char* file, char* msg);
 
+void mistelix_video_screenshot (const char* filein, void** image);
 
-/* Private (not exposed) */
+unsigned int mistelix_get_plugins_count ();
 
-char * mistelix_get_element_name_from_pipeline (GstBin* pipe, char* generic_name);
+void mistelix_get_plugins (char *plugins[]);
 
-void mistelix_detect_media (const char* file, char* media);
-
-static void cb_typefound (GstElement *typefind, guint probability, GstCaps *caps, gpointer data);
+/* Private (not exposed) but shared within the library */
 
 void mistelix_check_init ();
 
 void mistelix_check_started ();
 
-void run_pipeline (GstElement * pipe);
-
-gpointer mistelix_launch_gstreamer  (gpointer data);
-
-void mistelix_socket_connect ();
-
-void mistelix_socket_send (unsigned char *data, unsigned int bytes);
+void mistelix_detect_media (const char* file, char* media);
 
 
 
diff --git a/libmistelix/plugins.c b/libmistelix/plugins.c
new file mode 100644
index 0000000..005c845
--- /dev/null
+++ b/libmistelix/plugins.c
@@ -0,0 +1,111 @@
+//
+// Copyright (C) 2008-2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "mistelix.h"
+
+extern gboolean gstreamer_init;
+
+unsigned int
+mistelix_get_plugins_count ()
+{
+	GList *plugins, *plugins_org, *features;
+	GstPluginFeature *feature;
+	GstPlugin *plugin;
+	unsigned int count = 0;
+	gboolean was_init;
+
+	was_init = gstreamer_init;
+	mistelix_check_init ();
+
+#ifdef _GSTREAMER_BUG 
+	/*  This code can be enabled when gst-ffmpeg bug fix http://bugzilla.gnome.org/show_bug.cgi?id=584291
+	    becomes widely available */
+
+	if (was_init)
+		gst_update_registry (); /* Detect new plugins added since we started GStreamer */
+#endif
+
+	plugins_org = plugins = gst_default_registry_get_plugin_list ();
+
+	while (plugins) {
+		plugin = (GstPlugin *) (plugins->data);
+		count++;
+		features = gst_registry_get_feature_list_by_plugin (gst_registry_get_default (), plugin->desc.name);
+		while (features) {
+			feature = GST_PLUGIN_FEATURE (features->data);
+			if (GST_IS_ELEMENT_FACTORY (feature))
+				count++;
+	
+			features = g_list_next (features);
+		}
+		gst_plugin_list_free (features);
+		plugins = g_list_next (plugins);
+	}
+	gst_plugin_list_free (plugins_org);
+	return count;
+}
+
+// TODO: These are not really codec are plug-ins
+void
+mistelix_get_plugins (char *plugins[])
+{
+	GList *plugins_list, *features;
+	GstPlugin *plugin;
+	GstPluginFeature *feature;
+	const char *name;
+	int cnt = 0;
+
+	mistelix_check_init ();
+	plugins_list = gst_default_registry_get_plugin_list ();
+
+	while (plugins_list) {
+		plugin = (GstPlugin *) (plugins_list->data);
+		plugins[cnt] = malloc (strlen (plugin->desc.name) + 1);
+		strcpy (plugins[cnt], plugin->desc.name);
+		cnt++;
+
+		features = gst_registry_get_feature_list_by_plugin (gst_registry_get_default (), plugin->desc.name);
+
+		while (features) {
+			feature = GST_PLUGIN_FEATURE (features->data);
+			name = gst_plugin_feature_get_name (feature);
+							
+			if (GST_IS_ELEMENT_FACTORY (feature)) {
+				plugins[cnt] = malloc (strlen (name) + 1);
+				strcpy (plugins[cnt], name);
+				cnt++;
+			}
+
+			features = g_list_next (features);
+		}
+		gst_plugin_list_free (features);
+		plugins_list = g_list_next (plugins_list);
+	}
+	gst_plugin_list_free (plugins_list);
+}
+
+
diff --git a/libmistelix/slideshow.c b/libmistelix/slideshow.c
new file mode 100644
index 0000000..c11a33f
--- /dev/null
+++ b/libmistelix/slideshow.c
@@ -0,0 +1,551 @@
+//
+// Copyright (C) 2008-2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+
+#include "mistelix.h"
+
+
+typedef struct 
+{	
+	gchar filename [1024];
+	unsigned int weight;
+	unsigned int height;
+	unsigned int frames_sec;
+	unsigned int total_frames;
+	unsigned int type;
+} ThreadParams;
+
+typedef enum 
+{
+	None	 	= 0,
+	InitParams	= 1, 	/* Length (4 bytes) + pixels */
+	NewImage	= 2,	/* Length (4 bytes) seconds  */
+	FixedImage	= 3,	/* Length (4 bytes) + nframes + pixels */
+	End		= 4
+} Command;
+
+void mistelix_socket_send (unsigned char* data, unsigned int bytes);
+void mistelix_socket_connect ();
+gpointer mistelix_launch_gstreamer (gpointer data);
+
+const gchar* address = "localhost";
+const int port = 2048;
+static int mis_socket;
+ThreadParams params;
+char audio[1024];
+GThread* thread;
+int started;
+
+// It is assumed that there is only one client using the library at the time
+// There are no handles for session, just the active session
+
+void
+mistelix_slideshow_createstream (const gchar* filename, unsigned int type, unsigned int weight, unsigned int height, unsigned int frames_sec, unsigned int total_frames)
+{
+#ifdef _DEBUG
+	printf ("*** mistelix_slideshow_createstream: %s, %u, %u, %u, %u\n", filename, type, weight, height, frames_sec);
+#endif
+	thread =  NULL;
+	started = 0;
+	*audio = '\x0';
+	strcpy ((char*) params.filename,filename);
+	params.weight = weight;
+	params.height = height;
+	params.frames_sec = frames_sec;
+	params.total_frames = total_frames;
+	params.type = type;
+}
+
+void
+mistelix_slideshow_add_image (unsigned char* bytes, unsigned int len)
+{
+	unsigned char header[6];
+	unsigned char* pos = (unsigned char*) &len;
+	int i;
+#ifdef _DEBUG
+	printf ("*** mistelix_slideshow_add_image %x\n", len);
+#endif
+	mistelix_check_started ();
+
+	// Command
+	header[0] = 0xff;
+	header[1] = NewImage;
+
+	// Len
+	for (i = 0; i < sizeof (unsigned int); i++) {
+		header[2 + i] = *pos;
+		pos++;
+	}
+
+	mistelix_socket_send (header, 6);
+	mistelix_socket_send (bytes, len);
+}
+
+void
+mistelix_slideshow_add_imagefixed (unsigned char* bytes, unsigned int len, unsigned int frames)
+{
+	unsigned char header[10]; // 2 bytes header, 4 length buffer, 4 number of frames
+	unsigned char* pos = (unsigned char*) &len;
+	int i;
+#ifdef _DEBUG
+	printf ("*** mistelix_slideshow_add_image_fixed %x %u\n", len, frames);
+#endif
+	mistelix_check_started ();
+
+	// Command
+	header[0] = 0xff;
+	header[1] = FixedImage;
+
+	// Len
+	for (i = 0; i < sizeof (unsigned int); i++) {	
+		header[2 + i] = *pos;
+		pos++;
+	}
+
+	// Frames
+	pos = (unsigned char*) &frames;
+	for (i = 0; i < sizeof (unsigned int); i++) {
+		header[6 + i] = *pos;
+		pos++;
+	}
+
+	mistelix_socket_send (header, 10);
+	mistelix_socket_send (bytes, len);
+}
+
+
+void
+mistelix_slideshow_close ()
+{
+	// Wait until the pipe line completes
+	g_thread_join (thread);
+}
+
+
+void
+mistelix_slideshow_add_audio (const gchar* filename)
+{
+	strcpy (audio, filename);
+
+/*
+	Private functions
+*/
+
+}
+/* Sends a seek event to a pad */
+void
+send_seek_event (GstElement* pipeline, GstPad* pad, gboolean flush)
+{
+	gboolean res = FALSE;
+	GstEvent *event;
+	GstSeekFlags flags;
+
+	flags = GST_SEEK_FLAG_SEGMENT;
+
+	if (flush)
+		flags |= GST_SEEK_FLAG_FLUSH;
+
+	/* Seek from the begining */
+	event = gst_event_new_seek (1, GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1);
+	res = gst_pad_send_event (pad, event);
+	if (res)
+		gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, SEEK_TIMEOUT);
+	else 
+		printf ("send_seek_event: error sending seek event\n");
+}
+
+/*
+	Monitor the EOS event for the sink pad
+	and resend it to the pipeline to finish it
+*/
+static gboolean
+gst_handle_sink_event (GstPad * pad, GstEvent * event)
+{
+	GstElement* element = (GstElement *) gst_object_get_parent (GST_OBJECT (pad));
+
+#ifdef _DEBUG
+	printf ("--->* gst_handle_sink_event %s %s -> %s (%u)\n", 
+		 gst_element_get_name (element),
+		 gst_element_get_name (pad),
+		 gst_event_type_get_name (event->type),
+		 event->type);
+#endif
+	if (event->type == GST_EVENT_EOS) {
+		GstElement* pipe = (GstElement *) gst_object_get_parent (GST_OBJECT (element));
+		GstBus *bus = gst_element_get_bus (pipe);
+		gst_bus_post (bus, gst_message_new_eos (GST_OBJECT (pipe)));
+#ifdef _DEBUG
+		printf ("Posted EOS\n");
+#endif
+	}
+	return gst_pad_event_default (pad, event);
+}
+
+
+/*
+	Do not want to start the thread until is necessary
+	to allow for example to add an audio channel before launching it
+*/
+void
+mistelix_check_started ()
+{
+	if (started != 0)
+		return;
+
+	started = 1;
+
+	thread = g_thread_create (mistelix_launch_gstreamer, (gpointer) &params, TRUE, NULL);
+	// TODO: To be replaced by socket timeout
+	sleep (2);
+	mistelix_socket_connect ();
+}
+
+
+#ifdef _DEBUG
+
+/*
+	Lists all the elements in a pipeline
+*/
+void
+listelements (GstBin* bin)
+{
+	gpointer point, point_pad;
+	GstIterator *it, *it_pads;
+
+	it = gst_bin_iterate_elements (bin);
+
+	printf ("----\n");
+	while (gst_iterator_next (it, &point) == GST_ITERATOR_OK) {
+		GstElement* element = GST_ELEMENT (point);
+
+		it_pads = gst_element_iterate_pads (element);
+		printf ("element -> %s\n", gst_element_get_name (element));
+
+		while (gst_iterator_next (it_pads, &point_pad) == GST_ITERATOR_OK) {
+			GstPad * pad = GST_PAD (point_pad);
+			printf ("pad-> %s\n", gst_element_get_name (pad));
+		}
+	}
+	printf ("----\n");
+}
+#endif
+
+gboolean
+mistelix_is_codec (const char* name)
+{
+	int ncodecs, i;
+	gboolean found = FALSE;
+
+	ncodecs = mistelix_get_plugins_count ();
+
+	char *plugins[ncodecs];
+	mistelix_get_plugins (plugins);
+
+	for (i = 0; i < ncodecs; i++ )
+	{
+		if (strcmp (name, plugins[i]) == 0) {
+			found = TRUE;
+			break;
+		}
+	}
+
+	for (i = 0; i < ncodecs; i++)
+		free (plugins [i]);
+
+#ifdef _DEBUG
+	printf ("Codec %s, found %d\n", name, found);
+#endif
+	return found;
+}
+
+/*
+	Get the element name within the pipeline
+	Caller is responsible for freezing the allocated memory
+*/
+char *
+mistelix_get_element_name_from_pipeline (GstBin* pipe, char* generic_name)
+{
+	char* result = NULL;
+	gpointer point;
+	GstIterator* it;
+	int len;
+
+	len = strlen (generic_name);
+	it = gst_bin_iterate_elements (pipe);
+
+	while (gst_iterator_next (it, &point) == GST_ITERATOR_OK) {
+		GstElement* element = GST_ELEMENT (point);
+		char* name;
+
+		name = gst_element_get_name (element);
+
+		if (strncmp (name, generic_name, len) == 0) {
+			result = malloc (strlen (name) + 1);
+			strcpy (result, name);
+			break;
+		}
+	}
+#ifdef _DEBUG	
+	printf ("Seached %s, found %s\n", generic_name, result);
+#endif
+	return result;
+}
+
+/* Method to launch gstreamer thread. Method signature as required by g_thread_create */
+gpointer 
+mistelix_launch_gstreamer (gpointer data)
+{
+	char desc [1024];
+	GstElement* pipe, *element;
+	ThreadParams* params = (ThreadParams *) data;
+	gboolean has_audio;
+	GstBus *bus;
+	GstMessage *message;
+	GstStateChangeReturn ret;
+	GstPad* seekable_pad;
+	gpointer point_pad;
+	GstIterator *it_pads;
+	char* element_name;
+	int sink = 0;
+	gboolean vorbis = FALSE;
+	char media [2048];
+
+	mistelix_check_init ();
+
+	has_audio = (*audio != '\x0');
+
+	if (has_audio) {
+		mistelix_detect_media (audio, media);
+
+		if (strcmp (media, "application/ogg") == 0) {
+			if (mistelix_is_codec ("vorbisdec"))
+				vorbis = TRUE;
+			else 
+				has_audio = FALSE;
+		} else {
+			if (strcmp (media, "application/x-id3") == 0) {
+				if (mistelix_is_codec ("flump3dec"))
+					vorbis = FALSE;
+				else 
+					has_audio = FALSE;
+			} else {
+				printf ("mistelix: unsupported audio format: %s\n", media);
+				has_audio = FALSE;
+			}
+		}
+	}
+
+	if (params->type == 0)  {/* Theora output format */
+		if (has_audio) {
+			if (vorbis) { /* Source audio in Vorbis */
+				sprintf (desc, 
+					"mistelixvideosrc num-buffers=%u ! video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=(fraction)%u/1 !"
+					"theoraenc ! mux. filesrc location=\"%s\" ! oggdemux ! vorbisdec ! audioconvert ! vorbisenc ! "
+					"oggmux name=mux ! filesink location=\"%s\"",
+					params->total_frames, params->weight, params->height, params->frames_sec, audio, params->filename);
+			} else { /* Source audio in MP3 */
+				sprintf (desc, 
+					"mistelixvideosrc num-buffers=%u ! video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=(fraction)%u/1 !"
+					"theoraenc ! mux. filesrc location=\"%s\" ! flump3dec ! audioconvert ! vorbisenc ! "
+					"oggmux name=mux ! filesink location=\"%s\"",
+					params->total_frames, params->weight, params->height, params->frames_sec, audio, params->filename);
+			}
+		} else {
+			sprintf (desc, 
+				"mistelixvideosrc num-buffers=%u ! video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=(fraction)%u/1 !"
+				"theoraenc ! oggmux !filesink location=\"%s\"", 
+				params->total_frames, params->weight, params->height, params->frames_sec, params->filename);
+		}
+	}	
+	else { /* DVD output format */
+
+		/*
+		 * ffenc_mpeg2video
+		 *    We use 'bitrate'element to set the quality of the generated MPEG2 video. 
+		 *    Every additional 10000 bits/s represent approximately 10% additional time 
+		 *    to generate the video
+		 *
+		 * ffmux_dvd
+		 *    We use maxdelay and preload to generate MPEG2 compatible streams with DVD
+		*/
+		
+		/* No audio support for now */
+		sprintf (desc, 
+			"mistelixvideosrc num-buffers=%u ! video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=(fraction)%u/1 !"
+			"ffenc_mpeg2video bitrate=500000 ! ffmux_dvd preload=500000 maxdelay=699999 !filesink location=\"%s\"", 
+			params->total_frames, params->weight, params->height, params->frames_sec, params->filename);
+	}	
+#ifdef _DEBUG
+	printf ("mistelix_launch_gstreamer: %s\n", desc);
+#endif
+	pipe = gst_parse_launch (desc, NULL);
+
+	/* Launch pipeline */
+
+#ifdef _DEBUG
+	listelements (GST_BIN (pipe));
+	printf ("*** run_pipeline start\n");
+#endif
+
+	g_assert (pipe);
+	bus = gst_element_get_bus (pipe);
+	g_assert (bus);
+
+	gst_element_set_state (pipe, GST_STATE_PLAYING);
+
+	/* Wait for status change */
+	gst_element_get_state (pipe, NULL, NULL, SEEK_TIMEOUT);
+
+	if (has_audio) {
+
+		/* Find the pad of the audio decoder to send the audio seek events */
+		if (vorbis)
+			element_name = mistelix_get_element_name_from_pipeline (GST_BIN (pipe), "vorbisdec");
+		else
+			element_name = mistelix_get_element_name_from_pipeline (GST_BIN (pipe), "flump3dec");
+
+		g_assert (element_name);
+		element = gst_bin_get_by_name (GST_BIN (pipe), element_name);
+		free (element_name);
+
+		g_assert (element);
+		seekable_pad = gst_element_get_pad (element, "src");
+		g_assert (seekable_pad);
+
+		/* Find the muxer's sink's and set callback function  */
+		element = gst_bin_get_by_name (GST_BIN (pipe), "mux");
+		g_assert (element);
+
+		it_pads = gst_element_iterate_pads (element);
+		while (gst_iterator_next (it_pads, &point_pad) == GST_ITERATOR_OK) {
+			GstPad * pad = GST_PAD (point_pad);
+	
+			if (strncmp (gst_element_get_name (pad), "src", 3) == 0)
+				continue;
+
+			sink++;
+			if (sink < 2)
+				continue;
+
+			/* The second sink is the video sink */
+	#ifdef _DEBUG
+			printf ("Setting handler for %s\n", gst_element_get_name (pad));
+	#endif
+			gst_pad_set_event_function (pad, gst_handle_sink_event);
+			break;
+		}
+
+		send_seek_event (pipe, seekable_pad, FALSE);
+	}
+	/* We get a GST_MESSAGE_EOS when the pipe is finished */
+	while (1) {
+		GstMessageType revent;
+
+		message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
+
+		if (message) {
+			revent = GST_MESSAGE_TYPE (message);
+#ifdef _DEBUG
+			printf ("*** run_pipeline message: %s (%x)\n", gst_message_type_get_name (revent), revent);
+#endif
+			gst_message_unref (message);
+		} else
+			revent = GST_MESSAGE_UNKNOWN;
+
+		if (revent == GST_MESSAGE_SEGMENT_DONE) {
+			/* Send audio segment again */
+			send_seek_event (pipe, seekable_pad, TRUE);
+			continue;
+		}
+
+		if (revent == GST_MESSAGE_ERROR) {
+#ifdef _DEBUG
+			printf ("*** run_pipeline exiting reason GST_MESSAGE_ERROR\n");
+#endif
+			break;
+		}
+
+		if (revent == GST_MESSAGE_EOS) {
+#ifdef _DEBUG
+			printf ("*** run_pipeline exiting reason: GST_MESSAGE_EOS\n");
+#endif
+			break;
+		}
+	}
+	
+	/* Need to explicitly set elements to the NULL state before dropping the final reference */
+	gst_element_set_state (pipe, GST_STATE_NULL);
+	gst_element_get_state (pipe, NULL, NULL, SEEK_TIMEOUT);
+	gst_object_unref (pipe);
+	gst_object_unref (bus);
+
+#ifdef _DEBUG
+	printf ("*** run_pipeline end\n");
+#endif
+	return NULL;
+}
+
+void 
+mistelix_socket_connect ()
+{
+	struct sockaddr_in serveraddr;
+	int yes = 1;
+#ifdef _DEBUG
+	printf ("*** mistelix_socket_connect %s %u\n", address, port);
+#endif
+	if ((mis_socket = socket (AF_INET, SOCK_STREAM, 0)) == -1)
+		return;
+
+	if (setsockopt (mis_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
+	{
+		close (mis_socket);
+		return;
+	}
+
+	serveraddr.sin_family = AF_INET;
+	serveraddr.sin_addr.s_addr = INADDR_ANY;
+	serveraddr.sin_port = htons (port);
+	memset (&(serveraddr.sin_zero), '\0', 8);
+
+	if (connect (mis_socket,(struct sockaddr *)&serveraddr,sizeof (serveraddr)) < 0)
+	{
+		printf ("*** mistelix_socket_connect error. It may be caused because not all the assumed pipe elements are present\n");
+		return;
+	}
+
+	printf ("*** mistelix_socket_connect %d\n", mis_socket);
+}
+
+void 
+mistelix_socket_send (unsigned char* data, unsigned int bytes)
+{
+	write (mis_socket, data, bytes);
+}
+
diff --git a/libmistelix/typefind.c b/libmistelix/typefind.c
new file mode 100644
index 0000000..6306084
--- /dev/null
+++ b/libmistelix/typefind.c
@@ -0,0 +1,92 @@
+//
+// Copyright (C) 2008-2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#include <stdio.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <gst/gst.h>
+#include <sys/wait.h>
+
+#include "mistelix.h"
+
+
+
+static void
+cb_typefound (GstElement *typefind,
+	      guint       probability,
+	      GstCaps    *caps,
+	      gpointer    data)
+{
+	gchar *type;
+	char* media_type = (char*) data;
+
+	type = gst_caps_to_string (caps);
+
+//#ifdef _DEBUG
+	printf ("Media type %s found, probability %d%%, %x\n", type, probability, (unsigned int) caps);
+//#endif
+	if (caps!= NULL && type != NULL)
+		strcpy (media_type, type);
+
+	g_free (type);
+}
+
+
+void
+mistelix_detect_media (const char* file, char* media)
+{
+	GstElement* pipe, *filesrc, *typefind, *fakesink;
+	GstBus *bus;
+	char media_type [2048];
+
+	mistelix_check_init ();
+
+	pipe = gst_pipeline_new ("pipe");
+	bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
+	gst_object_unref (bus);
+
+	// create file source and typefind element
+	filesrc = gst_element_factory_make ("filesrc", "source");
+	g_object_set (G_OBJECT (filesrc), "location", file, NULL);
+	typefind = gst_element_factory_make ("typefind", "typefinder");
+	g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), (gpointer) media_type);
+	fakesink = gst_element_factory_make ("fakesink", "sink");
+
+	gst_bin_add_many (GST_BIN (pipe), filesrc, typefind, fakesink, NULL);
+	gst_element_link_many (filesrc, typefind, fakesink, NULL);
+
+	gst_element_set_state (GST_ELEMENT (pipe), GST_STATE_PLAYING);
+	/* Wait for status change */
+	gst_element_get_state (pipe, NULL, NULL, SEEK_TIMEOUT);
+
+	gst_element_set_state (GST_ELEMENT (pipe), GST_STATE_NULL);
+	gst_object_unref (GST_OBJECT (pipe));
+	strcpy (media, media_type);
+
+	printf ("*** mistelix_detect_media result for %s is [%s]\n", file, media);
+}
+
diff --git a/libmistelix/video.c b/libmistelix/video.c
index 3ad3421..616f7e6 100644
--- a/libmistelix/video.c
+++ b/libmistelix/video.c
@@ -31,6 +31,8 @@ typedef struct
 	const char *pipeline;
 } supported_media;
 
+void run_pipeline (GstElement * pipe);
+
 supported_media supported_medias[] = 
 {
 	//
@@ -70,14 +72,14 @@ mistelix_video_extensions (char* extensions)
 }
 
 int 
-mistelix_media_supported (const char* file, char* msg)
+mistelix_video_supported (const char* file, char* msg)
 {
 	char media [2048];
 	int i, ncodecs, c, media_present, plugin_present;
 	char* pos;
 
 //#ifdef _DEBUG
-	printf ("*** mistelix_media_supported %s\n", file);
+	printf ("*** mistelix_video_supported %s\n", file);
 //#endif
 
 	mistelix_detect_media (file, media);
@@ -90,9 +92,9 @@ mistelix_media_supported (const char* file, char* msg)
 	if (*media == 0x0)
 		return 1; // Could not identify media
 
-	ncodecs = mistelix_get_codecs_count ();
+	ncodecs = mistelix_get_plugins_count ();
 	char *codecs[ncodecs];
-	mistelix_get_codecs (codecs);
+	mistelix_get_plugins (codecs);
 
 	media_present =  plugin_present = 0;
 	for (i = 0; i < sizeof (supported_medias) / sizeof (supported_media); i++)
@@ -129,7 +131,7 @@ mistelix_media_supported (const char* file, char* msg)
 }
 
 int
-mistelix_convert_media (const char* filein, const char* fileout, unsigned int frames_sec)
+mistelix_video_convert (const char* filein, const char* fileout, unsigned int frames_sec)
 {
 	char media [2048];
 	int i, ncodecs, c, media_present, plugin_present;
@@ -149,9 +151,9 @@ mistelix_convert_media (const char* filein, const char* fileout, unsigned int fr
 	if (*media == 0x0)
 		return 1; // Could not identify media
 
-	ncodecs = mistelix_get_codecs_count ();
+	ncodecs = mistelix_get_plugins_count ();
 	char *codecs[ncodecs];
-	mistelix_get_codecs (codecs);
+	mistelix_get_plugins (codecs);
 
 	media_present =  plugin_present = 0;
 	for (i = 0; i < sizeof (supported_medias) / sizeof (supported_media); i++)
@@ -192,62 +194,69 @@ mistelix_convert_media (const char* filein, const char* fileout, unsigned int fr
 }
 
 
-//
-// Private
-//
+/*
+ 	Private functions
+*/
+
 
+/*
+	Runs standard pipline that ends by an EOS event
+*/	
 void
-mistelix_detect_media (const char* file, char* media)
+run_pipeline (GstElement * pipe)
 {
-	GstElement* pipe, *filesrc, *typefind, *fakesink;
 	GstBus *bus;
-	char media_type [2048];
-
-	mistelix_check_init ();
-
-	pipe = gst_pipeline_new ("pipe");
-	bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
-	gst_object_unref (bus);
+	GstMessage *message;
+	GstMessageType revent;
+	GstStateChangeReturn ret;
 
-	// create file source and typefind element
-	filesrc = gst_element_factory_make ("filesrc", "source");
-	g_object_set (G_OBJECT (filesrc), "location", file, NULL);
-	typefind = gst_element_factory_make ("typefind", "typefinder");
-	g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), (gpointer) media_type);
-	fakesink = gst_element_factory_make ("fakesink", "sink");
+#ifdef _DEBUG
+	printf ("*** run_pipeline start\n");
+#endif
+	g_assert (pipe);
+	bus = gst_element_get_bus (pipe);
+	g_assert (bus);
 
-	gst_bin_add_many (GST_BIN (pipe), filesrc, typefind, fakesink, NULL);
-	gst_element_link_many (filesrc, typefind, fakesink, NULL);
+	gst_element_set_state (pipe, GST_STATE_PLAYING);
 
-	gst_element_set_state (GST_ELEMENT (pipe), GST_STATE_PLAYING);
 	/* Wait for status change */
-	gst_element_get_state (pipe, NULL, NULL, SEEK_TIMEOUT);
-
-	gst_element_set_state (GST_ELEMENT (pipe), GST_STATE_NULL);
-	gst_object_unref (GST_OBJECT (pipe));
-	strcpy (media, media_type);
+	gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
 
-	printf ("*** mistelix_detect_media result for %s is [%s]\n", file, media);
-}
+	/* We get a GST_MESSAGE_EOS when the pipe is finished */
+	while (1) {
+		message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
 
+		if (message) {
+			revent = GST_MESSAGE_TYPE (message);
+#ifdef _DEBUG
+			printf ("*** run_pipeline message: %s (%x)\n", gst_message_type_get_name (revent), revent);
+#endif
+			gst_message_unref (message);
+		} else
+			revent = GST_MESSAGE_UNKNOWN;
 
-static void
-cb_typefound (GstElement *typefind,
-	      guint       probability,
-	      GstCaps    *caps,
-	      gpointer    data)
-{
-	gchar *type;
-	char* media_type = (char*) data;
+		if (revent == GST_MESSAGE_ERROR) {
+#ifdef _DEBUG
+			printf ("*** run_pipeline exiting reason GST_MESSAGE_ERROR\n");
+#endif
+			break;
+		}
 
-	type = gst_caps_to_string (caps);
+		if (revent == GST_MESSAGE_EOS) {
+#ifdef _DEBUG
+			printf ("*** run_pipeline exiting reason: GST_MESSAGE_EOS\n");
+#endif
+			break;
+		}
+	}
 
-//#ifdef _DEBUG
-	printf ("Media type %s found, probability %d%%, %x\n", type, probability, (unsigned int) caps);
-//#endif
-	if (caps!= NULL && type != NULL)
-		strcpy (media_type, type);
+	gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+	//gst_object_unref (pipe);
 
-	g_free (type);
+	gst_bus_set_flushing (bus, TRUE);
+	//gst_object_unref (bus);
+#ifdef _DEBUG
+	printf ("*** run_pipeline end\n");
+#endif
 }
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8b3c65d..65395c9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,9 +10,9 @@ extensions/SlideTransitions/StarWipe/StarWipeFivePoint.cs
 extensions/SlideTransitions/StarWipe/StarWipeFourPoint.cs
 extensions/SlideTransitions/StarWipe/StarWipeSixPoint.cs
 mistelix.desktop.in
+src/Backends/GStreamer/Video.cs
 src/Core/Dependencies.cs
 src/Core/DvdProjectBuilder.cs
-src/Core/MistelixLib.cs
 src/Core/NoneTransition.cs
 src/Core/ResolutionManager.cs
 src/Core/SlideShowsProjectBuilder.cs
diff --git a/src/Backends/GStreamer/Plugins.cs b/src/Backends/GStreamer/Plugins.cs
new file mode 100644
index 0000000..04d0ffa
--- /dev/null
+++ b/src/Backends/GStreamer/Plugins.cs
@@ -0,0 +1,69 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+using Mistelix.Core;
+
+namespace Mistelix.Backends.GStreamer
+{
+	//
+	// GStreamer plugin enumeration functions
+	// 
+	public static class Plugins
+	{
+		[DllImport ("libmistelix")]
+		static extern uint mistelix_get_plugins_count ();
+
+		[DllImport ("libmistelix")]
+		static extern IntPtr mistelix_get_plugins (IntPtr [] plugins);
+		
+		static Plugins ()
+		{
+
+		}
+
+		static public List <string> GetList ()
+		{
+			uint count;
+			IntPtr[] list;
+			string codec;
+			List <string> codecs = new List <string> ();
+
+			count = mistelix_get_plugins_count ();
+			Logger.Debug ("Plugin.GetList. Gstreamer pluggins: {0}", count);
+			list = new IntPtr [count];
+			mistelix_get_plugins (list);
+
+			for (int i = 0; i < count; i++)
+			{
+				codec = Marshal.PtrToStringAuto (list[i]);
+				codecs.Add (codec);
+				Marshal.FreeHGlobal (list[i]);
+			}
+			return codecs;
+		}
+	}
+}
diff --git a/src/Backends/GStreamer/SlideShow.cs b/src/Backends/GStreamer/SlideShow.cs
new file mode 100644
index 0000000..2142dbe
--- /dev/null
+++ b/src/Backends/GStreamer/SlideShow.cs
@@ -0,0 +1,125 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+using Mistelix.DataModel;
+
+namespace Mistelix.Backends.GStreamer
+{
+	//
+	// GStreamer slideshow functions
+	// 
+	public static class SlideShow
+	{
+		[DllImport ("libmistelix")]
+		static extern int mistelix_slideshow_createstream (string filename, uint type, uint weight, uint height, uint framessec, uint totalframes);
+
+		[DllImport ("libmistelix")]
+		static extern int mistelix_slideshow_add_image (IntPtr bytes, uint len);
+
+		[DllImport ("libmistelix")]
+		static extern int mistelix_slideshow_add_imagefixed (IntPtr bytes, uint len, uint frames);
+
+		[DllImport ("libmistelix")]
+		static extern void mistelix_slideshow_add_audio (string filename);
+
+		[DllImport ("libmistelix")]
+		static extern void mistelix_slideshow_close ();
+
+		static SlideShow ()
+		{
+
+		}
+
+		static public int CreateStream (string filename, ProjectType type, uint weight, uint height, uint framessec, uint totalframes)
+		{
+			return mistelix_slideshow_createstream (filename, (uint) type, weight, height, framessec, totalframes);
+		}
+		
+		static public int AddImage (SlideImage image)
+		{
+			IntPtr pixels = IntPtr.Zero;
+			int rslt = -1;
+	
+			try
+			{
+				if (image.Channels != 3)
+					throw new InvalidOperationException (String.Format ("mistelixvideosrc expects images in 24 bits (3 channels) not {0}", image.Channels));
+
+				pixels = Marshal.AllocHGlobal (image.Pixels.Length);
+				Marshal.Copy (image.Pixels, 0, pixels, image.Pixels.Length);
+
+				rslt = mistelix_slideshow_add_image (pixels, (uint) image.Pixels.Length);
+				return rslt;
+			}
+
+			finally
+			{
+			 	Marshal.FreeHGlobal (pixels);
+			}
+		}
+
+		static public int AddImageFixed (SlideImage image, uint frames)
+		{
+			IntPtr pixels = IntPtr.Zero;
+			int rslt = -1;
+
+			try
+			{
+				if (image.Channels != 3)
+					throw new InvalidOperationException (String.Format ("mistelixvideosrc expects images in 24 bits (3 channels) not {0}", image.Channels));
+
+				pixels = Marshal.AllocHGlobal (image.Pixels.Length);
+				Marshal.Copy (image.Pixels, 0, pixels, image.Pixels.Length);
+	
+				rslt = mistelix_slideshow_add_imagefixed (pixels, (uint) image.Pixels.Length, frames);
+				return rslt;
+			}
+
+			finally
+			{
+			 	Marshal.FreeHGlobal (pixels);
+			}
+		}
+
+		static public void AddAudio (string file)
+		{
+			try
+			{
+				mistelix_slideshow_add_audio (file);
+			}
+
+			finally
+			{
+
+			}
+		}
+
+		static public void Close ()
+		{
+			mistelix_slideshow_close ();
+		}
+	}
+}
diff --git a/src/Backends/GStreamer/Thumbnail.cs b/src/Backends/GStreamer/Thumbnail.cs
new file mode 100644
index 0000000..8554a72
--- /dev/null
+++ b/src/Backends/GStreamer/Thumbnail.cs
@@ -0,0 +1,58 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.InteropServices;
+using Gdk;
+
+namespace Mistelix.Backends.GStreamer
+{
+	//
+	// GStreamer video thumbnailing functions
+	// 
+	public static class Thumbnail
+	{
+		[DllImport ("libmistelix")]	
+		static extern void mistelix_video_screenshot (string filein, out IntPtr pixbuf);
+	
+		
+		static Thumbnail ()
+		{
+
+		}
+
+		static public Gdk.Pixbuf VideoScreenshot (string file)
+		{
+			Gdk.Pixbuf thumbnail;
+			IntPtr pix;
+
+			mistelix_video_screenshot (file, out pix);
+
+			if (pix == IntPtr.Zero)
+				throw new InvalidOperationException ("No screenshot taken");
+
+			thumbnail = new Gdk.Pixbuf (pix);
+			return thumbnail;
+		}
+	}
+}
diff --git a/src/Backends/GStreamer/Video.cs b/src/Backends/GStreamer/Video.cs
new file mode 100644
index 0000000..4d33f04
--- /dev/null
+++ b/src/Backends/GStreamer/Video.cs
@@ -0,0 +1,123 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using Mono.Unix;
+
+using Mistelix.Core;
+
+namespace Mistelix.Backends.GStreamer
+{
+	//
+	// GStreamer video functions
+	// 
+	public static class Video
+	{	
+		[DllImport ("libmistelix")]	
+		static extern void mistelix_video_extensions (StringBuilder extensions);
+
+		[DllImport ("libmistelix")]
+		static extern int mistelix_video_supported (string file, StringBuilder media);
+
+		[DllImport ("libmistelix")]
+		static extern int mistelix_video_convert (string filein, string fileout, uint frames_sec);
+
+		static string [] extensions;
+		
+		static Video ()
+		{
+
+		}
+
+		static public string[] FileExtensions ()
+		{
+			if (extensions != null)
+				return extensions;
+
+			List <string> strs = new List <string> ();
+			string rslt;
+			int pos;
+			StringBuilder sb = new StringBuilder (1024);
+
+			mistelix_video_extensions (sb);
+			rslt = sb.ToString ();
+	
+			while (true) {
+				rslt = rslt.TrimStart ();
+				pos = rslt.IndexOf (";");
+				
+				if (pos == -1) {
+					if (rslt.Length > 0)
+						strs.Add (rslt);
+					break;
+				}
+
+				strs.Add (rslt.Substring (0, pos));
+				pos++;
+				rslt = rslt.Substring (pos);
+			}
+			extensions = strs.ToArray ();
+			return extensions;
+		}
+
+		static public bool IsSupported (string file, out string msg)
+		{
+			int r;
+			StringBuilder rslt = new StringBuilder (2048);
+
+			r = mistelix_video_supported (file, rslt);
+			Logger.Debug ("MistelixLib.IsMediaSupported. File {0} is {1}", file, r);
+
+			switch (r) {
+			case 0: // Format supported
+				msg = string.Empty;
+				return true;
+			case 1: // Could not identify media
+				msg = String.Format (Catalog.GetString ("Could not identify media type for file '{0}'"), file);
+				return false;
+			case 2: // Format not supported 
+				msg = String.Format (Catalog.GetString ("The file '{0}' is encoded in an unsupported format"), file);
+				return false;
+			case 3: // Supported media but codec not found + codec name
+				msg = String.Format (Catalog.GetString ("The file '{0}' is encoded in a recognised format. However, you are missing the GStreamer plug-in '{1}' to decode it."), file, rslt);
+				return false;
+			default:
+				throw new Exception ("Unexpected result");
+			}
+		}
+
+		static public bool Convert (string filein, string fileout, uint frames_sec)
+		{
+			int rslt = mistelix_video_convert (filein, fileout, frames_sec);
+
+			if (rslt == 0)
+				return true;
+			
+			return false;
+		}
+
+	}
+}
diff --git a/src/Backends/OS/Unix.cs b/src/Backends/OS/Unix.cs
new file mode 100644
index 0000000..41b1882
--- /dev/null
+++ b/src/Backends/OS/Unix.cs
@@ -0,0 +1,93 @@
+//
+// Copyright (C) 2008-2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+using Mistelix.DataModel;
+using Mistelix.Core;
+
+namespace Mistelix.Backends.OS
+{
+	//
+	// Unix specific functions
+	// 
+	public static class Unix
+	{
+		[DllImport ("libmistelix")]
+		static extern void mistelix_launchtool (string app, string args, string in_file, string out_file, string err_file);
+
+		static Unix ()
+		{
+
+		}
+
+		// There is no SpecialFolder support for videos. We have to read the xdg configuration directly
+		public static string GetDefaultVideoDirectory ()
+		{
+			string directory = null, line;
+			const string home = "$HOME/";
+			const string key = "XDG_VIDEOS_DIR";
+			string home_dir = Environment.GetEnvironmentVariable ("HOME");
+			string config_file;
+
+			try {
+				config_file = Path.Combine (home_dir, ".config/user-dirs.dirs");
+
+				using (StreamReader reader = new StreamReader (config_file))
+				{
+					while ((line = reader.ReadLine ()) != null) 
+					{
+						line = line.Trim ();
+						int pos = line.IndexOf ('=');
+				                if (pos > 8 && line.Substring (0, pos) == key) {
+							string path = line.Substring (pos + 1).Trim ('"');
+							bool relative = false;
+
+							if (path.StartsWith (home)) {
+								relative = true;
+								path = path.Substring (home.Length);
+							} else if (!path.StartsWith ("/"))
+								relative = true;
+
+			                    		directory = relative ? Path.Combine (home_dir, path) : path;
+							break;
+						}
+		                	}
+				}
+			}
+			catch (Exception) { }
+
+			if (directory == null)
+				return Environment.GetFolderPath (Environment.SpecialFolder.Personal);
+			else
+				return directory;
+		}
+
+		static public void LaunchTool (string app, string args, string in_file, string out_file, string err_file)
+		{
+			mistelix_launchtool (app, args, in_file, out_file, err_file);
+		}
+	}
+}
diff --git a/src/Core/Dependencies.cs b/src/Core/Dependencies.cs
index 0300b11..0e7c1d7 100644
--- a/src/Core/Dependencies.cs
+++ b/src/Core/Dependencies.cs
@@ -28,6 +28,7 @@ using System.Diagnostics;
 
 using Mistelix.Transitions;
 using Mistelix.DataModel;
+using Mistelix.Backends.GStreamer;
 
 namespace Mistelix.Core
 {
@@ -128,7 +129,7 @@ namespace Mistelix.Core
 				return;
 
 			status_checked = true;
-			List <string> codecs = MistelixLib.GetCodecs ();
+			List <string> codecs = Plugins.GetList ();
 			string [] used =  {"ffenc_mpeg2video", "ffmux_dvd", "mistelixvideosrc", "theoraenc", "oggmux", "vorbisdec", "flump3dec", "asfdemux"};
 			bool [] founds = new bool [used.Length];
 
diff --git a/src/Core/DvdProjectBuilder.cs b/src/Core/DvdProjectBuilder.cs
index ab57e9f..4981cad 100644
--- a/src/Core/DvdProjectBuilder.cs
+++ b/src/Core/DvdProjectBuilder.cs
@@ -32,6 +32,7 @@ using Mistelix.Widgets;
 using Mistelix.DataModel;
 using Mistelix.Core;
 using Mistelix.Backends;
+using Mistelix.Backends.OS;
 using Mistelix.Dialogs;
 
 namespace Mistelix.Core
@@ -123,7 +124,7 @@ namespace Mistelix.Core
 			sp.Create ();
 		
 			//LaunchTool (string app, string args, string in_file, string out_file, string err_file);
-			MistelixLib.LaunchTool ("spumux", 
+			Unix.LaunchTool ("spumux", 
 				project.FileToFullPath (Defines.SPUMUX_FILE),
 				project.FileToFullPath (Defines.MAIN_MENU_FILE_SRC),
 				project.FileToFullPath (Defines.MAIN_MENU_FILE),
@@ -147,7 +148,7 @@ namespace Mistelix.Core
 
 			string args = String.Format ("-x{0}", project.FileToFullPath (Defines.DVDAUTHOR_FILE));
 
-			MistelixLib.LaunchTool ("dvdauthor",
+			Unix.LaunchTool ("dvdauthor",
 				args,
 				null,
 				null,
diff --git a/src/Core/Preferences.cs b/src/Core/Preferences.cs
index 3607766..b1769bf 100644
--- a/src/Core/Preferences.cs
+++ b/src/Core/Preferences.cs
@@ -29,6 +29,7 @@ using System.Text;
 using System.Diagnostics;
 
 using Mistelix.DataModel;
+using Mistelix.Backends.OS;
 
 namespace Mistelix.Core
 {
@@ -191,7 +192,7 @@ namespace Mistelix.Core
 				Environment.GetFolderPath (Environment.SpecialFolder.MyPictures));
 
 			properties.Add (VideosDirectoryKey,
-				GetDefaultVideoDirectory ());
+				Unix.GetDefaultVideoDirectory ());
 
 			properties.Add (AudioDirectoryKey,
 				Environment.GetFolderPath (Environment.SpecialFolder.MyMusic));
@@ -231,47 +232,5 @@ namespace Mistelix.Core
 				Logger.Error (String.Format ("Preferences.Load. Error loading preferences {0}", e.Message));
 			}
 		}
-
-		// There is no SpecialFolder support for videos. We have to read the xdg configuration directly
-		static string GetDefaultVideoDirectory ()
-		{
-			string directory = null, line;
-			const string home = "$HOME/";
-			const string key = "XDG_VIDEOS_DIR";
-			string home_dir = Environment.GetEnvironmentVariable ("HOME");
-			string config_file;
-
-			try {
-				config_file = Path.Combine (home_dir, ".config/user-dirs.dirs");
-
-				using (StreamReader reader = new StreamReader (config_file))
-				{
-					while ((line = reader.ReadLine ()) != null) 
-					{
-						line = line.Trim ();
-						int pos = line.IndexOf ('=');
-				                if (pos > 8 && line.Substring (0, pos) == key) {
-							string path = line.Substring (pos + 1).Trim ('"');
-							bool relative = false;
-
-							if (path.StartsWith (home)) {
-								relative = true;
-								path = path.Substring (home.Length);
-							} else if (!path.StartsWith ("/"))
-								relative = true;
-
-			                    		directory = relative ? Path.Combine (home_dir, path) : path;
-							break;
-						}
-		                	}
-				}
-			}
-			catch (Exception) { }
-
-			if (directory == null)
-				return Environment.GetFolderPath (Environment.SpecialFolder.Personal);
-			else
-				return directory;
-		}
 	}
 }
diff --git a/src/Core/SlideShow.cs b/src/Core/SlideShow.cs
index f811b4c..983011c 100644
--- a/src/Core/SlideShow.cs
+++ b/src/Core/SlideShow.cs
@@ -26,6 +26,7 @@ using System;
 using Mistelix.Transitions;
 using Mistelix.Core;
 using Mistelix.DataModel;
+using Mistelix.Backends.GStreamer;
 
 namespace Mistelix.Core
 {
@@ -41,7 +42,6 @@ namespace Mistelix.Core
 
 		public string Generate (Project project, ProgressEventHandler progress)
 		{
-			MistelixLib lib = new MistelixLib ();
 			int total_frames = 0;
 			int frames_sec = project.Details.FramesPerSecond;
 			ProgressEventArgs args = new ProgressEventArgs ();
@@ -65,12 +65,12 @@ namespace Mistelix.Core
 			else
 				outfile = filename;
 			
-			lib.SlideShowCreateStream (project.FileToFullPath (outfile), project.Details.Type,
+			Backends.GStreamer.SlideShow.CreateStream (project.FileToFullPath (outfile), project.Details.Type,
 				(uint) project.Details.Width, (uint) project.Details.Height, (uint) frames_sec, (uint) total_frames);
 
 			if (AudioFile != null) {
 				Logger.Debug ("SlideShow.Generate. Audiofile {0}", AudioFile);
-				lib.SlideShowAddAudio (AudioFile);
+				Backends.GStreamer.SlideShow.AddAudio (AudioFile);
 			}
 
 			Transition transition;
@@ -88,7 +88,7 @@ namespace Mistelix.Core
 
 				Logger.Debug ("SlideShow.Generate. Send Fixed image {0}, time {1} (frames)", i, (uint) (frames_sec * images[i].ShowTime));
 				transition = TransitionManager.CreateFromName (images[i].Transition);
-				lib.SlideShowAddImageFixed (((SlideImage)images[i]), (uint) (frames_sec * images[i].ShowTime));
+				Backends.GStreamer.SlideShow.AddImageFixed (((SlideImage)images[i]), (uint) (frames_sec * images[i].ShowTime));
 		
 				// Transition between two images
 				Logger.Debug ("SlideShow.Generate. Generate transition for frames_sec {0} and time {1}", frames_sec, images[i].TransitionTime);
@@ -100,14 +100,14 @@ namespace Mistelix.Core
 				transition.Target = (SlideImage) images[i + 1];
 				transition.Frames = frames_sec * images[i].TransitionTime;
 				foreach (SlideImage img in transition)
-					lib.SlideShowAddImage (img);
+					Backends.GStreamer.SlideShow.AddImage (img);
 
 				Logger.Debug ("Sending subimage completed");
 				((SlideImage) images[i]).ReleasePixels ();
 			}
 
 			Logger.Debug ("SlideShow.Generate. Send fixed image time {0} (frames)", (uint) (frames_sec * images[images.Count -1].ShowTime));
-			lib.SlideShowAddImageFixed (((SlideImage)images[images.Count - 1]), (uint) (frames_sec * images[images.Count -1].ShowTime));
+			Backends.GStreamer.SlideShow.AddImageFixed (((SlideImage)images[images.Count - 1]), (uint) (frames_sec * images[images.Count -1].ShowTime));
 			((SlideImage) images[images.Count - 1]).ReleasePixels ();
 	
 			if (progress != null) {
@@ -116,7 +116,7 @@ namespace Mistelix.Core
 			}
 
 			// This a blocking call. It does not return until the pipeline sends an EOS
-			lib.SlideShowClose ();
+			Backends.GStreamer.SlideShow.Close ();
 			Logger.Debug ("SlideShow.Generate. Finished generation");
 			return project.FileToFullPath (outfile);
 		}			
diff --git a/src/Core/Video.cs b/src/Core/Video.cs
index 01680ca..e4b24cf 100644
--- a/src/Core/Video.cs
+++ b/src/Core/Video.cs
@@ -29,6 +29,7 @@ using System.Collections.Generic;
 using Mistelix.Transitions;
 using Mistelix.DataModel;
 using Mistelix.Widgets;
+using Mistelix.Backends.GStreamer;
 
 namespace Mistelix.Core
 {
@@ -47,7 +48,7 @@ namespace Mistelix.Core
 		{
 			bool rslt;
 
-			rslt = MistelixLib.IsMediaSupported (filename, out msg);
+			rslt = Backends.GStreamer.Video.IsSupported (filename, out msg);
 			Logger.Debug ("Video.SupportedFormat. Filename {0} is {1}", filename, rslt);
 			return rslt;
 		}
@@ -60,7 +61,7 @@ namespace Mistelix.Core
 
 			Logger.Debug ("Video.Convert. File {0} to {1}", filename, outfile);
 			// TODO: If rslt != 0 throw an exception
-			rslt =  MistelixLib.ConvertMedia (filename, outfile, (uint) project.Details.FramesPerSecond);
+			rslt =  Backends.GStreamer.Video.Convert (filename, outfile, (uint) project.Details.FramesPerSecond);
 			return outfile;
 		}
 	}
diff --git a/src/DataModel/VideoProjectElement.cs b/src/DataModel/VideoProjectElement.cs
index 18314fd..746ecb7 100644
--- a/src/DataModel/VideoProjectElement.cs
+++ b/src/DataModel/VideoProjectElement.cs
@@ -28,11 +28,12 @@ using System.Xml.Serialization;
 using Gdk;
 
 using Mistelix.Core;
+using Mistelix.Backends.GStreamer;
 
 namespace Mistelix.DataModel
 {
 	// Describes a video within the authoring project
-	[XmlInclude (typeof (Video))]
+	[XmlInclude (typeof (Core.Video))]
 	public class VideoProjectElement : VisibleProjectElement
 	{
 		public VideoProjectElement ()
@@ -62,7 +63,7 @@ namespace Mistelix.DataModel
 		public override Gdk.Pixbuf GetThumbnail (int width, int height)
 		{
 			Gdk.Pixbuf im;
-			im = MistelixLib.VideoScreenshot (filename);
+			im = Backends.GStreamer.Thumbnail.VideoScreenshot (filename);
 			int max = Math.Max (im.Width, im.Height);
 			Gdk.Pixbuf scaled = im.ScaleSimple (width * im.Width / max, height * im.Height / max, InterpType.Nearest);
 			im.Dispose ();
diff --git a/src/Makefile.am b/src/Makefile.am
index 77ab465..71c4cb4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,7 +37,6 @@ MISTELIX_CSDISTFILES =				\
 	$(srcdir)/Backends/Spumux.cs		\
 	$(srcdir)/Backends/DvdAuthor.cs		\
 	$(srcdir)/DataModel/Transition.cs	\
-	$(srcdir)/Core/MistelixLib.cs \
 	$(srcdir)/Core/NoneTransition.cs	\
 	$(srcdir)/Core/TransitionManager.cs	\
 	$(srcdir)/Core/XmlStorage.cs	\
@@ -73,7 +72,12 @@ MISTELIX_CSDISTFILES =				\
 	$(srcdir)/Widgets/CairoImageCellRenderer.cs \
 	$(srcdir)/Widgets/WelcomeView.cs \
 	$(srcdir)/DataModel/RecentFile.cs \
-	$(srcdir)/Core/RecentFilesStorage.cs
+	$(srcdir)/Core/RecentFilesStorage.cs \
+	$(srcdir)/Backends/GStreamer/Video.cs \
+	$(srcdir)/Backends/GStreamer/Thumbnail.cs \
+	$(srcdir)/Backends/GStreamer/SlideShow.cs \
+	$(srcdir)/Backends/GStreamer/Plugins.cs \
+	$(srcdir)/Backends/OS/Unix.cs
 
 ASSEMBLIES = \
 	 $(MISTELIX_LIBS)    		\
diff --git a/src/Widgets/VideosFileView.cs b/src/Widgets/VideosFileView.cs
index da21dc7..16200c5 100644
--- a/src/Widgets/VideosFileView.cs
+++ b/src/Widgets/VideosFileView.cs
@@ -30,6 +30,7 @@ using Mistelix.DataModel;
 using System.ComponentModel;
 
 using Mistelix.Core;
+using Mistelix.Backends.GStreamer;
 
 namespace Mistelix.Widgets
 {
@@ -54,7 +55,7 @@ namespace Mistelix.Widgets
 			int pos;
 		
 			filename = filename.ToLower ();
-			extensions = MistelixLib.VideoExtensions ();
+			extensions = Backends.GStreamer.Video.FileExtensions ();
 
 			foreach (string extension in extensions) {
 				pos = extension.IndexOf ("."); // Extensions are returned as [*.ext]
@@ -78,7 +79,8 @@ namespace Mistelix.Widgets
 				try {
 					Gdk.Pixbuf im;
 
-					im = MistelixLib.VideoScreenshot (file);
+					// TODO: This should be at VideoProjectElement.GetThumbnail
+					im = Backends.GStreamer.Thumbnail.VideoScreenshot (file);
 
 					int max = Math.Max (im.Width, im.Height);
 					Gdk.Pixbuf scaled = im.ScaleSimple (thumbnail_width * im.Width / max, thumbnail_height * im.Height / max, InterpType.Nearest);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]