OK, My issue is quite simple.
I've managed to turn the flash On (and keep it On).
However, I'm still not sure how to turn it off (lol).
Here's my code :
var sensorLocation = CameraSensorLocation.Back;
try
{
// get the AudioViceoCaptureDevice
var avDevice = await AudioVideoCaptureDevice.OpenAsync(sensorLocation,
AudioVideoCaptureDevice.GetAvailableCaptureResolutions(sensorLocation).First());
// turn flashlight on
var supportedCameraModes = AudioVideoCaptureDevice
.GetSupportedPropertyValues(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchMode);
if (supportedCameraModes.ToList().Contains((UInt32)VideoTorchMode.On))
{
avDevice.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.On);
// set flash power to maxinum
avDevice.SetProperty(KnownCameraAudioVideoProperties.VideoTorchPower,
AudioVideoCaptureDevice.GetSupportedPropertyRange(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchPower).Max);
}
else
{
turnWhiteScreen(true);
}
}
catch (Exception ex)
{
// Flashlight isn't supported on this device, instead show a White Screen as the flash light
turnWhiteScreen(true);
}
Any ideas?
P.S.
I imagined that converting .ons to .offs could have worked, but it doesn't.
This has been tested on a HTC 8S and Lumia 820.
It looks like you can't retrieve the acquisition device twice (I'm not sure why), so you should store it in a property:
protected AudioVideoCaptureDevice Device { get; set; }
private async void ButtonTurnOn_Click(object sender, RoutedEventArgs e)
{
var sensorLocation = CameraSensorLocation.Back;
try
{
if (this.Device == null)
{
// get the AudioViceoCaptureDevice
this.Device = await AudioVideoCaptureDevice.OpenAsync(sensorLocation,
AudioVideoCaptureDevice.GetAvailableCaptureResolutions(sensorLocation).First());
}
// turn flashlight on
var supportedCameraModes = AudioVideoCaptureDevice
.GetSupportedPropertyValues(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchMode);
if (supportedCameraModes.ToList().Contains((UInt32)VideoTorchMode.On))
{
this.Device.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.On);
// set flash power to maxinum
this.Device.SetProperty(KnownCameraAudioVideoProperties.VideoTorchPower,
AudioVideoCaptureDevice.GetSupportedPropertyRange(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchPower).Max);
}
else
{
turnWhiteScreen(true);
}
}
catch (Exception ex)
{
// Flashlight isn't supported on this device, instead show a White Screen as the flash light
turnWhiteScreen(true);
}
}
Then, to turn it off:
private void ButtonTurnOff_Click(object sender, RoutedEventArgs e)
{
var sensorLocation = CameraSensorLocation.Back;
try
{
// turn flashlight on
var supportedCameraModes = AudioVideoCaptureDevice
.GetSupportedPropertyValues(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchMode);
if (this.Device != null && supportedCameraModes.ToList().Contains((UInt32)VideoTorchMode.Off))
{
this.Device.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.Off);
}
else
{
turnWhiteScreen(false);
}
}
catch (Exception ex)
{
// Flashlight isn't supported on this device, instead show a White Screen as the flash light
turnWhiteScreen(false);
}
}
Try this one
private static VideoTorchMode _videoTorchMode = VideoTorchMode.Off;
private AudioVideoCaptureDevice _videoRecordingDevice;
Check torch is exist in device.
private async void CheckTorch() {
if(AudioVideoCaptureDevice.AvailableSensorLocations.Contains(CameraSensorLocation.Back) &&
AudioVideoCaptureDevice.GetSupportedPropertyValues(CameraSensorLocation.Back, KnownCameraAudioVideoProperties.VideoTorchMode).ToList().Contains((UInt32)VideoTorchMode.On)) {
var temp = AudioVideoCaptureDevice.GetAvailableCaptureResolutions(CameraSensorLocation.Back)[0];
var resolution = new Windows.Foundation.Size(temp .Width, temp .Height);
_videoRecordingDevice = await AudioVideoCaptureDevice.OpenAsync(CameraSensorLocation.Back, resolution);
}
else
MessageBox.Show("Your device does not support torch");
}
To change torch state
private void SetTorchMode(){
try {
if (BackgroundHandler.Instance.IsBackTorchExist) {
if (_videoTorchMode == VideoTorchMode.Off) {
_videoRecordingDevice.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.On);
_videoTorchMode = VideoTorchMode.On;
}
else {
_videoRecordingDevice.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.Off);
_videoTorchMode = VideoTorchMode.Off;
}
}
}
catch (Exception ex){ }
}
Related
I've followed this article and implemented a Customer Renderer that's used to display a preview video stream from the device's camera.
I intend to capture a frame from the live stream and feed it into Tesseract OCR in order to read a number printed on a ticket.
My problem is that the image from camera preview is almost always not focused. So it is useless for its intended purpose.
An identical question has been asked years ago here in SO, but the accepted answer is not at all helpful for me.
This is the code of OnElementChanged event of CameraPreviewRenderer:
void OnElementChanged(ElementChangedEventArgs<CameraPreview> e)
{
CameraFragment newFragment = null;
if (e.OldElement != null)
{
e.OldElement.PropertyChanged -= OnElementPropertyChanged;
cameraFragment.Dispose();
}
if (e.NewElement != null)
{
this.EnsureId();
e.NewElement.PropertyChanged += OnElementPropertyChanged;
ElevationHelper.SetElevation(this, e.NewElement);
newFragment = new CameraFragment { Element = element };
}
FragmentManager.BeginTransaction()
.Replace(Id, cameraFragment = newFragment, "camera")
.Commit();
ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
}
This is a piece from class CameraFragment. Method RetrieveCameraDevice is the one that opens the camera (I think).
class CameraFragment : Fragment, TextureView.ISurfaceTextureListener
{
CameraDevice device;
CaptureRequest.Builder sessionBuilder;
CameraCaptureSession session;
CameraTemplate cameraTemplate;
CameraManager manager;
....
public async Task RetrieveCameraDevice(bool force = false)
{
if (Context == null || (!force && initTaskSource != null))
{
return;
}
if (device != null)
{
CloseDevice();
}
await RequestCameraPermissions();
if (!cameraPermissionsGranted)
{
return;
}
if (!captureSessionOpenCloseLock.TryAcquire(2500, TimeUnit.Milliseconds))
{
throw new RuntimeException("Timeout waiting to lock camera opening.");
}
IsBusy = true;
cameraId = GetCameraId();
if (string.IsNullOrEmpty(cameraId))
{
IsBusy = false;
captureSessionOpenCloseLock.Release();
Console.WriteLine("No camera found");
}
else
{
try
{
CameraCharacteristics characteristics = Manager.GetCameraCharacteristics(cameraId);
StreamConfigurationMap map = (StreamConfigurationMap)characteristics.Get(CameraCharacteristics.ScalerStreamConfigurationMap);
previewSize = ChooseOptimalSize(map.GetOutputSizes(Class.FromType(typeof(SurfaceTexture))),
texture.Width, texture.Height, GetMaxSize(map.GetOutputSizes((int)ImageFormatType.Jpeg)));
sensorOrientation = (int)characteristics.Get(CameraCharacteristics.SensorOrientation);
cameraType = (LensFacing)(int)characteristics.Get(CameraCharacteristics.LensFacing);
if (Resources.Configuration.Orientation == Android.Content.Res.Orientation.Landscape)
{
texture.SetAspectRatio(previewSize.Width, previewSize.Height);
}
else
{
texture.SetAspectRatio(previewSize.Height, previewSize.Width);
}
initTaskSource = new TaskCompletionSource<CameraDevice>();
Manager.OpenCamera(cameraId, new CameraStateListener
{
OnOpenedAction = device => initTaskSource?.TrySetResult(device),
OnDisconnectedAction = device =>
{
initTaskSource?.TrySetResult(null);
CloseDevice(device);
},
OnErrorAction = (device, error) =>
{
initTaskSource?.TrySetResult(device);
Console.WriteLine($"Camera device error: {error}");
CloseDevice(device);
},
OnClosedAction = device =>
{
initTaskSource?.TrySetResult(null);
CloseDevice(device);
}
}, backgroundHandler);
captureSessionOpenCloseLock.Release();
device = await initTaskSource.Task;
initTaskSource = null;
if (device != null)
{
await PrepareSession();
}
}
catch (Java.Lang.Exception ex)
{
Console.WriteLine("Failed to open camera.", ex);
Available = false;
}
finally
{
IsBusy = false;
}
}
}
I'm supposed to setup the "Focus Mode" in the Camera properties somewhere in this code. But I can't figure out a way to do this.
I am creating a Xamarin Form PCL project for Android and IOS.
Is this possible to display multiple permission at once on the screen? My App is using Location, Storage and Camera permission. From my current code, this is displaying permission popup one by one on the different page like before use of camera i display camera permission popup. As I know three permission required for my App so i want to display a single popup for all three permission.
Below is my code for storage permission.
public static async Task<dynamic> CheckStoragePermission()
{
var result = "";
try
{
var Storagestatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Plugin.Permissions.Abstractions.Permission.Storage);
if (Storagestatus != PermissionStatus.Granted)
{
await Utils.CheckPermissions(Plugin.Permissions.Abstractions.Permission.Storage);
}
}
catch (Exception ex)
{
error(ex.Message, Convert.ToString(ex.InnerException), ex.Source, ex.StackTrace);
}
return result;
}
Hope someone did this before in xamarin forms, I will thank for your help for this.
You could try using the following code to request multiple permissions at one time:
private async void Button_Clicked(object sender, EventArgs e)
{
await GetPermissions();
}
public static async Task<bool> GetPermissions()
{
bool permissionsGranted = true;
var permissionsStartList = new List<Permission>()
{
Permission.Location,
Permission.LocationAlways,
Permission.LocationWhenInUse,
Permission.Storage,
Permission.Camera
};
var permissionsNeededList = new List<Permission>();
try
{
foreach (var permission in permissionsStartList)
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(permission);
if (status != PermissionStatus.Granted)
{
permissionsNeededList.Add(permission);
}
}
}
catch (Exception ex)
{
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(permissionsNeededList.ToArray());
try
{
foreach (var permission in permissionsNeededList)
{
var status = PermissionStatus.Unknown;
//Best practice to always check that the key exists
if (results.ContainsKey(permission))
status = results[permission];
if (status == PermissionStatus.Granted || status == PermissionStatus.Unknown)
{
permissionsGranted = true;
}
else
{
permissionsGranted = false;
break;
}
}
}
catch (Exception ex)
{
}
return permissionsGranted;
}
Good Evening,
I’m doing some troubleshooting on the beginning of my home automation system. I am trying to toggle a relay using a Raspberry PI 3 and Windows IOT in C#. I’ve been playing with the code and I can see the relay toggle once or twice, but then the app crashes. I’m an IOT Noob, so is there something wrong with this code? (Variable names are defined elsewhere and the weird variable names I have below are for my WIP project... I prefer troubleshooting in English)....
private void BtnTempFan_Click(object sender, RoutedEventArgs e)
{
if (BtnTempFan.IsChecked == true)
{
TogglePin(TempFan, TempFan_PIN, BtnTempFan, GpioPinValue.High);
}
else
{
TempFan.Dispose();
}
}
private void TogglePin(GpioPin PinName, int PinNumber, ToggleButton Name, GpioPinValue value)
{
int pinnumber = PinNumber;
GpioPinValue pinvalue;
var gpio = GpioController.GetDefault();
PinName = gpio.OpenPin(pinnumber);
if (gpio == null)
{
PinName = null;
LblError.Text = "We can't find the controller on the device" + PinName;
LblError.Visibility = Visibility.Visible;
return;
}
if (PinName == null)
{
LblError.Text = "We can't find the pin on the device. Pin number " + PinNumber + "does not exist";
LblError.Visibility = Visibility.Visible;
return;
}
if (Name.IsChecked == true)
{
pinvalue = value;
PinName.Write(pinvalue);
PinName.SetDriveMode(GpioPinDriveMode.Output);
}
You don't say what the exception is. However, I believe you are supposed open a GPIO pin only once per app:
var gpio = GpioController.GetDefault();
PinName = gpio.OpenPin(pinnumber);
You have it in a method which is called once per button click. By opening the pin more than once, you are encountering that the pin is already open, and I believe this is what throws an exception and crashes the app.
In my code, I handle pin states in a "driver" class, and have a method called Connect which I call once when starting the application. For example:
public async Task Connect()
{
var gpioController = await GpioController.GetDefaultAsync();
try
{
_openPin = gpioController.OpenPin(_doorMotorOpenPin);
_closePin = gpioController.OpenPin(_doorMotorClosePin);
}
}
This encapsulates the 2 pins: _openPin and _closePin into a class that I can manage the lifecycle of.
Codekaizen is correct. I separated out opening the pin into a method that only gets called once and problem solved.
private void BtnTempFan_Click(object sender, RoutedEventArgs e)
{
if (BtnTempFan.IsChecked == false)
{
TogglePin(TempFan, TempFan_PIN, BtnTempFan, GpioPinValue.High);
}
if (BtnTempFan.IsChecked == true)
{
TogglePin(TempFan, TempFan_PIN, BtnTempFan, GpioPinValue.Low);
}
}
private void InitializePins()
{
var gpio = GpioController.GetDefault();
// Show an error if there is no GPIO controller
if (gpio == null)
{
TempFan = null;
LblError.Text = "We can't find the controller on the device";
LblError.Visibility = Visibility.Visible;
return;
}
TempFan = gpio.OpenPin(TempFan_PIN);
TempFan.SetDriveMode(GpioPinDriveMode.Output);
}
private void TogglePin(GpioPin PinName, int PinNumber, ToggleButton Name, GpioPinValue value)
{
int pinnumber = PinNumber;
GpioPinValue pinvalue;
pinvalue = value;
PinName.Write(pinvalue);
}
When trying to play a sound with CSCore loaded inside a Unity3D project, the editor terminates.
IWaveSource audio = CodecFactory.Instance.GetCodec(pathToMP3File);
ISoundOut device = new WasapiOut();
device.Initialize(audio);
device.Play(); // the call causing the crash
Which output I choose (WasapiOut, DirectSoundOut, WaveOut) does not change the result.
CSCore.dll has been compiled with "Unity 3.5 .net Full Base Class Libraries" target setting in VS 2015. This is the complete script:
using UnityEngine;
using CSCore;
using CSCore.Codecs;
using CSCore.SoundOut;
using System.Threading;
public class CScorePlayback : MonoBehaviour {
static string testAudio = "C:/Path/to/audio.mp3";
IWaveSource audioSource;
ISoundOut audioDevice;
Thread audioThread;
void Start () {
audioThread = new Thread(PlaySoundTest);
audioThread.Start();
}
void PlaySoundTest()
{
audioSource = CodecFactory.Instance.GetCodec(testAudio);
audioDevice = new WaveOut();
audioDevice.Initialize(audioSource);
try
{
audioDevice.Play();
Debug.Log("Sound Played!");
}
catch (System.Exception e)
{
Debug.Log("Error playing sound: " + e.Message);
}
}
void OnDestroy()
{
if (audioThread != null) audioThread.Join();
if (audioDevice != null)
{
audioDevice.Dispose();
}
if (audioSource != null)
{
audioSource.Dispose();
}
}
}
The first thing I would suggest you do is to put the Play() function that crashes in a try catch block.
void Start()
{
IWaveSource audio = CodecFactory.Instance.GetCodec(pathToMP3File);
ISoundOut device = new WasapiOut();
device.Initialize(audio);
try
{
device.Play(); // the call causing the crash
Debug.Log("Sound Played!");
}
catch (System.Exception e)
{
Debug.Log("Error playing sound: " + e.Message);
}
}
If it crashes, please see check if there a message printed out. Edit your question and post the error message.
Now also try to call the whole function in other Thread to make sure that is not the problem. Let me know what happens in the both instances.
void Start()
{
playSound();
}
void playSound()
{
new System.Threading.Thread(___playSound)
{
}.Start();
}
void ___playSound()
{
IWaveSource audio = CodecFactory.Instance.GetCodec(pathToMP3File);
ISoundOut device = new WasapiOut();
device.Initialize(audio);
try
{
device.Play(); // the call causing the crash
Debug.Log("Sound Played!");
}
catch (System.Exception e)
{
Debug.Log("Error playing sound: " + e.Message);
}
}
I try activate a progressbar, while the app is searching for the location (after pressing a button)
how can i solve it the best way?
the best would somehow to get an if else in there, wheater i got (the rigth) data from the geolocator and check that.
private async void Ellipse_Tap (object sender, System.Windows.Input.GestureEventArgs e)
{
Geolocator geolocator = new Geolocator();
//Set his accuracy in Meters
geolocator.DesiredAccuracyInMeters = 50;
try
{
//The await guarantee the calls to be returned on the thread from which they were called
//Since it is call directly from the UI thread, the code is able to access and modify the UI directly when the call returns.
Geoposition geoposition = await geolocator.GetGeopositionAsync(
maximumAge: TimeSpan.FromMinutes(5),
timeout: TimeSpan.FromSeconds(10)
);
//Relativer Nullpunkt
delta_y = geoposition.Coordinate.Latitude - y;
delta_x = geoposition.Coordinate.Longitude - x;
Path.Visibility = Visibility.Visible;
}
//If an error is catch 2 are the main causes: the first is that you forgot to includ ID_CAP_LOCATION in your app manifest.
//The second is that the user doesn't turned on the Location Services
catch (Exception ex)
{
if ((uint)ex.HResult == 0x80004004)
{
MessageBox.Show("Location is disabled in phone settings.");
return;
//Application.Current.Terminate();
}
//else
{
// something else happened during the acquisition of the location
}
}
}
Assuming you are using the ProgressIndicator in the SystemTry, Add the following to the OnNavigatedTo Method
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
SystemTray.ProgressIndicator = new ProgressIndicator();
}
Then create this method to set the ProgressIndicator.
private void DisplayProgressIndicator(bool isvisible, string message = "")
{
SystemTray.ProgressIndicator.Text = message;
SystemTray.ProgressIndicator.IsIndeterminate = isvisible;
SystemTray.ProgressIndicator.IsVisible = isvisible;
}
Then use the method created in the Eclips_Tap method.
private async void Ellipse_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Geolocator geolocator = new Geolocator();
geolocator.DesiredAccuracyInMeters = 50;
try
{
DisplayProgressIndicator(true, "Finding current location..."); // < SET THE PROGRESS INDICATOR
Geoposition geoposition = await geolocator.GetGeopositionAsync(
maximumAge: TimeSpan.FromMinutes(5),
timeout: TimeSpan.FromSeconds(10)
);
delta_y = geoposition.Coordinate.Latitude - y;
delta_x = geoposition.Coordinate.Longitude - x;
Path.Visibility = Visibility.Visible;
DisplayProgressIndicator(false); // << UNSET PROGRESS INDICATOR
}
catch (Exception ex)
{
if ((uint)ex.HResult == 0x80004004)
{
MessageBox.Show("Location is disabled in phone settings.");
return;
}
}
}
Hope this helps..