Custom Event Handling in GStreamer 1.0 - events

I am having a hard time wrapping my head around GStreamer event sending and handling. I understand the process, but can not achieve my desired outcome. I am developing a series of GStreamer plugins in tandem with a GStreamer main application. I have 3 plugins my_src which inherits from GstPushSrc, my_transform which inherits from GstBaseTransform and my_sink which inherits from GstBaseSink, and a main application my_app.
I am trying to send a custom event from my_app to all elements in the pipeline telling them to reconfigure the processing parameters. This is different from GST_EVENT_RECONFIGURE because it does not involve any renegotiation of caps. I am sending the event from my_app with the following:
// my_app.c
GstStructure *reconfigureStructure = gst_structure_new("reconfigure", NULL);
GstEvent *reconfigureEvent = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM,
reconfigureStructure);
gst_element_send_event(pipeline, reconfigureEvent);
I have overridden the GstBaseSrc event() method as follows:
// my_src.c
static gboolean my_src_event(GstBaseSrc *bs, GstEvent *event);
static void
my_src_class_init(MySrcClass *msc)
{
GstBaseSrcClass *bsc = GST_BASE_SRC_CLASS(msc);
bsc->event = my_src_event;
}
static gboolean
my_src_event(GstBaseSrc *bs, GstEvent *event)
{
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_CUSTOM_DOWNSTREAM: {
const GstStructure *structure = gst_event_get_structure(event);
if (gst_structure_has_name(structure, "reconfigure")) {
g_print("MY SRC RECONFIGURE\n");
// do reconfigure things
}
break;
}
}
return GST_BASE_SRC_CLASS(parent_class)->event(bs, event);
}
Similarly, I have overridden the GstBaseSink event handler as follows:
// my_sink.c
static gboolean my_sink_event(GstBaseSink *bs, GstEvent *event);
static void
my_sink_class_init(MySinkClass *msc)
{
GstBaseSinkClass *bsc = GST_BASE_SINK_CLASS(msc);
bsc->event = my_sink_event;
}
static gboolean
my_sink_event(GstBaseSink *bs, GstEvent *event)
{
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_CUSTOM_DOWNSTREAM: {
const GstStructure *structure = gst_event_get_structure(event);
if (gst_structure_has_name(structure, "reconfigure")) {
g_print("MY SINK RECONFIGURE\n");
// do reconfigure things
}
break;
}
}
return GST_BASE_SINK_CLASS(parent_class)->event(bs, event);
}
Lastly, I have overridden the GstBaseTransform sink_event() method as follows:
// my_transform.c
static gboolean my_transform_sink_event(GstBaseTransform *bt, GstEvent *event);
static void
my_transform_class_init(MyTransformClass *mtc)
{
GstBaseTransformClass *btc = GST_BASE_TRANDFORM_CLASS(mtc);
btc->sink_event = my_transform_sink_event;
}
static gboolean
my_transform_sink_event(GstBaseTransfor *bt, GstEvent *event)
{
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_CUSTOM_DOWNSTREAM: {
const GstStructure *structure = gst_event_get_structure(event);
if (gst_structure_has_name(structure, "reconfigure")) {
g_print("MY TRANSFORM RECONFIGURE\n");
// do reconfigure things
}
break;
}
}
return GST_BASE_TRANSFORM_CLASS(parent_class)->sink_event(bt, event);
}
When I run my_app I would expect the output to be:
MY SRC RECONFIGURE
MY TRANSFORM RECONFIGURE
MY SINK RECONFIGURE
However, I am only getting:
MY SINK RECONFIGURE
Any ideas what I am doing wrong here?

Related

Gluon Mobile Charm 5.0 Cannot Hide Layer

