How can I switch cameras in Xamarin.Forms? - xamarin.forms

My app uses Xamarin.Forms. Now I am trying to apply IceLink for implementing video calls. Is there a way to switch between front/rear/anyOther camera? I saw a sample where LocalMediaStream's UseNextVideoDevice() method is used, but now LocalMediaStream is obsolete, and I don't have it. But I do have IceLink.FM.LocalMedia object in my PageModel.
public void SwitchCamera()
{
if (_localMedia == null)
return;
// _localMedia.UseNextVideoDevice(); // obsolete
}
Is it possible to make that switch between cameras?

Related

Dynamically create multiple DirectShow virtual webcam devices

I am trying to create a virtual webcam DirectShow filter with multiple virtual devices.
The cameras are defined as follows:
CFactoryTemplate g_Templates[] =
{
{
SUB_DEVICE_NAME_0,
&CLSID_VirtualCam_0,
CVCam::CreateInstance0,
NULL,
&AMSFilterVCam_0
},
{
SUB_DEVICE_NAME_1,
&CLSID_VirtualCam_1,
CVCam::CreateInstance1,
NULL,
&AMSFilterVCam_1
}
};
The initialization is done with these static methods:
CUnknown * WINAPI CVCam::CreateInstance0(LPUNKNOWN lpunk, HRESULT *phr)
{
return new CVCam(NAME(DEVICE_NAME_0), lpunk, phr, CLSID_VirtualCam_0, 0);
}
CUnknown * WINAPI CVCam::CreateInstance1(LPUNKNOWN lpunk, HRESULT *phr)
{
return new CVCam(NAME(DEVICE_NAME_1), lpunk, phr, CLSID_VirtualCam_1, 1);
}
Is it possible to do this more dynamically so that we do not have to hard code each camera but can pass a parameter during runtime?
Regards,
Dynamic addition and removal of the camera is possible. However it is quite different from what you though of in the body of the question. DirectShow BaseClasses offer you certain helpers to convert static declarations into registration and DirectShow sample code shows how DLL exports are connected to these helpers for registration needs.
To make it dynamic you need to expand what AMoveDllRegisterServer2 does for most of filter projects and adapt its implementation for your needs.
This part of RegisterFilters might be a good starting point, you would want to make it a loop or something. You will have to deal with additional fm->RegisterFilter(... calls respectively to additional virtual cameras you want.

How to handle user interaction with new Bluetooth prompt in iOS13?

"There’s a new key for the Info.plist file: NSBluetoothAlwaysUsageDescription, which you can use to explain how and why your app uses Bluetooth. In contrast to the existing NSBluetoothPeripheralUsageDescription, the new description will be shown as part of the new pop-up, and also in the Settings app on the Bluetooth Privacy screens."
After updating to iOS 13, our app experienced crashes, as I'm sure many did. Our problem was due to not including the newly required bluetooth key in the Xamarin.iOS projects Info.plist file.
However after adding this upon loading the first "action" that occurs is presenting the user with the new Bluetooth access prompt.
We aren't clearly seeing how to capture the response to this prompt. In-fact after this prompt is interacted with the app has no "return" point as it were. Can't quite find a break-point for the prompt interaction / result handling and our app never returns from the prompt. It's running but the next "action" to occur never happens.
So- how to capture/handle user's interaction with the new Bluetooth prompt in iOS 13?
NOTE*: To be absolutely transparent - our application doesn't initialize any instance of CBCentralManager rather it takes advantage of a native framework that itself utilizes Bluetooth LE internally (out of our control).
Our case might be quite unique but for those experiencing this implement CBCentralManager and utilize its UpdatedState method to capture user interaction with the newly presented Bluetooth dialogue.
Initialization called in page creation of our Apps MainPage
BleManager = new BluetoothManager();
Class
using System;
using CoreBluetooth;
namespace MyApp.iOS.Classes
{
public class BluetoothManager
{
public CBCentralManager CentralBleManager
{
get { return this.bleCntrlMgr; }
}
protected CBCentralManager bleCntrlMgr;
protected CBCentralManagerDelegate bleMgrDel;
public BluetoothManager()
{
this.bleCntrlMgr = new CoreBluetooth.CBCentralManager();
this.bleCntrlMgr.UpdatedState += BleMgr_UpdatedState;
}
private void BleMgr_UpdatedState(object sender, EventArgs e)
{
Console.WriteLine("UpdatedState: {0}", bleCntrlMgr.State);
if (bleCntrlMgr.State == CBCentralManagerState.PoweredOn
|| bleCntrlMgr.State == CBCentralManagerState.PoweredOff
|| bleCntrlMgr.State == CBCentralManagerState.Resetting
|| bleCntrlMgr.State == CBCentralManagerState.Unauthorized
|| bleCntrlMgr.State == CBCentralManagerState.Unsupported)
{
/* return point */
// i.e.: CallMethod();
}
else if (bleCntrlMgr.State == CBCentralManagerState.Unknown)
{
/* <-- request access --> */
}
}
}
}

How to turn off Motion Controller line pointer

That's it, I'll step on my pride!
I'm using MRTK v2 and working fine except that at some point I want to turn off the line extending from the Motion Controller to the object and that provides input. After looking around and trying to find it in the MRTK documentation (it's gotta be easy, right?), I'm still banging my head on the wall and it's starting to hurt....
The MRTK documentation explains quite well how to configure it here:
https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_release/Documentation/Input/Pointers.md
But I'm looking to do this in script, enabling and disabling it as I need it in my application.
Any clue how to do this?
Many thanks!
Answered my own question. Simple:
PointerUtils.SetMotionControllerRayPointerBehavior(PointerBehavior.AlwaysOff);
See documentation here: https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_release/Documentation/Input/Pointers.md
Great question! Here's one way to do this that has worked for me. You can see my solution at this repository: https://github.com/julenka/MixedRealityToolkit-Unity/tree/so/linepointer_off. Open the scene Assets/TurnOffLinePointerTest.unity and then use hand simulation to press the buttons. The code to turn the pointers on/off is in Assets/PointerConfigurationExample.cs.
Note: the reason you need to use this approach of modifying the mediator instead of directly setting myPointer.IsActive = false is because the default mediator overwrites these values every frame. Luckily, you can customize this behavior.
Step 1: Update MRTK a bit so that PointerMediator can be accessed
Apply the changes from this commit to your MRTK clone. This change updates the FocusProvider in MRTK to make the PointerMediator publicly accessible, and makes the DefaultPointerMediator extensible by updating fields to be protected instead of private, and making methods virtual. See this pull request that implements this change directly into MRTK.
Step 2: Create a custom PointerMediator that will turn off far pointers
Create a custom Pointer Mediator like the one from this commit.
using System.Collections.Generic;
using Microsoft.MixedReality.Toolkit.Input;
public class CustomPointerMediator : DefaultPointerMediator
{
public bool FarPointersDisabled {get; set;}
public override void UpdatePointers()
{
base.UpdatePointers();
if (FarPointersDisabled)
{
foreach(var pointer in farInteractPointers)
{
pointer.IsActive = false;
}
}
}
}
Note that this mediator extends DefaultPointerMediator so it adapts almost all the default mediator logic. Make sure you have fully applied the changes from the first commit otherwise you will not be able to extend DefaultPointerMediator.
Step 3: Tell MRTK to use your custom pointer mediator
In your pointer profile, configure MRTK to use the custom pointer mediator instead of the default pointer mediator. Notice in the picture that I've created a custom pointer profile as part of a custom input system (don't modify the default profile otherwise your changes might get overwritten when you update MRTK).
Step 4: Component that uses custom mediator to turn line pointers on / off
You can now write your component which will use your custom mediator to turn the line pointers on and off.
public class PointerConfigurationExample : MonoBehaviour
{
/* Turns off all far interaction pointers */
public void TurnOffFarPointers()
{
Debug.Log("Line pointers off");
SetFarPointersDisabled(true);
}
public void TurnOnFarPointers()
{
Debug.Log("Line pointers on");
SetFarPointersDisabled(false);
}
private void SetFarPointersDisabled(bool isDisabled)
{
FocusProvider focusProvider = (FocusProvider) MixedRealityToolkit.InputSystem.FocusProvider;
if (focusProvider != null)
{
foreach(var mediator in focusProvider.PointerMediators)
{
// Note: you could check here to make sure you only disable pointers for hands
CustomPointerMediator myMediator = (CustomPointerMediator) (mediator.Value);
if (myMediator != null)
{
myMediator.FarPointersDisabled = isDisabled;
}
}
}
}
}

