[gst-devel] Problems to rip CD using cdparanoiasrc

Pascal Ognibene pognibene at gmail.com
Fri Jan 22 21:27:21 CET 2010


Hi all,

I'm trying to rip a CD using a simple gstreamer pipeline - something that is
already done in several programs,
but i'd like to understand myself how it works.

In the code below, I basically use the EOS event to seek to the next cd
track.
But the behavior I see is weird:
-the first track is ripped ok
-I call the start_track_rip function for track 2
-the program blocks here forever.

I must be doing something really wrong but I can't see what, even by the
looking at the sources of sound juicer for example.
Any help is welcome,

- pog

Code below:
-----------------

#include <glib.h>
#include <gst/gst.h>
#include <string.h>

guint current_rip_track = 1;
guint max_rip_track = 10;

void start_track_rip();

static GMainLoop *loop;
GstElement *pipeline;

static gboolean
my_bus_callback(GstBus * bus, GstMessage * message, gpointer data)
{
    g_print("Got %s message\n", GST_MESSAGE_TYPE_NAME(message));
    switch (GST_MESSAGE_TYPE(message)) {
    case GST_MESSAGE_ERROR:{
            GError *err;
            gchar *debug;
            gst_message_parse_error(message, &err, &debug);
            g_print("Error: %s\n", err->message);
            g_error_free(err);
            g_free(debug);
            g_main_loop_quit(loop);
            break;
        }
    case GST_MESSAGE_EOS:
        if (current_rip_track < max_rip_track) {
            current_rip_track++;
            g_print("going to next track %d\n", current_rip_track);
            start_track_rip();
        } else {
            g_print("no more tracks, stopping\n");
            return FALSE;
        }
        break;
    default:
        /* unhandled message */
        break;
    }
    return TRUE;
}

static gboolean cb_print_position(GstElement * pipeline)
{
    GstState state, pending_state;
    static GstFormat format = GST_FORMAT_TIME;
    gint64 pos, len;

    gst_element_get_state(pipeline, &state, &pending_state, 0);
    if (state != GST_STATE_PLAYING && pending_state != GST_STATE_PLAYING) {
        return FALSE;
    }

    if (gst_element_query_position(pipeline, &format, &pos)
        && gst_element_query_duration(pipeline, &format, &len)) {
        g_print("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
            GST_TIME_ARGS(pos), GST_TIME_ARGS(len));
    }
    /* call me again */
    return TRUE;
}

int main()
{
    gst_init(NULL, NULL);

    GstElement *source, *filter, *sink;
    GstBus *bus;

    // build pipeline
    pipeline = gst_pipeline_new("rip-pipeline");
    source = gst_element_factory_make("cdparanoiasrc", "mycdparanoia");
    filter = gst_element_factory_make("lame", "encoder");
    sink = gst_element_factory_make("filesink", "myfilesink");
    gst_bin_add_many(GST_BIN(pipeline), source, filter, sink, NULL);

    if (!gst_element_link_many(source, filter, sink, NULL)) {
        g_warning("Failed to link pipeline elements!");
    }

    bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
    gst_bus_add_watch(bus, my_bus_callback, NULL);
    gst_object_unref(bus);

    g_object_set(G_OBJECT(source), "device", "/dev/hda", NULL);

    start_track_rip();

    g_print("starting main loop\n");

    GMainLoop *loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(loop);

    /* clean up */
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);
    g_main_loop_unref(loop);

    return (0);
}

void start_track_rip()
{
    gchar buf[2048];

    GstElement *sink = gst_bin_get_by_name(GST_BIN(pipeline), "myfilesink");
    strcpy(buf, "/tmp/music_");
    gchar buf2[10];
    sprintf(buf2, "%02d", current_rip_track);
    strcat(buf, buf2);
    strcat(buf, ".mp3");
    gst_element_set_state(sink, GST_STATE_NULL);
    g_object_set(G_OBJECT(sink), "location", buf, NULL);

    // seek to track
    GstElement *cd = gst_bin_get_by_name(GST_BIN(pipeline), "mycdparanoia");
    g_object_set(G_OBJECT(cd), "track", current_rip_track, NULL);
    GstStateChangeReturn state_ret =
        gst_element_set_state(pipeline, GST_STATE_PLAYING);

    if (state_ret == GST_STATE_CHANGE_FAILURE) {
        g_print("01 state change failed\n");
    } else if (state_ret == GST_STATE_CHANGE_SUCCESS) {
        g_print("02 state change successful\n");
    } else if (state_ret == GST_STATE_CHANGE_ASYNC) {
        // what am I supposed to do here?
        g_print("seek async\n");
        state_ret =
            gst_element_get_state(pipeline, NULL, NULL, GST_SECOND / 2);
    }

    g_timeout_add_seconds(1, (GSourceFunc) cb_print_position, pipeline);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20100122/325d71d9/attachment.htm>


More information about the gstreamer-devel mailing list