Problems with Android MediaRecorder JNI (Delphi) - java

I am using RAD Studio 10.2 Tokyo and am programming in Delphi.
I am having general problems with a Java object using the JNI libraries.
What I am trying to do is find the maximum audio amplitude of an Android audio source between button presses.
Here is the code that I am using.
var
Form1: TForm1;
Recorder: JMediaRecorder;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not assigned(Recorder) then
begin
Recorder:= TJMediaRecorder.Create();
Recorder.setAudioSource(1);
Recorder.setOutputFormat(1);
Recorder.setAudioEncoder(1);
Recorder.setOutputFile(TPath.GetTempPath+'/test');
Recorder.prepare();
Recorder.start();
end;
Label1.Text:=IntToStr(Recorder.getMaxAmplitude());
end;
This appears to generate multiple issues.
Issue #1:
Although I am aware that in java the Media recorder settings should look something like
Recorder.setAudioSource(MediaRecorder.AudioSource.MIC).
That is not something that I can enter in RAD Studio. I took a look at the API and found that that is supposed to mean an integer of 1. The problem is that it gives me an error saying that it can't find an audio source.
Issue #2:
I need to set a path for the file using
Recorder.setOutputFile()
The problem with this is that it only accepts JStrings as input. I have looked all over the place and found a few people who use
StringToJString('my super cool string')
I think this is a part of a library that I am unaware of though because it doesn't work when I use it.
If you know of another way to get an amplitude reading off an Android audio source I would also accept that as an answer as that is the overall problem I am trying to solve.

In general, within the Delphi Android JNI framework:
Java class types are represented in Delphi using classes that are prefixed with TJ, and Java object instances are represented in Delphi using interfaces that are prefixed with J.
nested Java classes are represented by Delphi classes and interfaces that are named after the parent class name followed by _ followed by the nested class name.
Java static constants/fields/properties/methods are represented in Delphi as sub-properties/methods of a special JavaClass class property.
So, in your case:
the Java MediaRecorder class is represented by the TJMediaRecorder class and JMediaRecorder interface.
the Java MediaRecorder.AudioSource class is represented by the TJMediaRecorder_AudioSource class and JMediaRecorder_AudioSource interface.
the Java MediaRecorder.AudioSource.MIC constant is represented by the TJMediaRecorder_AudioSource.JavaClass.MIC class property:
Recorder.setAudioSource(TJMediaRecorder_AudioSource.JavaClass.MIC);
The same thing applies to the MediaRecorder.setOutputFormat() and MediaRecorder.setAudioEncoder() methods:
Recorder.setOutputFormat(TJMediaRecorder_OutputFormat.JavaClass.THREE_GPP);
Recorder.setAudioEncoder(TJMediaRecorder_AudioEncoder.JavaClass.AMR_NB);
As for strings, JNI knows nothing about Delphi strings, so you must use StringToJString() to convert Delphi strings to JNI strings, and use JStringToString() to convert JNI strings to Delphi strings. Both functions are in the Delphi RTL, specifically in the Androidapi.Helpers unit (XE6+) or Androidapi.JNI.JavaTypes unit (XE5), depending on which version of Delphi you are using.
Recorder.setOutputFile(StringToJString(TPath.Combine(TPath.GetTempPath, 'test')));

Related

Can I use java library of commons math in kotlin language?

