sdroege/gstreamer-rs

Help: Initializing and Setting a GValueArray for audioiirfilter

MateusAmin opened this issue · 1 comments

I would like to make a GValueArray of GDouble in Rust to set the gStreamer element property. I would sincerely appreciate any help. I can do it in C as shown in the examples below.

Currently, in rust I am stuck at trying to make GValue.

Now stuck at the audioiirfilter.set_property("a", &a); call.

    let mut gv: gobject_sys::GValue;
    let v: Box<gobject_sys::GValue> = Box::new(gv);
    let v: *mut gobject_sys::GValue = Box::into_raw(v);

    gobject_sys::g_value_init(v, gobject_sys::G_TYPE_DOUBLE);

    gobject_sys::g_value_set_double(v, 1.0);
    
    let a = gobject_sys::g_value_array_new(2);

    gobject_sys::g_value_array_append(a, v);

    audioiirfilter.set_property("a", &a); #Error
error[E0277]: the trait bound `*mut gobject_sys::GValueArray: glib::value::SetValue` is not satisfied
  --> src/main.rs:64:38
   |
64 |     audioiirfilter.set_property("a", &a);
   |                                      ^^ the trait `glib::value::SetValue` is not implemented for `*mut gobject_sys::GValueArray`
   |
   = note: required because of the requirements on the impl of `glib::value::ToValue` for `*mut gobject_sys::GValueArray`
   = note: required for the cast to the object type `dyn glib::value::ToValue`

Without context in C:

    GValueArray *va;
    GValue v = {
        0,
    };
    gdouble a_kernel[2];

    a_kernel[0] = 1;
    a_kernel[1] = -0.05095288;

    va = g_value_array_new(1);
    g_value_init(&v, G_TYPE_DOUBLE);

    for (int i = 0; i < 2; i++)
    {
        g_value_set_double(&v, a_kernel[i]);
        g_value_array_append(va, &v);
        g_value_reset(&v);
    }

With context in C:

#define GLIB_DISABLE_DEPRECATION_WARNINGS

#include <gst/gst.h>

int main(int argc, char *argv[])
{
    GstElement *pipeline, *source, *sink, *audioiirfilter;
    GstBus *bus;
    GstMessage *msg;
    GstStateChangeReturn ret;

    /* Initialize GStreamer */
    gst_init(&argc, &argv);

    /* Create the elements */
    source = gst_element_factory_make("audiotestsrc", "source");
    sink = gst_element_factory_make("autoaudiosink", "sink");

    audioiirfilter = gst_element_factory_make("audioiirfilter", "audioiirfilter");

    /* Create the empty pipeline */
    pipeline = gst_pipeline_new("test-pipeline");

    if (!pipeline || !source || !sink)
    {
        g_printerr("Not all elements could be created.\n");
        return -1;
    }

    /* Build the pipeline */
    gst_bin_add_many(GST_BIN(pipeline), source, audioiirfilter, sink, NULL);

    if (gst_element_link(source, audioiirfilter) != TRUE)
    {
        g_printerr("Elements could not be linked.\n");
        gst_object_unref(pipeline);
        return -1;
    }
    if (gst_element_link(audioiirfilter, sink) != TRUE)
    {
        g_printerr("Elements could not be linked.\n");
        gst_object_unref(pipeline);
        return -1;
    }

    GValueArray *va;
    GValue v = {
        0,
    };
    gdouble a_kernel[2];

    a_kernel[0] = 1;
    a_kernel[1] = -0.05095288;

    va = g_value_array_new(1);
    g_value_init(&v, G_TYPE_DOUBLE);

    for (int i = 0; i < 2; i++)
    {
        g_value_set_double(&v, a_kernel[i]);
        g_value_array_append(va, &v);
        g_value_reset(&v);
    }

    g_object_set(audioiirfilter, "a", va, NULL);
    g_value_array_free(va);

    /* Start playing */
    ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE)
    {
        g_printerr("Unable to set the pipeline to the playing state.\n");
        gst_object_unref(pipeline);
        return -1;
    }

    /* Wait until error or EOS */
    bus = gst_element_get_bus(pipeline);
    msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

    /* Free resources */
    gst_object_unref(bus);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);
    return 0;
}

If you want to run. Paste the with context example to c.c and run the following after following setup guidelines for gstreamer:

gcc c.c -o c `pkg-config --cflags --libs gstreamer-1.0` && ./c