I have a loading gif for all backend requests. Prior to Charm 5.0.0, it worked fine in which the loading gif would show, backend would finish what it needed to, then the loading gif would be hidden. Now, the loading gif shows, but it doesn't hide.
addLayerFactory(LOADING_GIF, () -> new Layer() {
private final Node root;
private final double sizeX = getGlassPane().getWidth();
private final double sizeY = getGlassPane().getHeight();
{
ProgressIndicator loading = new ProgressIndicator();
loading.setRadius(50);
loading.setStyle("-fx-text-fill:white");
root = new StackPane(loading);
root.setStyle("-fx-background-color: rgba(0,0,0,0);");
getChildren().add(root);
this.setStyle("-fx-background-color:rgba(255,255,255,0.7)");
this.setShowTransitionFactory(v -> {
FadeInTransition ft = new FadeInTransition(v);
ft.setRate(2);
return ft;
});
}
#Override
public void show() {
this.setBackgroundFade(0.0);
super.show();
Layer pane = this;
Task<Integer> task = new Task<Integer>() {
#Override
protected Integer call() throws Exception {
int iterations = 0;
int max = DataService.readOutTime / 1000;
while (iterations <= max) {
Thread.sleep(1000);
iterations++;
}
Platform.runLater(new Runnable() {
#Override
public void run() {
if (pane.isVisible()) {
pane.setShowTransitionFactory(v -> {
FadeOutTransition ft = new FadeOutTransition(v);
ft.setRate(2);
return ft;
});
pane.hide();
MobileApplication.getInstance().showMessage("There was an error in sending your data.");
}
}
});
return iterations;
}
};
Thread thread = new Thread(task);
thread.start();
}
#Override
public void hide() {
this.setBackgroundFade(0.0);
super.hide();
}
#Override
public void layoutChildren() {
root.setVisible(isShowing());
if (!isShowing()) {
return;
}
root.resize(sizeX, sizeY);
resizeRelocate((getGlassPane().getWidth() - sizeX) / 2, (getGlassPane().getHeight() - sizeY) / 2, sizeX, sizeY);
}
});
I have a couple of utility methods that show and hide the loader:
public void showLoader() {
MobileApplication.getInstance().showLayer(App.LOADING_GIF);
}
public void hideLoader() {
MobileApplication.getInstance().hideLayer(App.LOADING_GIF);
}
Interestingly, the custom timeout I created (to hide the loader in case there is a stall in the backend) doesn't hide the layer either.
There is an issue with your code: you are overriding Layer::layoutChildren, but you are not calling super.layoutChildren().
If you check the JavaDoc:
Override this method to add the layout logic for your layer. Care should be taken to call this method in overriden methods for proper functioning of the Layer.
This means that you are getting rid of some important parts of the Layer control, such as animations, events and visibility control.
This should work:
#Override
public void layoutChildren() {
super.layoutChildren();
root.setVisible(isShowing());
if (!isShowing()) {
return;
}
root.resize(sizeX, sizeY);
resizeRelocate(getGlassPane().getWidth() - sizeX) / 2, getGlassPane().getHeight() - sizeY) / 2, sizeX, sizeY);
}
On a side note, for the hide transition, you should use setHideTransitionFactory.
So this is what I have done to solve this. From the Gluon Docs on the hide() method:
If this layer is showing, calling this method will hide it. If a hide transition is present, it is played before hiding the Layer. Care should be taken to call this only once LifecycleEvent.SHOWN has been fired.
Thus, I was realizing that the response from the backend was coming before the layer was fully shown. Thus, I modified the overridden hide() method as follows:
#Override
public void hide() {
if (this.isShowing()) {
this.setOnShown(e -> {
this.setBackgroundFade(0.0);
super.hide();
});
} else {
super.hide();
}
}
So if the layer is still in LifecycleEvent.SHOWING mode when being told to hide, make sure that it hides when it is shown. Otherwise it is already shown so hide it.

How can i use VALA delegates in GTK3 button callback?

