/// <summary> /// Called to retry finding a sensor when the SensorConflict or /// NoAvailableSensors flags are set. /// </summary> public void TryResolveConflict() { using (var callbackLock = new CallbackLock(_lockObject)) { TryFindAndStartKinect(callbackLock); } }
private void OnKinectSensorsStatusChanged(object sender, StatusChangedEventArgs e) { if (e != null) { if ((e.Sensor == this.Kinect) || (this.Kinect == null)) { using (var callbackLock = new CallbackLock(_lockObject)) { // Check again in case things changed while we were // waiting on the lock. if ((e.Sensor == this.Kinect) || (this.Kinect == null)) { // Something about our sensor changed or we don't have a sensor. TryFindAndStartKinect(callbackLock); } } } } }
/// <summary> /// Gives up the current sensor if it has one. Stops watching for new sensors. /// </summary> public void Stop() { if (_isStarted) { using (var callbackLock = new CallbackLock(_lockObject)) { // Check again in case someone stopped us while // we were waiting on the lock. if (_isStarted) { _isStarted = false; KinectSensor.KinectSensors.StatusChanged -= OnKinectSensorsStatusChanged; SetSensorAndStatus(callbackLock, null, ChooserStatus.None); } } } }
/// <summary> /// Starts choosing a sensor. In the typical case, a sensor will /// be found and events will be fired before this function returns. /// </summary> public void Start() { if (!_isStarted) { using (var callbackLock = new CallbackLock(_lockObject)) { // Check again in case someone else started while // we were waiting on the lock. if (!_isStarted) { _isStarted = true; KinectSensor.KinectSensors.StatusChanged += OnKinectSensorsStatusChanged; TryFindAndStartKinect(callbackLock); } } } }
/// <summary> /// Helper to update our external status. /// </summary> /// <param name="callbackLock">Used to delay notifications to the client until after we exit the lock.</param> /// <param name="newKinect">The new sensor</param> /// <param name="newChooserStatus">The status we want to report to clients</param> private void SetSensorAndStatus(CallbackLock callbackLock, KinectSensor newKinect, ChooserStatus newChooserStatus) { KinectSensor oldKinect = Kinect; if (oldKinect != newKinect) { if (oldKinect != null) { oldKinect.Stop(); } Kinect = newKinect; callbackLock.LockExit += () => this._kinectSensorChangedContextWrapper.Invoke(this, new KinectSensorChangedEventArgs <KinectSensor>(oldKinect, newKinect)); callbackLock.LockExit += () => RaisePropertyChanged("Kinect"); } if (Status != newChooserStatus) { Status = newChooserStatus; callbackLock.LockExit += () => RaisePropertyChanged("Status"); } }
/// <summary> /// Called when we don't have a sensor or possibly have the wrong sensor /// and we want to see if we can get one. /// </summary> private void TryFindAndStartKinect(CallbackLock callbackLock) { if (!_isStarted) { // We aren't started so we don't need to be finding anything. Debug.Assert(Status == ChooserStatus.None, "isStarted and Status out of sync"); return; } if (Kinect != null && Kinect.Status == KinectStatus.Connected) { if (_requiredConnectionId == null) { // we already have an appropriate sensor Debug.Assert(Status == ChooserStatus.SensorStarted, "Chooser in unexpected state"); return; } if (Kinect.DeviceConnectionId == _requiredConnectionId) { // we already have the requested sensor Debug.Assert(Status == ChooserStatus.SensorStarted, "Chooser in unexpected state"); return; } } KinectSensor newSensor = null; ChooserStatus newStatus = 0; if (KinectSensor.KinectSensors.Count == 0) { newStatus = ChooserStatus.NoAvailableSensors; } else { foreach (KinectSensor sensor in KinectSensor.KinectSensors) { if (_requiredConnectionId != null && sensor.DeviceConnectionId != _requiredConnectionId) { // client has set a required connection Id and this // sensor does not have that Id newStatus |= ChooserStatus.NoAvailableSensors; continue; } if (sensor.Status != KinectStatus.Connected) { // Sensor is in some unusable state newStatus |= GetErrorStatusFromSensor(sensor); continue; } if (sensor.IsRunning) { // Sensor is already in use by this application newStatus |= ChooserStatus.NoAvailableSensors; continue; } // There is a potentially available sensor, try to start it try { sensor.Start(); } catch (IOException) { // some other app has this sensor. newStatus |= ChooserStatus.SensorConflict; continue; } catch (InvalidOperationException) { // In multi-proc scenarios, this is getting thrown at the start before we see IOException. Need to understand. // some other app has this sensor. newStatus |= ChooserStatus.SensorConflict; continue; } // Woo hoo, we have a started sensor. newStatus = ChooserStatus.SensorStarted; newSensor = sensor; break; } } SetSensorAndStatus(callbackLock, newSensor, newStatus); }