/// <summary> /// Converts a collection of stream strings to DataTypeIDs (Guids) that can be played back to the Kinect sensor /// </summary> /// <param name="streamNames">Collection of strings to convert to Guids</param> /// <returns>Collection of Guids, which includes DataTypeIDs for each stream</returns> internal static HashSet <Guid> ConvertStreamsToPlaybackGuids(IEnumerable <string> streamNames) { if (streamNames == null) { throw new ArgumentNullException("streamNames"); } if (streamNames.Count <string>() == 0) { throw new InvalidOperationException(Strings.ErrorNoStreams); } HashSet <Guid> streamGuids = StreamSupport.ConvertStreamsToGuids(streamNames); // remove body streams from the playback collection if (streamGuids.Contains(KStudioEventStreamDataTypeIds.Body)) { Console.WriteLine(Strings.WarningIgnoreBodyDuringPlayback); streamGuids.Remove(KStudioEventStreamDataTypeIds.Body); } if (streamGuids.Contains(KStudioEventStreamDataTypeIds.BodyIndex)) { Console.WriteLine(Strings.WarningIgnoreBodyIndexDuringPlayback); streamGuids.Remove(KStudioEventStreamDataTypeIds.BodyIndex); } return(streamGuids); }
/// <summary> /// Converts a collection of stream strings to DataTypeIDs (Guids) /// </summary> /// <param name="streamNames">Collection of strings to convert to Guids</param> /// <returns>Collection of Guids, which includes DataTypeIDs for each stream</returns> internal static HashSet <Guid> ConvertStreamsToGuids(IEnumerable <string> streamNames) { if (streamNames == null) { throw new ArgumentNullException("streamNames"); } if (streamNames.Count <string>() == 0) { throw new InvalidOperationException(Strings.ErrorNoStreams); } HashSet <Guid> streamGuids = new HashSet <Guid>(); foreach (string streamName in streamNames) { streamGuids.Add(StreamSupport.ConvertStreamStringToGuid(streamName)); } return(streamGuids); }
/// <summary> /// Updates (add/edits) stream-level metadata in an event file /// </summary> /// <param name="client">KStudioClient to use for accessing the event file</param> /// <param name="fileName">Path to event file</param> /// <param name="streamName">Name of stream which should contain the metadata</param> /// <param name="type">Type of metadata to update (Public or Personal)</param> /// <param name="key">Key of metadata object to add/edit</param> /// <param name="value">Value of metadata object to add/edit</param> /// <returns>String which contains the updated contents of the target metadata object</returns> public static string UpdateStreamMetadata(KStudioClient client, string fileName, string streamName, KStudioMetadataType type, string key, object value) { if (client == null) { throw new ArgumentNullException("client"); } if (string.IsNullOrEmpty(fileName)) { throw new ArgumentNullException("fileName"); } if (string.IsNullOrEmpty(streamName)) { throw new ArgumentNullException("streamName"); } string metadataText = string.Empty; using (KStudioEventFile file = client.OpenEventFileForEdit(fileName)) { // find the stream in the file and alter its metadata Guid dataTypeId = StreamSupport.ConvertStreamStringToGuid(streamName); if (dataTypeId == KStudioEventStreamDataTypeIds.Null) { throw new InvalidOperationException(Strings.ErrorNullStream); } KStudioEventStream stream = file.EventStreams.FirstOrDefault(s => s.DataTypeId == dataTypeId); if (stream != null) { KStudioMetadata metadata = stream.GetMetadata(type); Metadata.AlterMetadata(metadata, key, value); metadataText = Metadata.GetMetadataAsText(metadata, type, stream.DataTypeName); } } return(metadataText); }
/// <summary> /// Records streams from the Kinect sensor to an event file /// </summary> /// <param name="client">KStudioClient which is connected to the Kinect service</param> /// <param name="filePath">Path to new event file which will be created for recording</param> /// <param name="duration">How long the recording should last before being stopped</param> /// <param name="streamNames">Collection of streams to include in the recording</param> public static void RecordClip(KStudioClient client, string filePath, TimeSpan duration, IEnumerable <string> streamNames) { if (client == null) { throw new ArgumentNullException("client"); } if (!client.IsServiceConnected) { throw new InvalidOperationException(Strings.ErrorNotConnected); } if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException("filePath"); } HashSet <Guid> streamDataTypeIds = new HashSet <Guid>(); KStudioEventStreamSelectorCollection streamCollection = new KStudioEventStreamSelectorCollection(); KStudioRecording recording = null; // decide which streams to record if (streamNames != null && streamNames.Count <string>() > 0) { streamDataTypeIds = StreamSupport.ConvertStreamsToGuids(streamNames); StreamSupport.VerifyStreamsForRecordAndPlayback(streamDataTypeIds); } else { if (Path.GetExtension(filePath).ToLower().Equals(Strings.XrfExtension)) { streamDataTypeIds.Add(KStudioEventStreamDataTypeIds.RawIr); } else { streamDataTypeIds.Add(KStudioEventStreamDataTypeIds.Ir); streamDataTypeIds.Add(KStudioEventStreamDataTypeIds.Depth); streamDataTypeIds.Add(KStudioEventStreamDataTypeIds.Body); streamDataTypeIds.Add(KStudioEventStreamDataTypeIds.BodyIndex); } } // verify streams are recordable by the Kinect sensor foreach (Guid stream in streamDataTypeIds) { KStudioEventStream eventStream = client.GetEventStream(stream, KStudioEventStreamSemanticIds.KinectDefaultSensorProducer); if (!eventStream.IsRecordable) { throw new InvalidOperationException(string.Format(Strings.ErrorRecordingStreamNotSupported, StreamSupport.ConvertStreamGuidToString(stream))); } streamCollection.Add(stream); } // fix file extension, if necessary if (streamDataTypeIds.Contains(KStudioEventStreamDataTypeIds.RawIr) && Path.GetExtension(filePath).ToUpperInvariant().Equals(Strings.XefExtension.ToUpperInvariant())) { Path.ChangeExtension(filePath, Strings.XrfExtension); } // attempt to record streams for the specified duration try { recording = client.CreateRecording(filePath, streamCollection); } catch (Exception) { //K4W supports uncompressed and compressed color, so if we get an error, try recording the other type streamCollection = StreamSupport.CreateStreamCollection(streamDataTypeIds, true); recording = client.CreateRecording(filePath, streamCollection); } using (recording) { recording.StartTimed(duration); while (recording.State == KStudioRecordingState.Recording) { Thread.Sleep(500); } if (recording.State == KStudioRecordingState.Error) { throw new InvalidOperationException(Strings.ErrorRecordingFailed); } } }
/// <summary> /// Verifies that the streams selected for playback exist in the file and are capable of being played on the service /// </summary> /// <param name="client">KStudioClient which is connected to the Kinect service</param> /// <param name="filePath">Path to file that will be played back</param> /// <param name="playbackStreams">Collection of streams which have been selected for playback</param> private static void VerifyStreamsForPlayback(KStudioClient client, string filePath, IEnumerable <Guid> playbackStreams) { if (client == null) { throw new ArgumentNullException("client"); } if (!client.IsServiceConnected) { throw new InvalidOperationException(Strings.ErrorNotConnected); } if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException("filePath"); } if (playbackStreams == null) { throw new ArgumentNullException("playbackStreams"); } // verify stream exists in the file using (KStudioEventFile file = client.OpenEventFile(filePath)) { HashSet <Guid> fileStreams = new HashSet <Guid>(); foreach (KStudioEventStream stream in file.EventStreams) { fileStreams.Add(stream.DataTypeId); } if (!fileStreams.IsSupersetOf(playbackStreams)) { Guid invalidStream = playbackStreams.First(x => !fileStreams.Contains(x)); throw new InvalidOperationException(string.Format(Strings.ErrorPlaybackStreamNotInFile, StreamSupport.ConvertStreamGuidToString(invalidStream))); } } // verify stream is supported for playback by the Kinect sensor foreach (Guid stream in playbackStreams) { KStudioEventStream eventStream = client.GetEventStream(stream, KStudioEventStreamSemanticIds.KinectDefaultSensorConsumer); if (!eventStream.IsPlaybackable) { throw new InvalidOperationException(string.Format(Strings.ErrorPlaybackStreamNotSupported, StreamSupport.ConvertStreamGuidToString(stream))); } } }
/// <summary> /// Plays an event file to the Kinect service /// </summary> /// <param name="client">KStudioClient which is connected to the Kinect service</param> /// <param name="filePath">Path to event file which is targeted for playback</param> /// <param name="streamNames">Collection of streams to include in the playback session</param> /// <param name="loopCount">Number of times the playback should be repeated before stopping</param> public static void PlaybackClip(KStudioClient client, string filePath, IEnumerable <string> streamNames, uint loopCount) { if (client == null) { throw new ArgumentNullException("client"); } if (!client.IsServiceConnected) { throw new InvalidOperationException(Strings.ErrorNotConnected); } if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException("filePath"); } KStudioPlayback playback = null; // determine if all specified streams are valid for playback if (streamNames.Count <string>() > 0) { HashSet <Guid> playbackDataTypeIds = StreamSupport.ConvertStreamsToPlaybackGuids(streamNames); StreamSupport.VerifyStreamsForRecordAndPlayback(playbackDataTypeIds); Playback.VerifyStreamsForPlayback(client, filePath, playbackDataTypeIds); try { KStudioEventStreamSelectorCollection streams = StreamSupport.CreateStreamCollection(playbackDataTypeIds, false); playback = client.CreatePlayback(filePath, streams); } catch (Exception) { //K4W supports uncompressed and compressed color, so if we get an error, try playing the other type KStudioEventStreamSelectorCollection streams = StreamSupport.CreateStreamCollection(playbackDataTypeIds, true); playback = client.CreatePlayback(filePath, streams); } } else { playback = client.CreatePlayback(filePath); } // begin playback using (playback) { playback.EndBehavior = KStudioPlaybackEndBehavior.Stop; // this is the default behavior playback.Mode = KStudioPlaybackMode.TimingEnabled; // this is the default behavior playback.LoopCount = loopCount; playback.Start(); while (playback.State == KStudioPlaybackState.Playing) { Thread.Sleep(500); } if (playback.State == KStudioPlaybackState.Error) { throw new InvalidOperationException(Strings.ErrorPlaybackFailed); } } }