I'm trying to understand Vala delegates with Gtk3.
I tested callback and lambda with no problem.
I wanna test a delegate callback, here my code :
using Gtk;
delegate void typeDelegate(Button button);
int main (string[] args) {
Gtk.init (ref args);
typeDelegate cb = cbLabelf;
var window = new Window ();
window.title = "First GTK+ Program";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
var button = new Button.with_label ("Click me!");
//button.clicked.connect (cb);
//button.clicked+= cb;
button.clicked.connect+=cb;
window.add (button);
window.show_all ();
Gtk.main ();
return 0;
}
void cbLabelf(Button button)
{
button.label = "tank yu";
}
I also red generated C code ( when i use lambda) to understand.
Here the compil error :
GTKsampleDelegate.vala:20.5-20.30: error: Arithmetic operation not supported for types Gtk.Button.clicked.connect' andtypeDelegate'
button.clicked.connect+=cb;
Well,
Seems that you want to get the intrinsic variable that holds the instance that emitted the signal, I find strange that vala doesn't let you use a delegate variable to obtain it via parameter, yet, you can use one of the forms below: using no delegation variable (A) or bypassing the error with a closure (B).
public class FooSignalClass : Object {
/* Gtk Button.clicked signal has the void f(void) signature */
public signal void on_foo ();
public void foo() {
on_foo();
}
}
public delegate void FooSignalFunc (FooSignalClass fooer);
void on_foo_handler (FooSignalClass fooer) {
long fooer_memory_address = (long)fooer;
GLib.message(#"fooer exists? $(fooer!=null).");
GLib.message(#"address=$fooer_memory_address.");
}
int main () {
var foo_signal = new FooSignalClass();
long fooer_memory_address = (long)foo_signal;
GLib.message(#"foo_signal address=$fooer_memory_address.");
/* Option A: Connect directly without the delegate variable */
foo_signal.on_foo.connect(on_foo_handler);
/* Option B: You cant use a delegate directly, bypass it with a closure */
FooSignalFunc func = on_foo_handler;
foo_signal.on_foo.connect((instance) => {
func(instance);
});
foo_signal.foo();
return 0;
}

Pebble AppMessage crash when sending string containing accents from the phone to the watch

I'm building an API based application. I use the Pebble.SendAppMessage function to send data from the API to the watch. Each time I try to send data containing accentued characters and log them, the console print this following empty message:
[xx:xx:xx] javascript>
and no more interaction between the phone and the watch will work.
I first tried to encode each API data to UTF8 encoding but the crash still appears.
Can we send strings containing accents using the Pebble.SendAppMessage function? What exactly did I miss?
C code :
#include <pebble.h>
static Window *window;
static TextLayer *text_layer;
static void message_provider(DictionaryIterator* iterator, void* context) {
Tuple* tuple = dict_find(iterator, 0);
text_layer_set_text(text_layer, tuple->value->cstring);
}
static void window_load(Window *window) {
Layer *window_layer = window_get_root_layer(window);
GRect bounds = layer_get_bounds(window_layer);
text_layer = text_layer_create((GRect) { .origin = { 0, 72 }, .size = { bounds.size.w, 20 } });
text_layer_set_text(text_layer, "Loading...");
text_layer_set_text_alignment(text_layer, GTextAlignmentCenter);
layer_add_child(window_layer, text_layer_get_layer(text_layer));
}
static void window_unload(Window *window) {
text_layer_destroy(text_layer);
}
static void init(void) {
window = window_create();
window_set_window_handlers(window, (WindowHandlers) {
.load = window_load,
.unload = window_unload,
});
const bool animated = true;
window_stack_push(window, animated);
app_message_register_inbox_received(message_provider);
app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
}
static void deinit(void) {
window_destroy(window);
}
int main(void) {
init();
app_event_loop();
deinit();
}
JS code :
Pebble.addEventListener("ready", function() {
Pebble.sendAppMessage({"dummy" : "GĂ©rard example is always the best."}, function() {
console.log("message sent successfully !");
}, function() {
console.log("Cannot send message with accent.");
});
});

Can mousePressed be defined within a class?

I am trying to create a class called InputManager to handle mouse events. This requires that mousePressed be contained within the InputManager class.
like so
class InputManager{
void mousePressed(){
print(hit);
}
}
problem is, that doesn't work. mousePressed() only seems to work when it's outside the class.
How can I get these functions nicely contained in a class?
Try this:
in main sketch:
InputManager im;
void setup() {
im = new InputManager(this);
registerMethod("mouseEvent", im);
}
in InputManager Class:
class InputManager {
void mousePressed(MouseEvent e) {
// mousepressed handling code here...
}
void mouseEvent(MouseEvent e) {
switch(e.getAction()) {
case (MouseEvent.PRESS) :
mousePressed();
break;
case (MouseEvent.CLICK) :
mouseClicked();
break;
// other mouse events cases here...
}
}
}
Once you registered InputManger mouseEvent in PApplet you don't need to call it and it will be called each loop at the end of draw().
Most certainly, but you are responsible for ensuring it gets called:
interface P5EventClass {
void mousePressed();
void mouseMoved();
// ...
}
class InputManager implements P5EventClass {
// we MUST implement mousePressed, and any other interface method
void mousePressed() {
// do things here
}
}
// we're going to hand off all events to things in this list
ArrayList<P5EventClass> eventlisteners = new ArrayList<P5EventClass>();
void setup() {
// bind at least one input manager, but maybe more later on.
eventlisteners.add(new InputManager());
}
void draw() {
// ...
}
void mousePressed() {
// instead of handling input globally, we let
// the event handling obejct(s) take care of it
for(P5EventClass p5ec: eventlisteners) {
p5ec.mousePressed();
}
}
I would personally make it a bit tighter by also passing the event variables explicitly, so "void mousePressed(int x, int y);" in the interface and then calling "p5ec.mousePressed(mouseX, mouseY);" in the sketch body, simply because relying on globals rather than local variables makes your code prone to concurrency bugs.
The easiest way to do so would be:
class InputManager{
void mousePressed(){
print(hit);
}
}
InputManager im = new InputManager();
void setup() {
// ...
}
void draw() {
// ...
}
void mousePressed() {
im.mousePressed();
}
This should solve any problems you were having with variable scoping in your class.
Note: In the class, it doesn't even have to be named mousePressed, you can name it anything you wish, as long as you call it inside of the main mousePressed method.

C# like events in D programming language

I recently finished a 6-month internship at a company that uses C# for the most part of their programming. During this time I first used and got accustomed to the C# way of doing events. Like shown below:
acc.AccountBalanceLow += new AccountBalanceDelegate(atm.AccountToLow);
acc.AccountBalanceLow +=new AccountBalanceDelegate(atm.AccountToLowAgain);
Does D support such constructs? I'd imagine one could be created by the user by using operator overloading, but I'm not entirely sure. If it's not possible what would then be a common excepted way of doing it then?
The equivalent construct in D is to use Signals and Slots. This is a different means of implementing the Observer Pattern, which is effectively what a C# event does.
D (and C++) use an analogous pattern called signals and slots.
If you're feeling the need to use the C# style-events instead of signals and slots, they're extremely simple to implement:
module fluidity.core.event;
class Event {
alias void delegate(EventArgs) handler_t;
handler_t[] handlers;
Object owner;
this() {}
this(Object o) { owner = o; }
void attach(handler_t handler) {
if (handler)
handlers ~= handler;
}
void detach(handler_t handler) {
int i = -1;
foreach (j, h; handlers)
{
if (h is handler)
{
i = j;
break;
}
}
if (i > -1)
handlers = handlers[0..i] ~ handlers[i+1..$];
}
void raise() { raise(new EventArgs(owner)); }
void raise(EventArgs e) {
// call all handlers
foreach (handler; handlers)
{
if (handler)
handler(e);
}
}
void opAddAssign(handler_t handler) {
attach(handler);
}
void opSubAssign(handler_t handler) {
detach(handler);
}
}
class EventArgs {
Object source;
bool handled;
void handle() { handled = true; }
this() {}
this(Object s) {
source = s;
}
}
Here is an example of c# style events using signals, slots, and a templates:
events.d:
import std.signals;
class Event(T...){
mixin Signal!(T);
void broadcast(T args){
emit(args);
}
void opAddAssign(slot_t slot){
connect(slot);
}
void opSubAssign(slot_t slot) {
disconnect(slot);
}
}
declaration:
public Event!(int) onSomeEventOfInt;
public Event!(string, int) onSomeEventOfStringAndInt;
instantiation:
this.onSomeEventOfInt = new Event!(int)();
this.onSomeEventOfStringAndInt = new Event!(string, int)();
fire event:
int i = 4;
string str = "hello";
this.onSomeEventOfInt.broadcast(i);
this.onSomeEventOfStringAndInt.broadcast(str, 4);
observer registration:
obj1.onSomeEventOfInt += &handleEventOfInt
obj1.onSomeEventOfStringAndInt += &handleEventOfStringAndInt
void handleEventOfInt(int g)
{ /*do something */ }
void handleEventOfStringAndInt(string str, int g)
{ /*do something */ }
Check out DFL's event system. It works EXACTLY the same way as C# .NET.
DFL Event Example
Download DFL, grab the events module and use it the way you like. I modified it to use variadic template arguments. This gives maximum flexibility.
http://www.dprogramming.com/dfl098.zip

Resources