I work on windows but I am stuck here on Mac. I have the Canon SDK and have built a JNA wrapper over it. It works well on windows and need some help with Mac.
In the sdk, there is a function where one can register a callback function. Basically when an event occurs in camera, it calls the callback function.
On windows, after registering, I need to use User32 to get the event and to dispatch the event by:
private static final User32 lib = User32.INSTANCE;
boolean hasMessage = lib.PeekMessage( msg, null, 0, 0, 1 ); // peek and remove
if( hasMessage ){
lib.TranslateMessage( msg );
lib.DispatchMessage( msg ); //message gets dispatched and hence the callback function is called
}
In the api, I do not find a similar class in Mac. How do I go about this one??
PS: The JNA api for unix is extensive and I could not figure out what to look for. The reference might help
This solution is using the Cocoa framework. Cocoa is deprecated and I am not aware of any other alternative solution. But the below works like charm.
Finally I found the solution using Carbon framework. Here is my MCarbon interface which defines calls I need.
public interface MCarbon extends Library {
MCarbon INSTANCE = (MCarbon) Native.loadLibrary("Carbon", MCarbon.class);
Pointer GetCurrentEventQueue();
int SendEventToEventTarget(Pointer inEvent, Pointer intarget);
int RemoveEventFromQueue(Pointer inQueue, Pointer inEvent);
void ReleaseEvent(Pointer inEvent);
Pointer AcquireFirstMatchingEventInQueue(Pointer inQueue,NativeLong inNumTypes,EventTypeSpec[] inList, NativeLong inOptions);
//... so on
}
The solution to the problem is solved using the below function:
NativeLong ReceiveNextEvent(NativeLong inNumTypes, EventTypeSpec[] inList, double inTimeout, byte inPullEvent, Pointer outEvent);
This does the job. As per documentation -
This routine tries to fetch the next event of a specified type.
If no events in the event queue match, this routine will run the
current event loop until an event that matches arrives, or the
timeout expires. Except for timers firing, your application is
blocked waiting for events to arrive when inside this function.
Also if not ReceiveNextEvent, then other functions as mentioned in MCarbon class above would be useful.
I think Carbon framework documentation would give more insights and flexibilities to solve the problem. Apart from Carbon, in forums people have mentioned about solving using Cocoa, but none I am aware of.
Edit: Thanks to technomarge, more information here
Related
How can I call a windows UWP API from the JVM?
For example the Windows.Security.Credentials API.
When attempting to use JNA none of the native library names I have tried will link, and I can't actually find a DLL that matches the name Windows.Security.Credentials.dll as described in the documentation.
Is what I want to do even possible, how can I link to and call UWP API's?
Update: I completely missed the mark on my first answer, was thinking JNI, not JNA, which looks a bit more like C# pInvoke. The code below is roughly what you'll need, but you'll need to reconstruct the v-tables for IInspectable and IPasswordVault. You can use the activation factory instead of activating the instance through RoActivateInstance, but then you'll need to reconstruct the interface for IActivationFactory as well. Otherwise the call suquence below is correct, if in the wrong language.
You can link and call against RoActivateInstance or RoGetActivationFactory and use the low-level COM-styl ABI interfaces defined the SDK in Windows.Security.Credentials.h. Same import lib as above.
eg:
IInspectable *pI {};
Windows::Security::Credentials::IPasswordVault pPV;
HRESULT hr = RoActivateInstance(L"Windows.Security.Credentials.PasswordVault", &pI);
if (SUCCEEDED(hr)) {
hr = pI->QueryInterface(__uuidof(Windows::Security::Credentials::IPasswordVault), (void**)&pPV);
}
if (SUCCEEDED(hr)) {
IVectorView<IPasswordCredential> *pPV{}; // namespaces omitted
hr = pPV->RetrieveAll(&pPV);
}
Can someone provide an example of how the Progressable interface might be implemented for use when calling FileSystem.create()? I saw the following code snippet in another post, but it did not show where bytesWritten came from:
OutputStream os = hdfs.create( file,
new Progressable() {
public void progress() {
out.println("...bytes written: [ "+bytesWritten+" ]");
} });
The documentation of this interface says it is for reporting progress to the Hadoop framework to avoid timeout in the case of a lengthy operation, but "Hadoop: The Definitive Guide" says it is for notifying the application of the progress of the data being written to the data nodes, which doesn't make much sense since it is a create.
Thanks, RF
If you have an implementation of Mapper where an invocation of map() may take a long time (like more than several minutes), then you can periodically call progress() on the provided context object to let Hadoop know that your code isn't hung. That's what they mean by "explicitly reporting progress" - it works when you're using an object provided by the framework that implements Progressable, it obviously doesn't work that way when you write your own implementation of Progressable.
I should have read the Hadoop book further -- here is the example they gave later on:
OutputStream out = fs.create(new Path(dst), new Progressable() {
public void progress() {
System.out.print(".");
}
The accompanying text says " We illustrate progress
by printing a period every time the progress() method is called by Hadoop, which is after each 64 KB packet of data is written to the datanode pipeline".
I guess my question becomes, how does this "explicitly report progress to the Hadoop framework" as stated by the documentation of Progressable?
Checking the source code for MediaPlayer (link), the start() method looks like this:
public void start() throws IllegalStateException {
stayAwake(true);
_start();
}
And _start() method looks like this:
private native void _start() throws IllegalStateException;
Checking the native _start() method (link) (called start() but should it not be called _start() because of the native call was named _start()?):
status_t MediaPlayer::start()
{
ALOGV("start");
Mutex::Autolock _l(mLock);
if (mCurrentState & MEDIA_PLAYER_STARTED)
return NO_ERROR;
if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
mPlayer->setLooping(mLoop);
mPlayer->setVolume(mLeftVolume, mRightVolume);
mPlayer->setAuxEffectSendLevel(mSendLevel);
mCurrentState = MEDIA_PLAYER_STARTED;
status_t ret = mPlayer->start();
if (ret != NO_ERROR) {
mCurrentState = MEDIA_PLAYER_STATE_ERROR;
} else {
if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
ALOGV("playback completed immediately following start()");
}
}
return ret;
}
ALOGE("start called in state %d", mCurrentState);
return INVALID_OPERATION;
}
Where is the data read? I wanted to check how Android work with RTSP but I could not find out where it loads the data. I wanted to know if it uses some library like FFMpeg or some other implementation.
EDIT:
Why was this code necessary to use JNI for?
All of the following paths reference src/frameworks/base/.
In media/jni/android_media_MediaPlayer.cpp you will find the JNI code that forwards the Java method call to the underlying native framework. You can see the name mapping in the gMethods[] array and the AndroidRuntime::registerNativeMethods call near the bottom of the file. You can read more about registering native methods with JNI here, but that's not really the interesting part.
At this stage we are in the native counterpart of the Java MediaPlayer. For the most part, it doesn't do anything interesting, either. It binds to the MediaPlayerService through IBinder transactions. The MediaPlayerService creates the actual native player based on the type of media, and maintains a client (MediaPlayerService::Client) to facilitate communication with the native MediaPlayer, which in turn bubbles things back up to Java. You can see all this happen in the following files (if you're interested):
media/libmedia/mediaplayer.cpp,
media/libmedia/IMediaPlayer.cpp,
media/libmedia/IMediaPlayerClient.cpp,
media/libmedia/IMediaPlayerService.cpp,
media/libmediaplayerservice/MediaPlayerService.cpp
Header files for libmedia are in include/media/libmedia/.
Now to the really interesting part, which are the component players. In MediaServicePlayer.cpp there are a couple of getPlayerType methods that decide what player to instantiate. There's Stagefright framework (AwesomePlayer and NuPlayer) and Sonivox player for MIDI. For RTSP, NuPlayer is what you'll get. You can find a glue layer in media/libmediaplayerservice/nuplayer/ and all the real source code in media/libstagefright/ and media/libstagefright/rtsp/.
You missed a step along the way. The private native void _start() in the Java code refers to this entry in the MediaPlayer JNI layer (which refers to this function).
As for the RTSP implementation, you'll probably find it among the Stagefright sources.
_start method is defined in jni in this mediaplayer file link
from here that libmedia start method is getting called.
I have to interface a third party COM API into an Java application. So I decided to use Com4j, and so far I've been satisfied, but now I've run into a problem.
After running the tlbgen I have an object called IAddressCollection which according to the original API documentation conforms to the IEnum interface definition. The object provides an iterator() function that returns a java.util.Iterator<Com4jObject>. The object comes from another object called IMessage when I want to find all the addresses for the message. So I would expect the code to work like this:
IAddressCollection adrCol = IMessage.getAddressees();
Iterator<Com4jObject> adrItr = adrCol.iterator();
while(adrItr.hasNext()){
Com4jObject adrC4j = adrItr.next();
// normally here I would handle the queryInterface
// and work with the rest of the API
}
My problem is that when I attempt the adrItr.next() nothing happens, the code stops working but hangs. No exception is thrown and I usually have to kill it through the task manager. So I'm wondering is this a problem that is common with Com4j, or am I handling this wrong, or is it possibly a problem with the API?
Ok, I hate answering my own question but in this case I found the problem. The issue was the underlying API. The IAddressCollection uses a 1 based indexing instead of a 0 based as I would have expected. It didn't provide this information in the API documentation. There is an item function where I can pull the object this way and so I can handle this with
IAddressCollection adrCol = IMessage.getAddressees();
for(int i = 1; i <= adrCol.count(); i++){
IAddress adr = adrCol.item(i);
// IAddress is the actual interface that I wanted and this works
}
So sorry for the annoyance on this.
I use Launch4j as a wrapper for my Java application under Windows 7, which, to my understanding, in essence forks an instance of javaw.exe that in turn interprets the Java code. As a result, when attempting to pin my application to the task bar, Windows instead pins javaw.exe. Without the required command line, my application will then not run.
As you can see, Windows also does not realize that Java is the host application: the application itself is described as "Java(TM) Platform SE binary".
I have tried altering the registry key HKEY_CLASSES_ROOT\Applications\javaw.exe to add the value IsHostApp. This alters the behavior by disabling pinning of my application altogether; clearly not what I want.
After reading about how Windows interprets instances of a single application (and a phenomenon discussed in this question), I became interested in embedding a Application User Model ID (AppUserModelID) into my Java application.
I believe that I can resolve this by passing a unique AppUserModelID to Windows. There is a shell32 method for this, SetCurrentProcessExplicitAppUserModelID. Following Gregory Pakosz suggestion, I implemented it in an attempt to have my application recognized as a separate instance of javaw.exe:
NativeLibrary lib;
try {
lib = NativeLibrary.getInstance("shell32");
} catch (Error e) {
Logger.out.error("Could not load Shell32 library.");
return;
}
Object[] args = { "Vendor.MyJavaApplication" };
String functionName = "SetCurrentProcessExplicitAppUserModelID";
try {
Function function = lib.getFunction(functionName);
int ret = function.invokeInt(args);
if (ret != 0) {
Logger.out.error(function.getName() + " returned error code "
+ ret + ".");
}
} catch (UnsatisfiedLinkError e) {
Logger.out.error(functionName + " was not found in "
+ lib.getFile().getName() + ".");
// Function not supported
}
This appears to have no effect, but the function returns without error. Diagnosing why is something of a mystery to me. Any suggestions?
Working implementation
The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID using JNA.
I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.
For reference, I believe using this technique opens the possibility of using any of the APIs discussed in this article in a Java application.
I don't have Windows 7 but here is something that might get you started:
On the Java side:
package com.stackoverflow.homework;
public class MyApplication
{
static native boolean setAppUserModelID();
static
{
System.loadLibrary("MyApplicationJNI");
setAppUserModelID();
}
}
And on the native side, in the source code of the `MyApplicationJNI.dll library:
JNIEXPORT jboolean JNICALL Java_com_stackoverflow_homework_MyApplication_setAppUserModelID(JNIEnv* env)
{
LPCWSTR id = L"com.stackoverflow.homework.MyApplication";
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(id);
return hr == S_OK;
}
Your question explicitly asked for a JNI solution. However, since your application doesn't need any other native method, jna is another solution which will save you from writing native code just for the sake of forwarding to the windows api. If you decide to go jna, pay attention to the fact that SetCurrentProcessExplicitAppUserModelID() is expecting a UTF-16 string.
When it works in your sandbox, the next step is to add operating system detection in your application as SetCurrentProcessExplicitAppUserModelID() is obviously only available in Windows 7:
you may do that from the Java side by checking that System.getProperty("os.name"); returns "Windows 7".
if you build from the little JNI snippet I gave, you can enhance it by dynamically loading the shell32.dll library using LoadLibrary then getting back the SetCurrentProcessExplicitAppUserModelID function pointer using GetProcAddress. If GetProcAddress returns NULL, it means the symbol is not present in shell32 hence it's not Windows 7.
EDIT: JNA Solution.
References:
The JNI book for more JNI examples
Java Native Access (JNA)
There is a Java library providing the new Windows 7 features for Java. It's called J7Goodies by Strix Code. Applications using it can be properly pinned to the Windows 7 taskbar. You can also create your own jump lists, etc.
I have implemented access to the SetCurrentProcessExplicitAppUserModelID method using JNA and it works quite well when used as the MSDN documentation suggests. I've never used the JNA api in the way you have in your code snippet. My implementation follows the typical JNA usage instead.
First the Shell32 interface definition:
interface Shell32 extends StdCallLibrary {
int SetCurrentProcessExplicitAppUserModelID( WString appID );
}
Then using JNA to load Shell32 and call the function:
final Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
{
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
}
};
Shell32 shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class,
WIN32API_OPTIONS);
WString wAppId = new WString( "Vendor.MyJavaApplication" );
shell32.SetCurrentProcessExplicitAppUserModelID( wAppId );
Many of the API's in the last article you mentioned make use of Windows COM which is quite difficult to use directly with JNA. I have had some success creating a custom DLL to call these API's (eg. using the SHGetPropertyStoreForWindow to set a different app ID for a submodule window) which I then use JNA to access at runtime.
Try to use JSmooth. I use always this one. In JSmooth is there an option under Skeleton by Windowed Wrapper called
Lauch java app in exe process
See on this image.
(source: andrels.com)
Also command line arguments can be passed.
I think this can be a solution for you.
Martijn
SetCurrentProcessExplicitAppUserModelID (or SetAppID()) would in fact do what you're trying to do. However, it might be easier to modify your installer to set the AppUserModel.ID property on your shortcut - quoting from the Application User Model ID document mentioned above:
In the System.AppUserModel.ID property of the application's shortcut file. A shortcut (as an IShellLink, CLSID_ShellLink, or a .lnk file) supports properties through IPropertyStore and other property-setting mechanisms used throughout the Shell. This allows the taskbar to identify the proper shortcut to pin and ensures that windows belonging to the process are appropriately associated with that taskbar button.
Note: The System.AppUserModel.ID property should be applied to a shortcut when that shortcut is created. When using the Microsoft Windows Installer (MSI) to install the application, the MsiShortcutProperty table allows the AppUserModelID to be applied to the shortcut when it is created during installation.
The latest jna-platform library now includes JNA bindings for SetCurrentProcessExplicitAppUserModelID:
https://github.com/java-native-access/jna/pull/680
I fixed mine without any ID settings.
There is an option in Launch4J if you are using it and you say you do then...
You can change the header to JNI Gui and then wrap it around the jar with the JRE.
The good thing is that it runs .exe in the process now instead on running javaw.exe with your jar. It probably does it under the hood (not sure).
Also I have noticed also that it takes around 40-50% less CPU resource which is even better!
And the pinning works fine and all that window features are enabled.
I hope it helps to someone as I spent nearly 2 days trying to solve that issue with my undecorated javafx app.