How can I use INetwork in Xamarin Forms XLabs?

I am having a problem using INetwork from XLabs.Platform. I am getting System.NullReferenceException. I am not sure if the problem is similar to this where I need to initialize INetwork. However, because I am very new to Xamarin I have no idea how to set up the IOC container. I'd like to this in a completely cross-platform way (I'd like to avoid putting platform specific code if I can avoid it). Thanks!!
Code:
using XLabs.Ioc;
using XLabs.Platform;
...
namespace XXX
{
class XXX
{
public static bool isOnline()
{
var networkservice = DependencyService.Get<XLabs.Platform.Services.INetwork>();
var status = networkservice.InternetConnectionStatus();
return (
(status.Equals(XLabs.Platform.Services.NetworkStatus.ReachableViaCarrierDataNetwork))
|| (status.Equals(XLabs.Platform.Services.NetworkStatus.ReachableViaWiFiNetwork))
|| (status.Equals(XLabs.Platform.Services.NetworkStatus.ReachableViaUnknownNetwork)));
}
}
}
PS The documentation for using XLabs.Platform is out of date. The (apparently) previously functioning Reachability interface doesn't work anymore. Thinking about using this instead. This is an approach that requires cross platform code. Not going to use this as the author himself disses the approach.
If you want to check if there is any Internet Connection, I would suggest to use Connectivity Plugin (Xamarin Component). After adding the Xaamrin Component you can check if an internet connection is avaliable from PCL/Shared project like below
if (CrossConnectivity.Current.IsConnected)
{ // Make API call here
}
else
DisplayAlert("Connectivity Issue", "Please Connect to a Network", "OK") ;
You fill the ioc by adding this attribute:
[assembly: Xamarin.Forms.Dependency(typeof(NameOfClassImplementingAnInterface))]