I had seen forums and questions that can be used kotlin in java but, with respect to my question is that I want to use the apache math commons library ("which is only available in java") within kotlin. My project is in intellij idea and I have imported the library correctly, I show you how it is written in java
import org.apache.commons.math3.distribution
NormalDistribution normalDistribution = new NormalDistribution(10, 3);
double randomValue = normalDistribution.sample();
```
A class is a class, regardless of if it's defined in Java or Kotlin. For the most part, this means you just do the Kotlin thing in Kotlin and the Java thing in Java, regardless of where the class you're using is defined. There are exceptions, like for static methods, but most stuff "just works".
I expect, knowing nothing about the NormalDistribution class, that this will work:
val normalDistribution = NormalDistribution(10.0, 3.0);
val randomValue = normalDistribution.sample();
Ok, so I was wrong initially. I had to change my literals above from (10, 3) to (10.0, 3.0). Here's a difference between Java and Kotlin. Kotlin doesn't do automatic numeric type promotion. So while I could use Integer literals for the equivalent Java code, in Kotlin, I had to use Double literals. But my IDE showed me this right away, including a tooltip message that told me just what was wrong. And this is a Kotlin thing, not a Java thing. The same thing would happen if I tried to call a method defined in Kotlin taking doubles as parameters, and I tried to pass it integers. This had nothing to do with which language NormalDistribution is defined in. After that exercise, I can say for sure that this Kotlin code works fine.
Maybe the issue is more that you just don't know Kotlin very well yet. Part of learning Kotlin is realizing how much of a non-issue it is to use Java classes in Kotlin code.

GCC/LD Linking mangled symbols not recognized by JNA

Odd question here not quite sure how to ask it.
I am writing some JNA bindings for a proprietary shared library.
the library api has several functions named things like km_open, km_close, etc.
In c, these functions are defined in the header file as such:
Komodo km_open (
int port_number
);
int km_close (
Komodo komodo
);
and in Java i made JNA bindings for them defined like this:
public abstract Komodo km_open(int port_number);
public abstract int km_close(Komodo komodo);
but JNA fails to find these symbols in the library.
When I dump the symbols in the binary
i find the following:
0000000000008e20 g DF .text 0000000000000005 Base net_km_open
0000000000007410 g DF .text 0000000000000005 Base c_km_open
0000000000008e40 g DF .text 0000000000000005 Base net_km_close
0000000000007430 g DF .text 0000000000000005 Base c_km_close
I am guessing that because this library is meant to be used by both .net and standalone c applications that these names are mangled to provide alternative versions of the function. and yet I cannot find anything in the demo applications source code that maps the name c_km_open to km_open. yet it compiles in GCC and the code works. How do these symbols get resolved when linking/loading the binary and does JNA have a method of doing the same thing? Currently I can get the JNA bindings to work if I modify the bindings like this:
public abstract Komodo c_km_open(int port_number);
public abstract int c_km_close(Komodo komodo);
which is an acceptable workaround I just want to understand what is going on in the background here.
Nevermind, I found the answer, it was kind of tricky, but instead of linking against the .so library file itself, the makefile generated a piece of object code by the same name as the .so library which defined wrapper methods that dynamically loaded the "c_" functions. they then linked to that piece of object code instead of the library. it didn't come up in a search because it was a generated file.
The solution in JNA is then to simply mimic that behavior by creating a wrapper class with the simplified names that make a callback to the JNA bindings

How to pass List<T> from Java to a C++ std::vector function parameter using JNA

I have a native function :
int NativeFunction(std::vector<MyObject>);
I am loading the Native dll using JNA and I am trying to call this function NativeFunction from Java like:
nativedlljnapointer.NativeFunction(List<MyObject>);
I am however running into "java.lang.IllegalArgumentException: Unsupported argument type ArrayList" exception.
I al tried using java util vector when I am running into the same exception "java.lang.IllegalArgumentException: Unsupported argument type java.util.Vector"
Can someone suggest me how I could pass List from my Java function to the native function which has vector<> as an argument.
Any help will be greatly appreciated.
std::vector and java List are completely different types, it's normal for them not to work.
Furthermore , Is MyObject a C++ defined object or a Java defined object (if you define one in each, they are again, completely different objects ! )?
The best and safest way to communicate via JNI is to use serialization, like you would between any two different environments.
Granted, it takes a bit of extra work, but in the long run you end up with more robust code.

Extracting information from a given C++/Java program using another C/Java program

Can anyone give me some idea of how to extract information from a given C++ or Java program(source code)? The information may be names of classes or names of methods or telling some inheritance relation or class hierarchy,etc.You have to write a c++ or Java program for the same.I have tried and abled to do that but it is not totally correct.Right now what I'm doing is reading the given program line by line and checking for "class" keyword and if I find any such word,it means the word following right after that is name of that class(to extract name of classes).I'm just thinking is there any built in libraries in C or Java which can do this work more efficiently ?And please suggest some simple ideas(not some external libraries or plugins).
If all you want is the names of classes and methods within classes, you can rig a set of regular expressions to pick off various tokens (identifiers, "{", "}", operator, number, string), and a crummy parser (called an "island parser") to recognize the sequence of tokens that make up class declarations and method declarations. (Hint: for Java and C++, make sure you somehow match
corresponding { ... }").
This stunt works for classes and methods because in essence this how real compilers work: they break the input stream into tokens (usually using the compiler-generalization of regexps called "lexer generators"), and then use a parser to determine the actual code structure, and classes and methods are pretty easy to spot in the syntax. (This solution is a kind of clean version of what OP posted).
If you want to any other information form Java or C++ source code (e.g., types of method arguments, etc.) you probably need a tool that actually parses the languages, and builds symbol tables so you have a chance of knowing what the identifiers found in various locations mean.
(EDIT: OP indicated he wants to find out what function calls what other function. He can't do this sensibly without a full language front end (parser+ symbol table as a minimum).
You can get various tools to parse C++ (GCC, Clang, Elsa, ...) and various other tools to parse Java (ANTLR, javacc, ...). You will find that GCC is pretty hard to bend to general tasks, Clang and Elsa less problematic. ANTLR and Javacc will parse Java code but don't AFAIK build symbol tables, so they fall a little flat for general purpose tasks. What you will find is that dealing with a C++ tool will turn out to be completely different than dealing with a Java tool since none of these tools have any common compiler infrastructure.
How you extract class and method names from each of these will vary in detail, but most of them offer some kind of way to climb over a parse tree (and you code some ad hoc match for what you want to find, e.g., class declaration syntax) and/or navigate symbol tables (and spit out symbols marked as "class" or "method" names). How you find the right syntax requires you to know in intimate detail the structure of the tree and code lots of test to match for the proper tree structures.
If you really want to process both languages, and use a single infrastructure to do it, you could consider our DMS Software Reengineering Toolkit. DMS is language agnostic but can be tuned to arbitrary langauges, and then parse those languages, build abstract symbol tables and various kinds of flow analysis. DMS has both full C++ Front end (with a built-in preprocessor and handling C++ in its various forms including the new standard C++11) and a Java Front end handling all dialects of Java up through 1.6 (with 1.7 happening momentarily).
To do OPs (originally stated) task of finding classes and methods, you'd tell DMS to parse the file and then climb over trees or symbol tables, much as for the other tools. You can code an ad hoc tree matcher in DMS, but it easier to write patterns:
pattern match_class_declaration(i: identifier, b: statements): class_declaration
= " class \i { \b } ";
can be used with DMS to match those trees that happen to be class declarations, and will return "i" (and "b" which we don't care about) bound to the correspond subtrees. "i" of course contains the class name you want. Other patterns can be used to recognize other constructs, such as class names that inherit, or implement interfaces, or methods that return some type or methods that return void.
The point is you don't have to know the tree structure in any great detail to use such patterns.
To go further, as OP seems to want to do (e.g build caller/callee information), you'd need to construct control flow graphs, do points-to analysis, etc. DMS provides support for that.
The good news is one infrastructure handles both languages; you can even mix C++ and Java in DMS without it getting anything confused. The more difficult news is that DMS is a fairly complex beast, but that's because it has to handle all the complexities of C++ and Java (as well as many other langauges). Still beats working with two different language parsers with two radically different implementations and thus two complete sets of learning curves.
the question sounds too vague to answer. please elaborate.
from what i could gauge, use Reflection when you are working with Java classes to figure out almost everything about a class and its methods. There are other (static) APIs that you could use on the Class object (if you have that hand). Refer the javadocs for more.
You could try to use some source from compilers, like gcc. They already have all the syntax parsing and preprocessing there, so you could save tons of time.
For compiled Java you could also use bytecode manipulation libraries (like asm).
As you're trying to parse a text file, a shell script based on awk and/or sed would be sufficient. You'll have to define some simple regular expressions based on the languages keywords and syntax to extract the informations you need.
For instance, this regular expression would match most of the class declarations of a C++ source file:
class *([A-Za-z_][A-Za-z_0-9]*) *\{?$
The parenthesis allow you to extract the identifier you're looking for, this is called a capturing group.
If you really want to do it in C/C++/Java, you'll have to find a library that provides regular expressions facilities (Java standard library already provides some). Maybe Boost Regex for a C++ program.
Here's an example building up how to parse a C++ file using the clang (llvm) libraries. Its long and pretty detailed but you should be able to adapt it to do what you need (for C and C++ anyway .. dont know if llvm is any good at handling Java ... and don't know if its easy to adapt that approach for Java).
Not sure about current Java, but C++ is a true nightmare to parse if you want to fully extract semantic information (consider that it took YEARS for the industry to agree 100% on how and if certain construct should have been parsed).
Note that while class name in C++ is easy enough (just remember however that the word class or struct can also be present before a template parameter instead of typename, that you can have "nested classes" and that you can have class "forward declarations") for members things are much harder because member name comes after the type and even understanding what is a type, where the type ends or what is the member name is not trivial... consider
int (*foo)(int x, int y);
Node<Bar, Baz, Allocator<Foo, &Q::operator > >, 12> (*rex)(int);
in the first case the member name is foo, and in the second case member name is rex (note that I'm not sure if the second example is valid C++ code or, supposing it's valid, if common C++ compilers would accept it).
Note that even just understanding where the class member list begins after the class name is not trivial (you have to skip the inheritance list that can include templated classes with parameters that are generic types).
So, giving up with a regular expression (that clearly is not able to parse a type being it a complex recursive entity), the only solution is to use code written by someone else.
For this job (for C++) you can try for example GCC-XML that has been written exactly for this reason (it generates an XML result from parsing C++ source code).

Matlab / Java API callback

I'm designing an API (in Java) and expect to have users accessing the API from Matlab. The problem is that I want the API to provide a piece of functionality like:
javaApi.waitUntilPredicateIsTrue(Predicate<JavaObj> test);
My API (in the background) gets hold of instances of Java Obj (via some mechanism, e.g. polling). I want this API method to block until one of these instances, when passed to the Predicate evaluates to true. If I was calling this API from Java, I'd do:
javaApi.waitUntilPredicateIsTrue(new Predicate<JavaObj>() {
public boolean evaluate(JavaObj jo) {
return "READY".equals(jo.getState());
}
});
You get the idea.
How can this be called from within Matlab? Can I use anonymous inner classes from Matlab? Can I declare a Matlab classdef which extends the interface Predicate (can this cope with the Java generic version)?
That sounds like a tough question. I'm still running R2006b so this may have changed, but it looks like MATLAB will not translate function handles (incl. anonymous functions) and structures into Java objects. I don't know about MATLAB custom classes, since the syntax has changed. Strings, arrays, and cell arrays will translate properly. They don't comment at all on implementing interfaces. (:p :p :p BOO HISS)
edit: just found this page on Matlab Central, it talks about some undocumented interfaces.
Matlab has a much nicer solution than forcing users to create a whole class just to provide a single method. Take a look at their anonymous functions.
Note that anonymous functions in Matlab have odd scoping rules. Make sure you read the "Variables Used in the Expression" section of the linked help page. If you want more traditional lexical scoping, take a look at nested functions.
EDIT:
I am assuming that you will be doing the polling from Matlab, not passing the predicate function to Java. Example:
function waitForPredicate(pred)
while pred
end
end
waitForPredicate(#()javaApi.isMyConditionMet());

Categories

Resources