<div dir="auto">I forgot, but an in the middle option is to split your source pipelines into seperate pipelines. Then use appsr/appsink to pass the data to the mixing pipeline. This way you can simply retimestamp and it no longer matter how you seek the sources.</div><div class="gmail_extra"><br><div class="gmail_quote">Le 17 déc. 2017 1:41 PM, "Nicolas Dufresne" <<a href="mailto:nicolas@ndufresne.ca">nicolas@ndufresne.ca</a>> a écrit :<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div><br><div class="gmail_extra"><br><div class="gmail_quote">Le 17 déc. 2017 11:44 AM,  <<a href="mailto:spam@feuerundbenzin.tk" target="_blank">spam@feuerundbenzin.tk</a>> a écrit :<br type="attribution"><blockquote class="m_-8531326014025062837quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello,<br>
<br>
I want to create a lite sampler application. Where you can play,stop,loop multiple sound files.<br>
im currently experimenting with gstreamer and stuck on some point.<br>
<br>
this is how my application currently look like:<br>
<br>
pipeline:<br>
bin1: filesource1 -> decoder1 -> converter1 ---\<br>
|-> audiomixer -> alsasink<br>
bin2: filesource2 -> decoder2 -> converter2  ---/<br>
<br>
i have an audiomixer connected with to file sources. how can i seek the 2 sources interdependently ?<br>
I can seek the whole pipeline, but seeking the filesources don't work (see function play_button_CB in src).<br>
<br>
can anybody help ?<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">For now, your only "easy" option would be to use GStreamer Editing Services, a library designed on top of GStreamer to implement non-linear audio/video editing applications. Second possibility would be to use it's helper plugins, NLE. The hard way is to implement something similar to NLE, though that requires strong GStreamer dynamic coding skills, it's not for everyone.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="m_-8531326014025062837quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Thanks Richard<br>
<br>
<br>
------------------------------<wbr>-----------------<br>
#include <gst/gst.h><br>
#include <gst/gstelement.h><br>
#include <stdio.h><br>
#include <unistd.h><br>
#include <string.h><br>
<br>
#include <glib.h><br>
#define FALSE (0)<br>
#define TRUE (!FALSE)<br>
<br>
#include <gtk/gtk.h><br>
<br>
typedef struct<br>
{<br>
    GstElement *pipeline;<br>
<br>
    GstElement *file_source;<br>
    GstElement *audio_decoder;<br>
    GstElement *audioconvert;<br>
    GstElement *bin_playback;<br>
<br>
    GstElement *file_source2;<br>
    GstElement *audio_decoder2;<br>
    GstElement *audioconvert2;<br>
    GstElement *bin_playback2;<br>
<br>
    GstElement *audio_mixer;<br>
    GstElement *alsasink;<br>
<br>
    GstElement *visual;<br>
    GstElement *tee;<br>
<br>
<br>
    GstBus *bus;<br>
    GstMessage *message;<br>
<br>
    gchar filelocation[2000];<br>
}playerData;<br>
<br>
playerData gstreamerPlayer;<br>
<br>
<br>
typedef struct<br>
{<br>
    GtkWidget *mainWindow;<br>
    GtkWidget *play_button;<br>
<br>
}guiData;<br>
<br>
guiData guiElements;<br>
<br>
/*<br>
void on_pad_added2 (GstElement *src_element, GstPad *src_pad, gpointer data)<br>
{<br>
    g_print ("\nLinking dynamic pad between wavparse and alsasink\n");<br>
<br>
    GstElement *sink_element = (GstElement *) data;     // Is alsasink<br>
    GstPad *sink_pad = gst_element_get_static_pad (sink_element, "sink");<br>
    gst_pad_link (src_pad, sink_pad);<br>
<br>
    gst_object_unref (sink_pad);<br>
    src_element = NULL;     // Prevent "unused" warning here<br>
}<br>
*/<br>
<br>
gboolean player_Create(playerData *data)<br>
{<br>
    data->pipeline = gst_pipeline_new("audio_pipeli<wbr>ne");<br>
<br>
    if (data->pipeline == NULL)    return FALSE;<br>
    gst_element_set_state (data->pipeline, GST_STATE_NULL);<br>
<br>
    data->alsasink = gst_element_factory_make("alsa<wbr>sink", "audiosink");<br>
    data->audio_mixer = gst_element_factory_make("audi<wbr>omixer","audiomixer");<br>
<br>
    if ( !data->pipeline || !data->alsasink || !data->audio_mixer)    {<br>
        g_printerr ("\nNot all elements for audio pipeline were created\n");<br>
        return FALSE;<br>
    }<br>
<br>
<br>
    gst_bin_add_many(GST_BIN (data->pipeline), data->audio_mixer,data->alsasi<wbr>nk,NULL);<br>
<br>
<br>
    if (gst_element_link_many (data->audio_mixer, data->alsasink, NULL) != TRUE) {<br>
        g_printerr("\nAudio mixer and audio sink element could not link\n");<br>
        return FALSE;<br>
    }<br>
<br>
<br>
}<br>
<br>
<br>
gboolean player_Add(playerData *data)<br>
{<br>
    data->bin_playback = gst_bin_new ("bin_playback");<br>
    data->bin_playback2 = gst_bin_new ("bin_playback2");<br>
<br>
<br>
<br>
<br>
    data->file_source = gst_element_factory_make("file<wbr>src", "filesource");<br>
    data->audioconvert = gst_element_factory_make("audi<wbr>oconvert", "audioconverter");<br>
<br>
    data->file_source2 = gst_element_factory_make("file<wbr>src", "filesource2");<br>
    data->audioconvert2 = gst_element_factory_make("audi<wbr>oconvert", "audioconverter2");<br>
<br>
<br>
<br>
<br>
<br>
    if ( !data->file_source || !data->audioconvert)    {<br>
        g_printerr ("\nNot all elements for audio pipeline were created\n");<br>
        return FALSE;<br>
    }<br>
<br>
    if ( !data->file_source2 || !data->audioconvert2)    {<br>
        g_printerr ("\nNot all elements for audio pipeline were created\n");<br>
        return FALSE;<br>
    }<br>
<br>
<br>
<br>
    g_object_set (G_OBJECT (data->file_source), "location", "/home/admin2/Downloads/Sample<wbr>Audio_0.4mb.mp3", NULL);<br>
<br>
    g_object_set (G_OBJECT (data->file_source2), "location", "/home/admin2/Downloads/Sample<wbr>Audio_0.7mb.mp3", NULL);<br>
<br>
<br>
<br>
    data->audio_decoder = gst_element_factory_make("mad"<wbr>, "audiomp3decoder");<br>
    if ( !data->audio_decoder)    {<br>
        g_printerr ("\nNot all elements for audio pipeline were created\n");<br>
        return FALSE;<br>
    }<br>
<br>
<br>
    gst_bin_add_many(GST_BIN(data-<wbr>>bin_playback), data->file_source, data->audio_decoder, data->audioconvert, NULL);<br>
<br>
    if (gst_element_link_many (data->file_source, data->audio_decoder, NULL) != TRUE) {<br>
        g_printerr("\nFile source and audio decoder element could not link\n");<br>
        return FALSE;<br>
    }<br>
<br>
    if (gst_element_link_many (data->audio_decoder, data->audioconvert, NULL) != TRUE) {<br>
        g_printerr("\nAudio decoder and audio converter element could not link\n");<br>
        return FALSE;<br>
    }<br>
<br>
    {<br>
    GstPad *pad;<br>
    pad = gst_element_get_static_pad (data->audioconvert, "src");<br>
    gst_element_add_pad (data->bin_playback, gst_ghost_pad_new ("src", pad));<br>
    gst_object_unref (GST_OBJECT (pad));<br>
    }<br>
<br>
<br>
<br>
/*############################<wbr>##############################<wbr>######################*/ <br>
    data->audio_decoder2 = gst_element_factory_make("mad"<wbr>, "audiomp3decoder2");<br>
    if ( !data->audio_decoder2)    {<br>
        g_printerr ("\nNot all elements for audio pipeline were created\n");<br>
        return FALSE;<br>
    }<br>
<br>
    gst_bin_add_many(GST_BIN(data-<wbr>>bin_playback2), data->file_source2, data->audio_decoder2, data->audioconvert2,NULL);<br>
<br>
    if (gst_element_link_many (data->file_source2, data->audio_decoder2, NULL) != TRUE) {<br>
        g_printerr("\nFile source and audio decoder element could not link\n");<br>
        return FALSE;<br>
    }<br>
    if (gst_element_link_many (data->audio_decoder2, data->audioconvert2, NULL) != TRUE) {<br>
        g_printerr("\nAudio decoder and audio converter element could not link\n");<br>
        return FALSE;<br>
    }<br>
<br>
    {<br>
    GstPad *pad;<br>
    pad = gst_element_get_static_pad (data->audioconvert2, "src");<br>
    gst_element_add_pad (data->bin_playback2, gst_ghost_pad_new ("src", pad));<br>
    gst_object_unref (GST_OBJECT (pad));<br>
    }<br>
<br>
<br>
<br>
    return TRUE;<br>
}<br>
<br>
<br>
<br>
<br>
<br>
gboolean player_Start(playerData *data)<br>
{<br>
    gst_bin_add_many(GST_BIN (data->pipeline), data->bin_playback, data->bin_playback2, NULL);<br>
<br>
<br>
<br>
    if (gst_element_link_many (data->bin_playback, data->audio_mixer, NULL) != TRUE) {<br>
        g_printerr("\nbin_playback and audio mixer element could not link\n");<br>
        return FALSE;<br>
    }<br>
    if (gst_element_link_many (data->bin_playback2, data->audio_mixer, NULL) != TRUE) {<br>
            g_printerr("\nbin_playback2 and audio mixer element could not link\n");<br>
            return FALSE;<br>
    }<br>
<br>
    if (gst_element_set_state (data->pipeline, GST_STATE_NULL) != GST_STATE_CHANGE_SUCCESS) {<br>
        g_print("\nFailed to set pipeline state to NULL\n");<br>
        return FALSE;<br>
    }<br>
<br>
    gst_element_set_state (data->pipeline, GST_STATE_PLAYING);<br>
    while(gst_element_get_state(da<wbr>ta->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) != GST_STATE_CHANGE_SUCCESS);<br>
    return TRUE;<br>
<br>
}<br>
<br>
<br>
<br>
<br>
static gboolean bus_call_CB (GstBus *bus, GstMessage *msg, gpointer    data) {<br>
    GMainLoop *loop = (GMainLoop *) data;<br>
<br>
    switch (GST_MESSAGE_TYPE (msg)) {<br>
<br>
        case GST_MESSAGE_EOS:<br>
            g_print ("End of stream\n");<br>
            g_main_loop_quit (loop);<br>
            break;<br>
<br>
        case GST_MESSAGE_ERROR:<br>
            {<br>
            gchar  *debug;<br>
            GError *error;<br>
<br>
            gst_message_parse_error (msg, &error, &debug);<br>
<br>
            g_printerr ("Error: %s\n", error->message);<br>
            g_error_free (error);<br>
<br>
            if (debug) {<br>
                g_printerr ("\nDebug details: %s\n", debug);<br>
                g_free (debug);<br>
            }<br>
<br>
            g_main_loop_quit (loop);<br>
            break;<br>
            }<br>
<br>
        default:<br>
            break;<br>
    }<br>
<br>
  return TRUE;<br>
}<br>
<br>
static void play_button_CB (GtkButton *button, guiData *data) {<br>
<br>
    //this works ...<br>
    /*<br>
    if (!gst_element_seek(gstreamerPl<wbr>ayer.pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT,GST_SEEK<wbr>_TYPE_SET,0,GST_SEEK_TYPE_NONE<wbr>, 6)) {<br>
        g_print("Seek failed!\n");<br>
    }<br>
    */<br>
<br>
    //how to seek file_source independently ???<br>
<br>
    //this not ...<br>
    if (!gst_element_seek(gstreamerPl<wbr>ayer.file_source, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT,GST_SEEK<wbr>_TYPE_SET,0,GST_SEEK_TYPE_NONE<wbr>, 6)) {<br>
        g_print("Seek failed!\n");<br>
    }<br>
}<br>
<br>
void create_Gui(guiData *data) {<br>
<br>
<br>
      data->mainWindow = gtk_window_new(GTK_WINDOW_TOPL<wbr>EVEL);<br>
<br>
<br>
      data->play_button = gtk_button_new_from_icon_name ("media-playback-start", GTK_ICON_SIZE_SMALL_TOOLBAR);<br>
      g_signal_connect (G_OBJECT (data->play_button), "clicked", G_CALLBACK (play_button_CB), data);<br>
<br>
      GtkWidget *controls = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);<br>
      gtk_box_pack_start (GTK_BOX (controls), data->play_button, FALSE, FALSE, 2);<br>
      gtk_container_add (GTK_CONTAINER (data->mainWindow), controls);<br>
