diff --git a/ecdb/trunk/TODO b/ecdb/trunk/TODO index a75949c..cfe84f2 100644 --- a/ecdb/trunk/TODO +++ b/ecdb/trunk/TODO @@ -1,2 +1,3 @@ -> Detect if the media in a drive has changed and update the drive info (dbus?). --> Creating images is right now rather inflexible (no special/symlinks, etc) and have to do all file managment outside before creating image. +-> Make gstreamer dependancy optional +-> more graceful handling of errors diff --git a/ecdb/trunk/configure.in b/ecdb/trunk/configure.in index 712223d..9d6c89c 100644 --- a/ecdb/trunk/configure.in +++ b/ecdb/trunk/configure.in @@ -72,14 +72,20 @@ changequote([,])dnl LIBBURN_REQUIRED=0.4.2 LIBISOFS_REQUIRED=0.6.2 +GST_MAJORMINOR=0.10 +GST_REQS=0.10.2 +GSTPLUG_REQS=0.10.1 +dnl Make gstreamer an optional dependancy at some point PKG_CHECK_MODULES(ECDB, [ - libburn-1 >= $LIBBURN_REQUIRED - libisofs-1 >= $LIBISOFS_REQUIRED ecore ewl edje efreet-mime + libburn-1 >= $LIBBURN_REQUIRED + libisofs-1 >= $LIBISOFS_REQUIRED + gstreamer-$GST_MAJORMINOR >= $GST_REQS + gstreamer-plugins-base-$GST_MAJORMINOR >= $GSTPLUG_REQS ]) AC_OUTPUT([ diff --git a/ecdb/trunk/src/Makefile.am b/ecdb/trunk/src/Makefile.am index 660d2c7..3717759 100644 --- a/ecdb/trunk/src/Makefile.am +++ b/ecdb/trunk/src/Makefile.am @@ -8,6 +8,7 @@ ecdb_SOURCES = \ ecdb_image.c ecdb_image.h \ ecdb_burn.c ecdb_burn.h \ ecdb_misc.c ecdb_misc.h \ + ecdb_audio.c ecdb_audio.h \ ecdb_common.h ecdb_CFLAGS = @ECDB_CFLAGS@ diff --git a/ecdb/trunk/src/ecdb.h b/ecdb/trunk/src/ecdb.h index 70abefb..6b9c9ab 100644 --- a/ecdb/trunk/src/ecdb.h +++ b/ecdb/trunk/src/ecdb.h @@ -17,6 +17,7 @@ #include #include #include +#include #undef FREE #define FREE(dat) \ @@ -44,6 +45,7 @@ extern int ECDB_DRIVE_ACTION_UPDATE; #include "ecdb_image.h" #include "ecdb_burn.h" #include "ecdb_misc.h" +#include "ecdb_audio.h" #endif diff --git a/ecdb/trunk/src/ecdb_audio.c b/ecdb/trunk/src/ecdb_audio.c new file mode 100644 index 0000000..88e83c4 --- /dev/null +++ b/ecdb/trunk/src/ecdb_audio.c @@ -0,0 +1,189 @@ +#include "ecdb.h" + +/* A lot of the code below is from brasero, so thanks to them for it */ +char *ecdb_audio_output_create(Ecdb_Source *src); +static gboolean cb_buscall(GstBus *bus, GstMessage *msg, gpointer data); +static void cb_newpad(GstElement *decodebin, GstPad *pad, + gboolean last, gpointer data); + +int +ecdb_audio_project_setup(Ecdb_Burn_Project *proj) +{ + int argc; + char **argv; + + GMainLoop *loop; + + ecore_app_args_get(&argc, &argv); + gst_init(&argc, &argv); + loop = g_main_loop_new(NULL, FALSE); + return TRUE; +} + +static gboolean +cb_buscall(GstBus *bus, GstMessage *msg, gpointer data) +{ + if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_EOS) + printf("End of stream\n"); + + else if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) + { + gchar *debug; + GError *err; + + gst_message_parse_error(msg, &err, &debug); + g_free(debug); + g_print("Error: %s\n", err->message); + g_error_free(err); + } + + return TRUE; +} + +static void +cb_newpad(GstElement *decodebin, GstPad *pad, gboolean last, gpointer data) +{ + GstPad *sink; + GstCaps *caps; + GstStructure *structure; + GstElement *convert; + + convert = (GstElement *) data; + + sink = gst_element_get_pad (convert, "sink"); + if (GST_PAD_IS_LINKED (sink)) + return; + + /* make sure we only have audio */ + caps = gst_pad_get_caps (pad); + if (!caps) + return; + + structure = gst_caps_get_structure (caps, 0); + if (structure + && g_strrstr (gst_structure_get_name (structure), "audio")) + gst_pad_link (pad, sink); + + gst_object_unref (sink); + gst_caps_unref (caps); +} + +int +ecdb_audio_project_handle(Ecdb_Source *src, char *error) +{ + GstElement *decode; + GstElement *source; + GstBus *bus = NULL; + GstCaps *filtercaps; + GstElement *pipeline; + GstElement *sink = NULL; + GstElement *filter = NULL; + GstElement *convert = NULL; + GstElement *resample = NULL; + char *output; + + pipeline = gst_pipeline_new(NULL); + bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); + gst_bus_add_watch(bus, cb_buscall, NULL); + gst_object_unref(bus); + + /* source */ + source = gst_element_make_from_uri(GST_URI_SRC, src->dst, NULL); + if (!source) + { + error = "Source couldn't be created!"; + gst_object_unref(GST_OBJECT(pipeline)); + return FALSE; + } + gst_bin_add(GST_BIN(pipeline), source); + g_object_set(source, "typefind", FALSE, NULL); + + /* Output */ + sink = gst_element_factory_make("filesink", NULL); + output = ecdb_audio_output_create(src); + g_object_set(sink, "location", output, NULL); + src->dst = output; + if (!sink) + { + error = "Sink couldn't be created!"; + gst_object_unref(GST_OBJECT(pipeline)); + FREE(output); + return FALSE; + } + gst_bin_add(GST_BIN(pipeline), sink); + g_object_set(sink, "sync", FALSE, NULL); + + /* Audioconvert */ + convert = gst_element_factory_make("audioconvert", NULL); + if (!convert) + { + error = "Audioconvert couldn't be created!"; + gst_object_unref(GST_OBJECT(pipeline)); + FREE(output); + return FALSE; + } + + /* resample */ + resample = gst_element_factory_make("audioresample", NULL); + if (!resample) + { + error = "Audioresampler couldn't be create!"; + gst_object_unref(GST_OBJECT(pipeline)); + FREE(output); + return FALSE; + } + gst_bin_add(GST_BIN(pipeline), resample); + + /* Filter */ + filter = gst_element_factory_make("capsfilter", NULL); + if (!filter) + { + error = "Filter couldn't be created!"; + gst_object_unref(GST_OBJECT(pipeline)); + FREE(output); + return FALSE; + } + gst_bin_add(GST_BIN(pipeline), filter); + filtercaps = gst_caps_new_full(gst_structure_new("audio/x-raw-int", + "channels", G_TYPE_INT, 2, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, 1234, + "rate", G_TYPE_INT, 44100, + "signed", G_TYPE_BOOLEAN, TRUE, + NULL), NULL); + g_object_set(GST_OBJECT(filter), "caps", filtercaps, NULL); + gst_caps_unref(filtercaps); + + /* decode */ + decode = gst_element_factory_make("decodebin", NULL); + if (!decode) + { + error = "Decode couldn't be created!"; + gst_object_unref(GST_OBJECT(pipeline)); + FREE(output); + return FALSE; + } + gst_bin_add(GST_BIN(pipeline), decode); + gst_element_link_many(source, decode, NULL); + g_signal_connect(G_OBJECT(decode), "new-decoded-pad", + G_CALLBACK(cb_newpad), resample); + gst_element_link_many(resample, convert, filter, sink, NULL); + + /* End stuff */ + gst_element_set_state(pipeline, GST_STATE_PLAYING); + FREE(output); + return TRUE; +} + +char * +ecdb_audio_output_create(Ecdb_Source *src) +{ + char ret[PATH_MAX]; + + snprintf(ret, PATH_MAX, "/tmp/ecdb/%s.wav", + ecore_file_file_get + (ecore_file_strip_ext(src->dst))); + return strdup(ret); +} + diff --git a/ecdb/trunk/src/ecdb_audio.h b/ecdb/trunk/src/ecdb_audio.h new file mode 100644 index 0000000..fe1fc0c --- /dev/null +++ b/ecdb/trunk/src/ecdb_audio.h @@ -0,0 +1,6 @@ +#ifndef ECDB_AUDIO_H +#define ECDB_AUDIO_H + +Ecdb_Source *ecdb_audio_track_handle(Ecdb_Source *src); + +#endif diff --git a/ecdb/trunk/src/ecdb_common.h b/ecdb/trunk/src/ecdb_common.h index 20176da..d3a2543 100644 --- a/ecdb/trunk/src/ecdb_common.h +++ b/ecdb/trunk/src/ecdb_common.h @@ -56,7 +56,7 @@ struct _Ecdb_Project_Info typedef struct _Ecdb_Source Ecdb_Source; struct _Ecdb_Source { - const char *dst; + char *dst; unsigned char rec:1; unsigned char num_children; Ecdb_Source **children; diff --git a/ecdb/trunk/src/ecdb_image.c b/ecdb/trunk/src/ecdb_image.c index d178338..f9c7531 100644 --- a/ecdb/trunk/src/ecdb_image.c +++ b/ecdb/trunk/src/ecdb_image.c @@ -37,7 +37,7 @@ ecdb_source_data_set(Ecdb_Source *src, const char *dst, unsigned char rec) if (!src) return; - src->dst = dst; + src->dst = strdup(dst); src->rec = rec; }