How do I detect .connect_pad_added() template = video_%u? - rust

Using the gstreamer Rust bindings, how can I test if a sometimes pad that has been added is from template video_%u or audio_%u?
For example, using qtdemuxm, the following pad added is called once for video and once for audio
.connect_pad_added(move |demux, src_pad| {
according to the binding docs it seems
get_property_name_template(&self)
but this fails
.connect_pad_added(move |demux, src_pad| {
let templateName = get_property_name_template(&src_pad);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
a more manual way is to get the name then if else, but is there a more direct method?
println!(
"Received new pad {}",
src_pad.get_name()
);
I have also tried matching the pad form a template
.connect_pad_created('video_%u', src_pad{ ....
but I could not find a way to match the string of the template.

You have at least two options here:
You check if the pad name starts with audio_ or video_. You can get the name via get_name()
You get the pad template from the pad via get_pad_template() and then check the name template via get_property_name_template()
Ideally you would however not depend on template names (unless you explicitly work with a specific element factory, like qtdemux here) but instead look at the caps on the pad via get_current_caps() and if they are not available yet get notified once they change via connect_notify(Some("caps"), ...).

Related

LUA (ESP8266) How to call/enter a module command from a string

Please forgive me, I don't even know if what I am asking is the correct terminology.
So...here goes.
I built a custom firmware of Nodemcu Dali ( from Hackerspace Stutgart.) This includes a dali lighting control "flavour" as they refer to. I had to modify it to work with the most recent LUA version. Anyway that works and the MODULE is built into the firmware.
From the LUA commandline / Interpretor (Esplorer interface, I can call the module and it all works fine.
To use the module you enter:
dali.arc(address_Mode,0,parameter)
or
dali.send(Address_Mode,Command,Address,parameter)
Address_mode can be: dali.SLAVE , dali.GROUP
Command can be dali.UP_200MS , dali.IMMEDIATE_OFF , dali.GO_TO_SCENE --... about 50 commands.
An Example command to send the light level 128 to all drivers would be as follows:
dali.arc(dali.BROADCAST,0,128) -- direct arc mode ( all lights,*ignored*,50% dimmed)
I want to use MQTT to control this thing.
I could use MQTT topics:
dali_topic/arc_broadcast -- for dali.arc(dali.BROADCAST,var1,var2)
dali_topic/group -- for dali.arc(dali.GROUP,var1,var2)
dali_topic/slave -- for dali.arc(dali.SLAVE,var1,var2)
and my payload string would only have to 2 variables,comma seperated eg. 0,128.
This I can all do day long but now I want to make it "better"...
I want to be able to rather send the message " dali.BROADCAST,0,128" which the code should then sort into a table with elements:
table[1] = dali.BROADCAST
table[2] = 0
table[3] = 128
and call dali.arc(table[1],table[2],table[3])
The table creation works,but I cannot get dali.BROADCAST passed to the module /function? call. First off because it is a string and second because it cannot be converted to a number or whatever substitute is required.
If this can be done them the Command field could aslo be sent with the MQTT payload rather than needing 50 MQTT topics.
I suppose I could also just try a lot of if statements or search a lookup table, but perhaps there is a simple way to just insert the command field in to function/module call?
Any assistance greatly appreciated
Edit here is some LUA output:
table ={"dali.BROADCAST",0,128}
dali.arc(table[1],table[2],table[3])
result:
Lua error: stdin:1: bad argument #1 to 'arc' (number expected, got boolean)
since if you print("dali.BROADCAST") you get nil
However
table[4] = dali.BROADCAST
dali.arc(table[4],table[2],table[3])
result works fine.
print( type(dali.BROADCAST ))
gives number
so how to pass my mqtt string dali.BROADCAST which is received as "dali.BROADCAST" and convert it to just dali.BROADCAST?
note I am not sending "" the message is however sent by MQTT as a CSV string.
From the Firmware source for the dali module.. in the module folder: dali.c
LROT_BEGIN(dali, NULL, 0)
LROT_FUNCENTRY( setup, dali_setup )
LROT_FUNCENTRY( arc, dali_arc )
LROT_FUNCENTRY( send, dali_send )
LROT_NUMENTRY( BROADCAST, BROADCAST )
LROT_NUMENTRY( SLAVE, SLAVE )
LROT_NUMENTRY( GROUP, GROUP )
LROT_NUMENTRY( IMMEDIATE_OFF, DALI_IMMEDIATE_OFF)
LROT_NUMENTRY( GO_TO_SCENE, DALI_GO_TO_SCENE)
The shackspace github link is the correct one, it is simply based on LUA1.45 or something low like that. I only had to modify dali.c in Modules to work with the lastest LUA.
The relevant dali files in the firmware is located in
app/modules
app/include
app/dali
folders
EDIT: Thinking about it, you probably always end up indexing dali, in which case you can do so directly by just structuring your table like this:
table[1] = "arc"
table[2] = "BROADCAST"
table[3] = 0
table[4] = 128
This way you can get to dali.BROADCAST by doing dali[table[2]] and to dali.arc by doing dali[table[1]].
HINT: You should probably still keep a whitelist of what is allowed where because someone could send any string and your program shouldn't just blindly index the dali table with that and return it.
You probably want something like this
Here's the relevant code:
function deepindex(tab, path)
if type(path)~="string" then
return nil, "path is not a string"
end
local index, rest = path:match("^%.?([%a%d]+)(.*)")
if not index then
index, rest = path:match("^%[(%d+)%](.*)")
index = tonumber(index)
end
if index then
if #rest>0 then
if tab[index] then
return deepindex(tab[index], rest)
else
return nil, "full path not present in table"
end
else
return tab[index]
end
else
return nil, "malformed index-path string"
end
end
Homework: this function also works with [] indexing for numbers, which you don't need. It should be easy to simplify the function to only do string-indexing with .
You would use that on the global environment to index it with a single string:
deepindex(_G, "dali.BROADCAST")
-- Which is the same as
_G.dali.BROADCAST
-- And, unless dali is a local, also
dali.BROADCAST
Keep in mind though, that this lets you remote-index _G with anything, which is a huge security nightmare. Better do this:
local whitelist = {}
whitelist.dali = dali
deepindex(whitelist, "dali.BROADCAST") -- this works
deepindex(whitelist, "some.evil.submodule") -- This does nothing
Was looking for a Wiki entry with more details, but I found none. If you happen to know where documentation is that specifies more about the available Lua commands, please include a link in your question.
It appears that there may be other functions to approach the same outcome, but I'm not certain how they are worded in your particular build.
https://github.com/shackspace/nodemcu-firmware-dali/blob/master/app/dali/dali_encode.c
What's returned when you print( type( dali.BROADCAST )) ?
I was guessing it might be raw C userdata, the specific case-switch for that arc command, however, I just found a similar Lua project that lists it as hexadecimal 255
https://github.com/a-lurker/Vera-Plugin-DALI-Planet/blob/master/Luup_device/L_DaliPlanet1.lua
Yea, it's likely just sending hexadecimal numbers.
https://en.wikipedia.org/wiki/Digital_Addressable_Lighting_Interface
try sending dali.arc( 0xFF, 0x00, 0x80 )
or dali.arc( 0xFE, 0x80 )
They make it sound like '1111 1110' ( 0xFE ) is directly followed by the brightness value, so that second command might light.
I'm not sure why it doesn't appear to be sending the correct codes when you place them in a table. What you've written appears to be correct, but it's likely a one-way broadcast, so you don't receive back any error messages...
If you can't get the arc command to work with tables, possibly you'll have better luck with the dali.send() command. Might just be a flaw in that app. If you can't get it resolved, submit a bug report to their GitHub page.

How do you iterate within an Azure Logic App Response component

I have an Azure MS SQL Server component that is returning multiple rows and feeding into a Response component.
The Body of the Response component looks like this:
{
"MyID":"#{body('Get_rows')['value'][1]['Id']}"
}
I can make the number in the bracket 0 and get the first result. I can make it 1 and get the second result. But what I am trying to find is the syntax to loop through all the results that are passed so that it would effectively provide the following (assuming there were 2 results total:
{
"MyID":"#{body('Get_rows')['value'][0]['Id']}"
}
{
"MyID":"#{body('Get_rows')['value'][1]['Id']}"
}
Thanks in advance for advice on where to find the correct syntax or for examples of correct syntax.
It took me a while but figured out that I needed to do two things:
I had to run a for each after the Get Rows and within that I created a Data Operations - Compose component. Within that I was able to create a single JSON object with all the parameters.
From there I used #outputs command as shown below in the Body of the Response and it inserted the array brackets and the commas to delimit the Compose entries automagically.
Here is what the code in the Body of the Response looks like:
#outputs('Compose')
Note that 'Compose' is the default name given to the first Compose component you place in the application.

How to use MarkLogic search options by name

I'm using the ML9 Java API to upload a search options file to the DB with a name that I can use later in my search call. I would now like to write an xquery transform to highlight the query-matches in a set of elements in the response. Standard snippets won't work for me since they only bring back the fields in which there are matches and because they may not bring back the complete field value, but only the immediate context of the match.
So I want to use the cts:highlight function in a custom transform and want to pass to it the name of the options that I have uploaded into the DB. My question is how I can best get the options element from the DB using the name passed in to the transform method. I want to use this to construct the cts:query that I can pass in to the cts:highlight call as in:
let $query := cts:query(search:parse($query-string, $options))
let $result := cts:highlight($doc, $query, <markup>{$cts:text}
</markup>)
I was thinking I could pass in the query-string and the name of the pre-loaded options and use these to construct the cts:query, but don't know how to get the options from the name.
I found a way to avoid having to read the options. Setting the option 'return-query' to true adds a search:query node to the search:response which is passed to the transform method as the document-node. I'm then able to get this directly in the transform method to use in cts:highlight as:
let $query := cts:query($response/search:response/search:query/*[1])
The options are stored in the modules database associated with your REST instance. You could theoretically dig them out, though that would be relying on an implementation detail (the URI).
You might look into a combination of extract-document-data, as Sam mentioned, plus a search result transform, rather than the heavier approach of doing your own search through what I'd guess is a read transform.
Another alternative might be a custom snippeter that you pull into your options via transform-results. See http://docs.marklogic.com/guide/search-dev/query-options#id_58295.

Can I store anything I want in com.google.android.gms.cast.MediaMetadata?

The documentation from google is giving a 404 error right now so I can't read it.
It appears that I can put any strings I want into the MediaMetadata but when I go to retrieve them from the VCM (VideoCastManager) they aren't there. Is there any way to add custom data to the MediaMetadata?
I want this so I can have more information about the video I am playing when the application reconnects.
Thanks.
I was having the same issue....and I found the cause to be how I was constructing my MediaMetaData object in my sender app's code.
Constructing the MediaMetadata object in your receiver app's code with the constant MediaMetadata.MEDIA_TYPE_MOVIE (as is done in the CastCompanionLibrary sample) won't let you store anything with .putString(key,value) other than with the keys MediaMetadata.KEY_TITLE and MediaMetadata.KEY_SUBTITLE.
Here's what I've found....
Since I'm playing video on the chromecast, I assumed the best way to construct the MediaMetadata object was to use the MediaMetadata.MEDIA_TYPE_MOVIE constant like so :
MediaMetadata castMetaData = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
Then....I attempted to send the following data with the MediaMetadata object:
castMetaData.putString(MediaMetadata.KEY_TITLE,"videoTitle");
castMetaData.putString(MediaMetadata.KEY_SUBTITLE,"videoSubTitle");
castMetaData.putString(MediaMetadata.KEY_ARTIST,"videoArtistName");
After sending this MediaMetadata object to the receiver (ensuring that the three KEYs and their corresponding values were in-tact) and video began to play, I attempted a call to retrieve the video's metadata from the receiver with :
MediaMetadata receiverMetadata = videoCastManager.getRemoteMediaInformation().getMetaData();
This returned a MediaMetadata object, but the MediaMetadata.KEY_ARTIST mapping was no where to be found.
After changing the MediaMetadata construct parameter to MediaMetadata.MEDIA_TYPE_GENERIC like so I was able to send more metadata in the MediaMetadata object:
MediaMetadata castMetaData = new MediaMetadata(MediaMetadata.MEDIA_TYPE_GENERIC);
Note
I don't know if constructing the MediaMetadata object with MediaMetadata.MEDIA_TYPE_GENERIC is OK when the actual task is to play video.
What is VCM? You can add any pair of key/values to the MediaMetadat, use one of the variations of put*() such as putInt(key,value), putString(key, value), etc. Then retrieve them by corresponding get*() methods. On your receiver side, you'll have a JSON with those key/value pairs so you can easily retrieve them there too.

Storage in LWUIT

Please can someone give me a small sample of how to use the Storage class in LWUIT? I have tried implementing by emulating the system used in the Recipe Hands-on-Lab, but my application does not need to have multiple objects, as it is within the sample.
Recipe sample allows user to add more and more samples, but all I want to do is add ONE entry of information.
Also how do I retrieve the info stored?
com.sun.lwuit.io.Storage.init("MobileApplication1");
if(com.sun.lwuit.io.Storage.isInitialized()) {
com.sun.lwuit.io.Storage.getInstance().writeObject("MobileApplication1","My first string");
String myStr = (String)com.sun.lwuit.io.Storage.getInstance().readObject("MobileApplication1");
System.out.println(myStr);
} else {
System.out.println("Storage not initialized");
}
The above code will create a storage of name 'MobileApplication1', add an object 'My first string' and reads the string.
You can use J2ME record store as well and your record store will always have only 1 record.

Resources