How do you detect whether your Mixed Reality app is running on HoloLens 1, HoloLens 2 or an immersive headset? - hololens

Mixed Reality apps can soon run on three kinds of devices: HoloLens 1, Hololens 2 and Immersive (VR) headsets. Some behavior will likely be different depending on the type of device you run the app on. How can I ask the SDK what kind of device my app is running currently on?

If you are using MRTK (I noticed you might based on your tag), then the best way to do this is by using platform capabilities utility, since that will work as new devices come out, and across platforms. For example, instead of checking "am on on HoloLens 2" you can check "does my device support articulated hands?". That will then work on other platforms that support articulated hands. For an example, chekc out MixedRealityToolkit.Examples/Demos/Utilities/Scenes/MixedRealityCapabilityDemo.unity in MRTK examples.
If you need a temporary solution for now to differentiate WMR from HL1 from HL2, you can use the following code. Note it's windows-only:
using Windows.Security.ExchangeActiveSyncProvisioning;
EasClientDeviceInformation CurrentInfo = new EasClientDeviceInformation();
string sku = CurrentInfo.SystemSku;
HoloLens 1, HoloLens 2, and Immersive headsets should all return different strings.
Edit 6/5/2020:
It's also possible to check the runtime platform as follows:
if (Application.platform == RuntimePlatform.WSAPlayerARM)
{
// Running HoloLens 2, most likely.
}

HolographicDisplay.GetDefault().IsOpaque is true for Immersive VR headsets and false for AR devices like HoloLens.
For HoloLens you don't need to detect a precise device family. Instead you should check the feature support via Universal Contract Version like
bool checkUniversalApiContract(int contractNumber)
{
return winrt::Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", contractNumber);
}
bool supportsHandTracking = checkUniversalApiContract(8);

To check whether it is opaque (VR) or not (AR):
#if UNITY_2017_2_OR_NEWER
bool isOpaque = UnityEngine.XR.WSA.HolographicSettings.IsDisplayOpaque;
#else
bool isOpaque = UnityEngine.VR.VRDevice.isPresent;
#endif
To check whether it is HL1 or HL2, this is a simple solution, not requiring other dlls:
#if UNITY_WSA || UNITY_WSA_10_0
// Get vertical field of view in degrees
// HL1 == 17.5, HL2 == 29
bool isHL1 = (Camera.main.fieldOfView < 23f);
#endif

Related

Can I trigger the Hololens Calibration sequence from inside my application?

I have a hololens app I am creating that requires the best accuracy possible for hologram placement. This application will be used by numerous individuals. Whenever I try to show the application progress, I have to have the user go through the calibration process, otherwise the holograms appear to have way too much drift.
I would like to be able to call the hololens calibration process automatically when the application opens. Later, after I set up user authentication and id management, I will call the calibration process when a new user is found.
https://learn.microsoft.com/en-us/windows/mixed-reality/calibration
I have looked into the calibration (via the above documentation and elsewhere) and it seems that all it is setting is IPD. However the alternative solutions I have found that allow for dynamic ipd adjustment appear to be invalid for UWP Store apps. This makes them unusable for me.
I am looking for any help or direction, or if this is even possible. Thank you.
Yes, it is possible to to this, you need to use the LaunchUriAsync protocol to launch the following URI: ms-hololenssetup://EyeTracking
Here is an example implementation, obtained from the LaunchUri example in MRTK
public void LaunchEyeTracking()
{
#if WINDOWS_UWP
UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
{
bool result = await global::Windows.System.Launcher.LaunchUriAsync(new System.Uri("ms-hololenssetup://EyeTracking"));
if (!result)
{
Debug.LogError("Launching URI failed to launch.");
}
}, false);
#else
Debug.LogError("Launching eye tracking not supported Windows UWP");
#endif
}

Transmitting as iBeacon in XAMARIN - AltBeacon library

