public async Task <List <TeslaEvent> > ParseFiles(IReadOnlyList <StorageFile> files) { var result = new List <TeslaEvent>(); var eventMetadataFiles = files.Where(f => f.FileType.Equals(EventMetadataFileExtension)); var videoFiles = files.Where(f => f.FileType.Equals(EventVideoFileExtension)); var thumbnailFiles = files.Where(f => f.FileType.Equals(EventThumbnailFileExtension)); foreach (var metadataFile in eventMetadataFiles) { var eventText = await FileIO.ReadTextAsync(metadataFile); try { TeslaEvent teslaEvent = ParseEvent(files, metadataFile.Path, eventText); result.Add(teslaEvent); } catch { _failedFiles++; } ProgressUpdated?.Invoke(this, new ProgressEventArgs(result.Count, _failedFiles, eventMetadataFiles.Count())); } return(result.OrderBy(r => r.Timestamp).ToList()); }
public TeslaEventMapElementViewModel(TeslaEvent model) { Model = model; _fileSystemService = new FileSystemService(); Location = new Geopoint(new BasicGeoposition() { Latitude = model.EstimatedLatitude, Longitude = model.EstimatedLongitude }); this.PropertyChanged += TeslaEventMapElementViewModel_PropertyChanged; }
/// <summary> /// Reads video metadata properties from filesystem and populates properties in the event. /// </summary> /// <remarks>Costly operation. Don't do this for all events at the time of scanning through the top directory. Populate metadata only when user needs it.</remarks> public async Task <TeslaEvent> PopulateEventMetadata(TeslaEvent teslaEvent) { foreach (var segment in teslaEvent.Segments) { foreach (var clip in segment.Clips.Cast <Clip>()) { StorageFile storageFile = (StorageFile)clip.ClipFile; IDictionary <string, object> retrieveProperties = await storageFile.Properties.RetrievePropertiesAsync(new string[] { VideoFrameRatePropertyName, MediaDurationPropertyName }); clip.FrameRate = ((uint)retrieveProperties[VideoFrameRatePropertyName]); var duration = ((ulong)retrieveProperties[MediaDurationPropertyName]); clip.Duration = TimeSpan.FromTicks((long)duration); } segment.MaxClipFrameDuration = segment.Clips.Max(c => (int)c.FrameDuration); segment.MaxClipDuration = segment.Clips.Max(c => c.Duration); } return(teslaEvent); }
private async void ViewVideoCommandExecute(object obj) { TeslaEvent teslaEvent = ((TeslaEventMapElementViewModel)obj).Model; ViewFrame.Navigate(typeof(EventDetailsPage), await _fileSystemService.PopulateEventMetadata(teslaEvent)); }
private TeslaEvent ParseEvent(IReadOnlyList <StorageFile> files, string filePath, string eventText) { var folderName = _eventFolderNameRegex.Match(filePath).Groups["EventFolderName"].Value; EventStoreLocation storeLocation = EventStoreLocation.Unkown; if (filePath.Contains(SavedClipsFolderName, StringComparison.InvariantCultureIgnoreCase)) { storeLocation = EventStoreLocation.SavedClip; } else if (filePath.Contains(SentryClipsFolderName, StringComparison.InvariantCultureIgnoreCase)) { storeLocation = EventStoreLocation.SentryClip; } var metadata = JsonSerializer.Deserialize <TeslaEventJson>(eventText); var teslaEvent = new TeslaEvent(metadata); teslaEvent.StoreLocation = storeLocation; teslaEvent.FolderPath = filePath; var thumbnailFile = files.FirstOrDefault(f => f.FileType.Equals(EventThumbnailFileExtension) && f.Path.Contains(folderName)); if (thumbnailFile != null) { teslaEvent.ThumbnailFile = thumbnailFile; teslaEvent.ThumbnailPath = thumbnailFile.Path; } var results = files.Where(f => f.Path.Contains(folderName) && f.FileType.Equals(EventVideoFileExtension)).GroupBy( f => ParseTimestampFromFilename(f.Name), f => f, (key, g) => new { SegmentTimestamp = key, ClipFiles = g.ToList() }); foreach (var fileGroup in results.OrderBy(r => r.SegmentTimestamp)) { var eventSegment = new EventSegment(); eventSegment.SegmentTimestamp = fileGroup.SegmentTimestamp; eventSegment.Clips = new List <Clip>(); foreach (var clipFile in fileGroup.ClipFiles) { eventSegment.Clips.Add(ParseClipFile(clipFile)); } teslaEvent.Segments.Add(eventSegment); } // Link event timestamps for (int i = 0; i < teslaEvent.Segments.Count - 1; i++) { teslaEvent.Segments[i].NextSegmentTimestamp = teslaEvent.Segments[i + 1].SegmentTimestamp; } // Sets flag if a segment period contains the event timestamp var hotSegment = teslaEvent.Segments.Where(s => s.SegmentTimestamp < teslaEvent.Timestamp && (!s.NextSegmentTimestamp.HasValue || teslaEvent.Timestamp < s.NextSegmentTimestamp.Value)).FirstOrDefault(); if (hotSegment != null) { hotSegment.ContainsEventTimestamp = true; } return(teslaEvent); }