/// <summary> /// Instantiates a new InteractionStream, feeds this InteractionStream with Skeleton- and DepthData and subscribes to the InteractionFrameReady event. /// </summary> /// <param name="kinectSensor">The Kinect sensor passed to the interaction stream instance.</param> /// <param name="interactionClient">The interaction client passed to the interaction stream instance.</param> /// <returns>An UserInfo stream that contains an action that disposes the interaction stream when the observable is disposed.</returns> public static IObservable <UserInfo[]> GetUserInfoObservable(this KinectSensor kinectSensor, IInteractionClient interactionClient) { if (kinectSensor == null) { throw new ArgumentNullException("kinect"); } if (interactionClient == null) { throw new ArgumentNullException("interactionClient"); } if (!kinectSensor.DepthStream.IsEnabled) { throw new InvalidOperationException("The depth stream is not enabled, but mandatory."); } if (!kinectSensor.SkeletonStream.IsEnabled) { throw new InvalidOperationException("The skeleton stream is not enabled, but mandatory."); } return(Observable.Create <UserInfo[]>(observer => { var stream = new InteractionStream(kinectSensor, interactionClient); var obs = kinectSensor.GetAllFramesReadyObservable() .SelectStreams((_, __) => Tuple.Create(_.Timestamp, __.Timestamp)) .Subscribe(_ => { stream.ProcessSkeleton(_.Item3, kinectSensor.AccelerometerGetCurrentReading(), _.Item4.Item1); stream.ProcessDepth(_.Item2, _.Item4.Item2); }); stream.GetInteractionFrameReadyObservable() .SelectUserInfo() .Subscribe(_ => observer.OnNext(_)); return new Action(() => { obs.Dispose(); stream.Dispose(); }); })); }