Is there any way to add a valueCommit lifecycle to non-mxml components in Actionscript?

The invalidate/commitProperties model used by mxml components is very useful, in my experience, and I'd like to be able to make use of it in domain model objects in my actionscript applications. How can I go about adding lifecycle events like that to my objects? Is there a global object lifecycle manager?
As noted by Robert Bak, you're essentially on your own to implement such a mechanism for non-UI components.
I've found this a very useful technique to use on model classes, since it can dramatically reduce the "thrashing" of bound-property updates when your model classes are not simple data transfer objects - i.e. they have any kind of multi-property logic encapsulated within them.
Since my use-case is for model objects, I didn't need all the methods of IInvalidating.
Here's my particular implementation as a starting point for your own efforts. Note that this comes from a "base model class" we use called RAFModel and that this is for the Flex 4 SDK.
// INVALIDATION AND COMMITPROPERTIES PATTERN
private var invalidatePropertiesFlag:Boolean;
public function invalidateProperties():void
{
if (!invalidatePropertiesFlag)
{
invalidatePropertiesFlag = true;
invalidateModelObject(this);
}
}
protected function commitProperties():void
{
// override this
}
// -- INVALIDATION SUPPORT
public static var invalidObjects:Dictionary = new Dictionary(true);
public static var validatePending:Boolean = false;
public static function invalidateModelObject(obj:RAFModel):void
{
invalidObjects[obj] = true;
if (!validatePending)
{
validatePending = true;
FlexGlobals.topLevelApplication.callLater(validateObjects);
}
}
protected static function validateObjects():void
{
var invalidQueue:Dictionary = invalidObjects;
// start a fresh tracker for further invalidations
// that are a side effect of this pass
invalidObjects = new Dictionary(true);
// ready to receive another call
validatePending = false;
for (var o:* in invalidQueue)
{
var rm:RAFModel = o as RAFModel;
if (rm)
{
// clear the flag first, in case we're reentrant
// on any given instance
rm.invalidatePropertiesFlag = false;
rm.commitProperties();
}
}
}
Invalidation and commitProperties isn't linked to MXML (you can use it with as components) but it is linked to the flex managed visual component lifecycle (as they are the only ones which need to be synchronized with the flash frame by frame rendering). So unless you're talking about visual components it will not work out of the box.
But if you're looking to implement the same mechanism for your non-visual classes, you should probably start by implementing IInvalidating (docs) and creating a mechanism that calls the validateNow() function when the validation needs to be done.
The Flex Component LifeCycle is designed to handle a User Interface Component's creation, destruction, and changes during the time in between. I, personally, do not find the approach appropriate for non-User Interface components.
You could, if you wanted, extend UIComponent in your domain model objects and then add that domain model as a child to a container. it would then go through the Flex Component LifeCycle validation phases (commitProperties, updateDisplayList, and measure).
But, I would not recommend that approach.

Resources