<br>
      gtk_widget_show_all(data->main<wbr>Window);<br>
<br>
}<br>
<br>
<br>
<br>
<br>
int main(int argc, char *argv[])<br>
{<br>
    gtk_init_check(&argc, &argv);<br>
    gst_init (&argc, &argv);<br>
<br>
<br>
    player_Create(&gstreamerPlayer<wbr>);<br>
    player_Add(&gstreamerPlayer);<br>
    player_Start(&gstreamerPlayer)<wbr>;<br>
<br>
<br>
<br>
    GstBus *bus;<br>
    guint bus_watch_id;<br>
    GMainLoop *loop;<br>
    loop = g_main_loop_new (NULL, FALSE);<br>
<br>
<br>
<br>
    bus = gst_pipeline_get_bus (GST_PIPELINE (gstreamerPlayer.pipeline));<br>
    bus_watch_id = gst_bus_add_watch (bus, bus_call_CB, loop);<br>
    gst_object_unref (bus);<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
    create_Gui(&guiElements);<br>
    g_main_loop_run (loop);<br>
<br>
<br>
    gst_element_set_state (gstreamerPlayer.pipeline, GST_STATE_NULL);<br>
    gst_object_unref (GST_OBJECT (gstreamerPlayer.pipeline));<br>
    g_source_remove (bus_watch_id);<br>
    g_main_loop_unref (loop);<br>
<br>
    //to more cleanup here<br>
}<br>
<br>
______________________________<wbr>_________________<br>
gstreamer-devel mailing list<br>
<a href="mailto:gstreamer-devel@lists.freedesktop.org" target="_blank">gstreamer-devel@lists.freedesk<wbr>top.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/gstreamer-dev<wbr>el</a><br>
</blockquote></div><br></div></div></div>
</blockquote></div></div>