I have come across a problem with iBeacon transmission in AltBeacon library in XAMARIN.
In Android Studio, this code works perfect (I can detect created iBeacon on iPhone). I am using Android 5:
mBeaconTransmitter = new BeaconTransmitter(this, new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
Beacon beacon = new Beacon.Builder()
.setId1("FDA50693-A4E2-4FB1-AFCF-C6EB07647825")
.setId2("1000")
.setId3("2000")
.setManufacturer(0x004C)
.setTxPower(-59)
.setDataFields(Arrays.asList(new Long[] {0l}))
.build();
mBeaconTransmitter.startAdvertising(beacon);
However, I have not managed to attain the same result in XAMARIN (Visual Studio). I cannot detect created iBeacon on iPhone in this case:
var iBeaconParser = new BeaconParser();
iBeaconParser.SetBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
BeaconTransmitter beaconTransmitter = new BeaconTransmitter(ApplicationContext, iBeaconParser);
var beacon1 = new AltBeacon.Builder().SetId1("FDA50693-A4E2-4FB1-AFCF-C6EB07647825")
.SetId2("1000").SetId3("2000").SetTxPower(-59).SetManufacturer(0x004C).Build();
beaconTransmitter.StartAdvertising(beacon1);
The transmission also works in the second case. Other Android device could detect the created iBeacon. It was unsuccessful to detect the iBeacon on iPhone.
Thank you for any advice.
Hey buddy it's been almost 3 years you have ask this question so I don't know that is it still relevant for you or not but my be this will help others.
I have seen this code this is absolutely right for the beacon broadcasting and I will suggest to check that if you have bind IBeaconconsumer with beacon manage in the initialization function Bind((IBeaconConsumer)Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity); or check that if you have use _tagRegion and this refers to right one.
Hope this will help.

D3D9 CreateDevice() fails on Windows 10 when creating a multihead device

When calling IDirect3D9::CreateDevice with the BehaviorFlags D3DCREATE_ADAPTERGROUP_DEVICE in order to create a fullscreen multihead device (with 2 or more monitors attached) the function returns D3DERR_INVALIDCALL, when running the application on Windows 10 (build 1511, or build 10240).
The same code works fine on Windows 7 (on a multitude of different machines), and also on Windows 8.1 (with the latest updates). Also creating individual D3D9 devices (fullscreen) for each attached monitor to the graphics adapter works fine on Windows 10.
D3D9Ex by the way shows exactly the same behavior. Can anyone point me to a working D3D9 multihead example that works on Windows 10? Thanks!
I observed the exact same behaviour with "CreateDevice".
But when you use "CreateDeviceEx" it works ... well ... almost :-(.
You may now create the device and use it, but under some circumstances (especially if you use the same resolutions as the desktop already had) you wont see anything and "Present" will continuously return "S_PRESENT_MODE_CHANGED". But if you now switch the second monitor to some other resolution via ResetEx end then switch back to desktop resolution - voila it works. I put that on on a key I can press after initialization:
const int idx = 1;
int OldWidth = D3DPresPar[idx].BackBufferWidth;
int OldHeight = D3DPresPar[idx].BackBufferHeight;
D3DPresPar[idx].BackBufferWidth = 1280;
D3DPresPar[idx].BackBufferHeight = 720;
D3DDispMode[idx].Width = 1280;
D3DDispMode[idx].Height = 720;
FailCheck(pD3DDevice->ResetEx(D3DPresPar, D3DDispMode), "ResetEX");
D3DPresPar[idx].BackBufferWidth = OldWidth;
D3DPresPar[idx].BackBufferHeight = OldHeight;
D3DDispMode[idx].Width = OldWidth;
D3DDispMode[idx].Height = OldHeight;
FailCheck(pD3DDevice->ResetEx(D3DPresPar, D3DDispMode), "ResetEX");
And after pressing the key it suddenly works. Weird, eh?
I confirmed this behaviour on multiple computers with nvidia, amd and intel grafics adapters. So the bug seems to be on microsoft side.
Conclusion: Theoretically it should work but there is some annyoing bug in windows 10 multihead initialization.
With some weird tricks you can achieve what you want, but these tricks are just too weird to use in production.

For testing GPS based J2ME app, Is there any emulator which have built in GPS?

I am new in J2ME app development field. I am developing GPS based app using Nokia Maps for series 40 mobiles. I want such emulator which provide GPS(to retrieve & set current coordinates & many other purposes). I search a lot on google but I didn't found such emulator.... even what ever emulators provide by Nokia SDKs; they also don't have GPS capability... Then how should I get such emulator??
You can download the latest Nokia IDE (which includes the Nokia Maps Plugin) here:
Emulator download
The emulator associated with the SDK includes tools to simulate JSR-179 location calls (e.g. Cell-Id/GPS), you can play back coordinates for a saved file and receive them at regular intervals. Look at the emulator's Tools > Route Editor menu.
The confusion here is the difference between GPS positioning and Cell-Id positioning. There are currently no series 40 mobiles (that I know of) with a GPS unit - hence positioning will need to be done by Cell-ID - In this case the only way to retrieve frequent location updates in the Cell-ID scenario is to call the getLocation() method within a repeating loop. Retrieving location objects via the locationUpdated() method, can only be done in a GPS-based location retrieval.
In summary you can get a location from any Java ME phone supporting JSR-179, you won't be using GPS though.
To get a location use the following:
cellIdLocator = getCellIdProvider();
cellIdLocator.getLocation(DEFAULT_TIMEOUT);
Where the cell-id provider can be held in a singleton
private LocationProvider cellIdLocator;
public LocationProvider getCellIdProvider() throws LocationException {
if (cellIdLocator == null) {
int[] methods = {
Location.MTA_ASSISTED | Location.MTE_CELLID
| Location.MTY_NETWORKBASED};
cellIdLocator = LocationUtil.getLocationProvider(methods, null);
}
return cellIdLocator;
}

How can I select an audio output device in directshow

I was wondering how I can select the output device for audio in directshow. I am able to get available audio output devices in directshow. But how can I make one of these to be audio output device. Its always going for the default audio device. I want to be able to output audio on my choice of device. I have been struggling through google but couldn't find anything useful. All I could get was this link but it doesn't really solve my problem.
Any help will be really helpful for me.
First off, if you're not using DirectShow .NET (DirectShowLib), get that here: It serves as a (very complete) interface between unmanaged DirectShow and C#
What follows is a pretty simple example of how to play an audio file, to the desired audio device
using DirectShowLib;
private IGraphBuilder m_objFilterGraph = null;
private IBasicAudio m_objBasicAudio = null;
private IMediaControl m_objMediaControl = null;
private void playAudioToDevice(string fName, int devIndex)
{
object source = null;
DsDevice[] devices;
devices = DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory);
DsDevice device = (DsDevice)devices[devIndex];
Guid iid = typeof(IBaseFilter).GUID;
device.Mon.BindToObject(null, null, ref iid, out source);
m_objFilterGraph = (IGraphBuilder)new FilterGraph();
m_objFilterGraph.AddFilter((IBaseFilter)source, "Audio Render");
m_objFilterGraph.RenderFile(fName, "");
m_objBasicAudio = m_objFilterGraph as IBasicAudio;
m_objMediaControl = m_objFilterGraph as IMediaControl;
m_objMediaControl.Run();
}
It is up to user to manage audio devices and choose a primary device (such as via Control Panel applet). You can find ways to switch devices programmatically in Windows XP, however in Vista+ it is impossible without interactive user action by design.
See also Larry's answer here: How to change default sound playback device programmatically?
UPDATE: The mentioned above refers to modifying system configuration trying to alter default audio output device. An application is however not limited to default device only. Instead, it can enumerate available devices (see Using the System Device Enumerator + CLSID_AudioRendererCategory) and then create an instance of renderer for specific device with BindToObject call. From there on, it is a regular filter, just bound internally to device of interest.

Resources