Skip to content

Commit

Permalink
Controller API support (#158)
Browse files Browse the repository at this point in the history
* Initial lowlevel controller API and timed value controller mappings / pointer types.

* Add missing GstDirectControlBinding support to lowlevel.

* Add Natives.objectFor and Natives.callerOwnsReturn variants that accept GPointer directly.

* Add ControlSource and ControlBinding base classes; add GstObject support for control bindings; add DirectControlBinding, TimedValueControlSource (incomplete) and InterpolationControlSource.

* Add GstTimedValue structure and Java equivalent; add bulk set and get support to TimedValueControlSource.

* Add LFOControlSource

* Add GTYPE_NAME and registration.

* Return boolean from GstObject::syncValues as upstream - use with trigger control source is awkward otherwise.

* Add some testing of interpolation control source.

* Add TriggerControlSource with simple test.

* Return this on property setting for easier method chaining.

* Implement ARGBControlBinding mapping.

* Add ProxyControlBinding mapping.
  • Loading branch information
neilcsmith-net committed Jun 7, 2019
1 parent 3a19c36 commit 2ef6e3d
Show file tree
Hide file tree
Showing 31 changed files with 2,168 additions and 184 deletions.
126 changes: 126 additions & 0 deletions src/org/freedesktop/gstreamer/ControlBinding.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2019 Neil C Smith
*
* This file is part of gstreamer-java.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
*/
package org.freedesktop.gstreamer;

import org.freedesktop.gstreamer.lowlevel.GValueAPI;
import org.freedesktop.gstreamer.lowlevel.GstControlBindingPtr;

import static org.freedesktop.gstreamer.lowlevel.GstControlBindingAPI.GSTCONTROLBINDING_API;

/**
* Attachment for control source sources.
* <p>
* See upstream documentation at
* <a href="https://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstControlBinding.html"
* >https://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstControlBinding.html</a>
* <p>
*/
public class ControlBinding extends GstObject {

public static final String GTYPE_NAME = "GstControlBinding";

private final Handle handle;

protected ControlBinding(Handle handle, boolean needRef) {
super(handle, needRef);
this.handle = handle;
}

ControlBinding(Initializer init) {
this(new Handle(
init.ptr.as(GstControlBindingPtr.class, GstControlBindingPtr::new),
init.ownsHandle),
init.needRef);
}

/**
* Gets the value for the given controlled property at the requested time.
*
* @param timestamp the time the control-change should be read from
* @return the value of the property at the given time, or NULL if the
* property isn't controlled
*/
public Object getValue(long timestamp) {
GValueAPI.GValue gValue = GSTCONTROLBINDING_API.gst_control_binding_get_value(
handle.getPointer(), timestamp);
return gValue == null ? null : gValue.getValue();
}

/**
* Gets a number of values for the given controlled property starting at
* the requested time.
* <p>
* This function is useful if one wants to e.g. draw a graph of the control
* curve or apply a control curve sample by sample.
*
* @param timestamp the time that should be processed
* @param interval the time spacing between subsequent values
* @param values array to fill with control values
* @return false if the given array could not be filled
*/
public boolean getValueArray(long timestamp, long interval, Object[] values) {
GValueAPI.GValueArray gValues = new GValueAPI.GValueArray(values.length);
boolean ok = GSTCONTROLBINDING_API.gst_control_binding_get_g_value_array(
handle.getPointer(),
timestamp,
interval,
gValues.n_values,
gValues);
if (ok) {
for (int i = 0; i < values.length; i++) {
values[i] = gValues.getValue(i);
}
}
return ok;
}

/**
* This function is used to disable a control binding for some time, i.e.
* GstObject.syncValues() will do nothing.
*
* @param disabled whether to disable the controller or not
*/
public void setDisabled(boolean disabled) {
GSTCONTROLBINDING_API.gst_control_binding_set_disabled(handle.getPointer(), disabled);
}

/**
* Check if the control binding is disabled.
*
* @return TRUE if the binding is inactive
*/
public boolean isDisabled() {
return GSTCONTROLBINDING_API.gst_control_binding_is_disabled(handle.getPointer());

}


protected static class Handle extends GstObject.Handle {

public Handle(GstControlBindingPtr ptr, boolean ownsHandle) {
super(ptr, ownsHandle);
}

@Override
protected GstControlBindingPtr getPointer() {
return (GstControlBindingPtr) super.getPointer();
}

}

}
160 changes: 160 additions & 0 deletions src/org/freedesktop/gstreamer/ControlSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Copyright (c) 2019 Neil C Smith
*
* This file is part of gstreamer-java.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
*/
package org.freedesktop.gstreamer;

import org.freedesktop.gstreamer.lowlevel.GstControlSourcePtr;

import static org.freedesktop.gstreamer.lowlevel.GstControlSourceAPI.GSTCONTROLSOURCE_API;

/**
* Base class for control source sources.
* <p>
* See upstream documentation at
* <a href="https://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstControlSource.html"
* >https://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstControlSource.html</a>
* <p>
*/
public class ControlSource extends GstObject {

public static final String GTYPE_NAME = "GstControlSource";

private final Handle handle;

protected ControlSource(Handle handle, boolean needRef) {
super(handle, needRef);
this.handle = handle;
}

ControlSource(Initializer init) {
this(new Handle(
init.ptr.as(GstControlSourcePtr.class, GstControlSourcePtr::new),
init.ownsHandle),
init.needRef);
}

/**
* Gets the value for this ControlSource at a given timestamp.
*
* @param timestamp the time for which the value should be returned
* @return value
* @throws IllegalStateException if the value could not be calculated
*/
public double getValue(long timestamp) {
double[] out = new double[1];
boolean ok = GSTCONTROLSOURCE_API.gst_control_source_get_value(handle.getPointer(), timestamp, out);
if (ok) {
return out[0];
} else {
throw new IllegalStateException();
}
}

/**
* Gets an array of values for for this ControlSource. Values that are
* undefined contain NANs.
*
* @param timestamp the first timestamp
* @param interval the time steps
* @param values array to put control-values in
* @return true if the values were successfully calculated
*/
public boolean getValueArray(long timestamp, long interval, double[] values) {
return GSTCONTROLSOURCE_API.gst_control_source_get_value_array(
handle.getPointer(),
timestamp,
interval,
values.length,
values);
}

/**
* A simple structure for saving a timestamp and a value.
* <p>
* Equivalent to GstTimedValue.
* <p>
* <a href="https://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstControlSource.html#GstTimedValue"
* >https://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstControlSource.html#GstTimedValue</a>
*
*/
public static final class TimedValue {

public final long timestamp;
public final double value;

/**
* Create a TimedValue wrapping the timestamp (see {@link ClockTime})
* and corresponding value.
*
* @param timestamp the timestamp (GstClockTime) of the value change
* @param value the corresponding value
*/
public TimedValue(long timestamp, double value) {
this.timestamp = timestamp;
this.value = value;
}

@Override
public int hashCode() {
int hash = 7;
hash = 37 * hash + (int) (this.timestamp ^ (this.timestamp >>> 32));
hash = 37 * hash + (int) (Double.doubleToLongBits(this.value) ^ (Double.doubleToLongBits(this.value) >>> 32));
return hash;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TimedValue other = (TimedValue) obj;
if (this.timestamp != other.timestamp) {
return false;
}
if (Double.doubleToLongBits(this.value) != Double.doubleToLongBits(other.value)) {
return false;
}
return true;
}

@Override
public String toString() {
return "TimedValue{" + "timestamp=" + timestamp + ", value=" + value + '}';
}

}

protected static class Handle extends GstObject.Handle {

public Handle(GstControlSourcePtr ptr, boolean ownsHandle) {
super(ptr, ownsHandle);
}

@Override
protected GstControlSourcePtr getPointer() {
return (GstControlSourcePtr) super.getPointer();
}

}

}
2 changes: 2 additions & 0 deletions src/org/freedesktop/gstreamer/Gst.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.stream.Stream;
import org.freedesktop.gstreamer.controller.Controllers;
import org.freedesktop.gstreamer.elements.Elements;
import org.freedesktop.gstreamer.glib.GLib;
import org.freedesktop.gstreamer.glib.GMainContext;
Expand Down Expand Up @@ -666,6 +667,7 @@ private static synchronized void loadAllClasses() {
new Event.Types(),
new Message.Types(),
new Query.Types(),
new Controllers(),
new Elements(),
new WebRTC.Types())
.flatMap(NativeObject.TypeProvider::types)
Expand Down
Loading

0 comments on commit 2ef6e3d

Please sign in to comment.