public InsertDescriptionHistoryItem(ObservableCollection<Description> allDescriptions, ObservableCollection<Description> descriptions, Description element) { _allDescriptions = allDescriptions; _descriptions = descriptions; _element = element; }
public SpaceRecordingViewModel(Space space, Project project) { InitCommands(); _setDurationBasedOnWpm = false; _description = null; Space = space; Project = project; ResetElapsedTime(); SetTimeLeft(); RecordDuration = Space.Duration; MaxWordsPerMinute = DefaultMaxWordsPerMinute; MinWordsPerMinute = DefaultMinWordsPerMinute; _recorder = new DescriptionRecorder(); _recorder.DescriptionRecorded += (sender, args) => Description = args.Value; _player = new DescriptionPlayer(); _player.DescriptionFinishedPlaying += (sender, args) => CommandManager.InvalidateRequerySuggested(); _recordingTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(CountdownTimerIntervalMsec) }; _recordingTimer.Tick += RecordingTimerOnTick; _stopwatch = new Stopwatch(); CountdownViewModel = new CountdownViewModel(); CountdownViewModel.CountdownFinished += (sender, args) => StartRecording(); SetWpmValuesBasedOnSpaceText(); }
/// <summary> /// Creates a waveform image from a description's audio file. Uses the description.Waveform /// property to obtain the data for the waveform. /// </summary> /// <param name="description">Description to create waveform for.</param> /// <param name="bounds">Size of the image to create.</param> /// <param name="canvasWidth">The width of the canvas that will contain this image.</param> /// <returns>A bitmap of the description's waveform.</returns> public static RenderTargetBitmap CreateDescriptionWaveForm(Description description, Rect bounds, double canvasWidth) { if (bounds.Width <= 1 || bounds.Height <= 1) return null; if (description.Waveform == null) description.GenerateWaveForm(); var drawingVisual = new DrawingVisual(); using (var dc = drawingVisual.RenderOpen()) { var data = description.Waveform.Data; double samplesPerPixel = Math.Max(data.Count / canvasWidth, 1); double middle = bounds.Height / 2; double yscale = middle; double samplesPerSecond = (description.Waveform.Header.SampleRate * (description.Waveform.Header.BlockAlign / (double)description.Waveform.SampleRatio)); var waveformLineGroup = new GeometryGroup(); int endPixel = (int)bounds.Width; for (int pixel = 0; pixel <= endPixel; pixel++) { double offsetTime = (description.Duration / (bounds.Width * Milliseconds.PerSecond)) * pixel; double sampleStart = Math.Max(samplesPerSecond * offsetTime, 0); if (sampleStart + samplesPerPixel < data.Count) { var range = data.GetRange((int)sampleStart, (int)samplesPerPixel); double max = (double)range.Max() / short.MaxValue; double min = (double)range.Min() / short.MaxValue; waveformLineGroup.Children.Add(new LineGeometry { StartPoint = new Point(pixel, middle + max * yscale), EndPoint = new Point(pixel, middle + min * yscale), }); } } waveformLineGroup.Freeze(); dc.DrawGeometry(Brushes.Black, LinePen, waveformLineGroup); } var bitmap = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, DefaultDpi, DefaultDpi, PixelFormats.Pbgra32); bitmap.Render(drawingVisual); bitmap.Freeze(); description.WaveformImage = bitmap; return bitmap; }
public void AddDescriptionEventHandlers(Description description) { /* Draw the description only if the video is loaded, because there is currently * an issue with the video loading after the descriptions are added from an * opened project. */ if (_viewmodel.MediaViewModel.MediaVideo.CurrentState != LiveDescribeVideoStates.VideoNotLoaded) SetDescriptionLocation(description); description.NavigateToRequested += (sender1, e1) => { UpdateMarkerPosition((description.StartInVideo / _videoDurationMsec) * (AudioCanvas.Width) - MarkerOffset); UpdateVideoPosition((int)description.StartInVideo); //Scroll 1 second before the start in video of the space TimeLineScrollViewer.ScrollToHorizontalOffset((AudioCanvas.Width / _videoDurationMsec) * (description.StartInVideo - 1000)); }; description.PropertyChanged += (sender, args) => { if (args.PropertyName == "IsSelected") Dispatcher.Invoke(() => DescriptionCanvas.Draw()); }; description.PropertyChanged += (o, e) => { if (e.PropertyName == "StartInVideo" || e.PropertyName == "EndInVideo" || e.PropertyName == "SetStartAndEndInVideo") SetDescriptionLocation(description); }; }
public bool CanPlay(Description description) { lock (_playLock) { return !IsPlaying; } }
/// <summary> /// Determines if the given description can play at the given time. /// </summary> /// <param name="description">The description to check.</param> /// <param name="videoPositionMilliseconds">The time to check the description against.</param> /// <returns>Whether the description can be played or not.</returns> public bool CanPlayInVideo(Description description, double videoPositionMilliseconds) { lock (_playLock) { double offset = videoPositionMilliseconds - description.StartInVideo; //if it is equal then the video time matches when the description should start dead on return CanPlay(description) && ((!description.IsExtendedDescription && 0 <= offset && offset < description.WaveFileDuration) || (description.IsExtendedDescription && 0 <= offset && offset < LiveDescribeConstants.ExtendedDescriptionStartIntervalMax)); } }
private void SetDescriptionLocation(Description description) { SetIntervalLocation(description, DescriptionCanvas); }
public void StopRecording() { lock (_recordingAccessLock) { Log.Info("Finished Recording"); MicrophoneStream.StopRecording(); _waveWriter.Dispose(); _waveWriter = null; var read = new WaveFileReader(_recordedFile); var d = new Description(_recordedFile, 0, read.TotalTime.TotalMilliseconds, _descriptionStartTime, _recordExtended); OnDescriptionRecorded(d); read.Dispose(); IsRecording = false; } }
private void AddDescriptionEventHandlers(Description description) { description.MouseDown += (sender1, e1) => { //Add mouse down event on every description here if (Mouse.LeftButton == MouseButtonState.Pressed) { if (description.IsExtendedDescription) { _intervalInfoListViewModel.SelectedExtendedDescription = description; SpaceAndDescriptionsTabControl.ExtendedDescriptionsListView.ScrollToCenterOfView(description); } else { _intervalInfoListViewModel.SelectedRegularDescription = description; SpaceAndDescriptionsTabControl.DescriptionsListView.ScrollToCenterOfView(description); } } }; description.NavigateToRequested += (sender1, e1) => { if (description.IsExtendedDescription) { _intervalInfoListViewModel.SelectedExtendedDescription = description; SpaceAndDescriptionsTabControl.ExtendedDescriptionsListView.ScrollToCenterOfView(description); } else { _intervalInfoListViewModel.SelectedRegularDescription = description; SpaceAndDescriptionsTabControl.DescriptionsListView.ScrollToCenterOfView(description); } }; TimelineControl.AddDescriptionEventHandlers(description); }
private void ImportAudioDescription() { var desc = new Description(ProjectFile.FromAbsolutePath(DescriptionPath, _projectManager.Project.Folders.Project), 0, DescriptionLengthInMilliseconds, StartInVideo, false) { Text = Text }; _projectManager.AddDescriptionAndTrackForUndo(desc); var handler = OnImportDescription; if (handler != null) handler(this, EventArgs.Empty); }
public void AddDescription(Description desc) { if (Defines.Zagga && desc.IsExtendedDescription) return; AllDescriptions.Add(desc); if (!desc.IsExtendedDescription) RegularDescriptions.Add(desc); else ExtendedDescriptions.Add(desc); }
private void Unselect(ref Description description) { description.IsSelected = false; description.PropertyChanged -= DescriptionFinishedPlaying; description = null; }
/// <summary> /// Plays a description, beginning from a time offset from the beginning of the wav file. /// </summary> /// <param name="description">Description to play.</param> /// <param name="offset">How far into the description to start playing at.</param> private void PlayAtOffset(Description description, double offset) { lock (_playLock) { var reader = new WaveFileReader(description.AudioFile); //reader.WaveFormat.AverageBytesPerSecond/ 1000 = Average Bytes Per Millisecond //AverageBytesPerMillisecond * (offset + StartWaveFileTime) = amount to play from reader.Seek((long)((reader.WaveFormat.AverageBytesPerSecond / 1000) * (offset + description.StartWaveFileTime)), SeekOrigin.Begin); var descriptionStream = new WaveOutEvent(); descriptionStream.PlaybackStopped += DescriptionStream_PlaybackStopped; descriptionStream.Init(reader); DescriptionStream = descriptionStream; _playingDescription = description; IsPlaying = true; _playingDescription.IsPlaying = true; descriptionStream.Play(); } }
private void OnDescriptionFinishedPlaying(Description description) { EventHandler<EventArgs<Description>> handler = DescriptionFinishedPlaying; if (handler != null) handler(this, new EventArgs<Description>(description)); }
/// <summary> /// Plays the given description at the given video time. /// </summary> /// <param name="description">Description to play.</param> /// <param name="videoPositionMilliseconds">Time to the description at.</param> public void PlayInVideo(Description description, double videoPositionMilliseconds) { lock (_playLock) { if (IsPlaying) return; double offset = videoPositionMilliseconds - description.StartInVideo; PlayAtOffset(description, offset); } }
public void Play(Description description) { lock (_playLock) { PlayAtOffset(description, 0); } }
private void AddDescriptionEventHandlers(Description description) { /* Draw the description only if the video is loaded, because there is currently * an issue with the video loading after the descriptions are added from an * opened project. */ if (_videoMedia.CurrentState != LiveDescribeVideoStates.VideoNotLoaded) DrawDescribableInterval(description); description.PropertyChanged += (o, args) => { if (args.PropertyName.Equals("StartInVideo") || args.PropertyName.Equals("EndInVideo") || args.PropertyName.Equals("SetStartAndEndInVideo")) DrawDescribableInterval(description); }; description.MouseDown += (sender1, e1) => { //Add mouse down event on every description here if (Mouse.LeftButton == MouseButtonState.Pressed) { if (description.IsExtendedDescription) { _descriptionInfoTabViewModel.SelectedExtendedDescription = description; SpaceAndDescriptionsTabControl.ExtendedDescriptionsListView.ScrollToCenterOfView(description); } else { _descriptionInfoTabViewModel.SelectedRegularDescription = description; SpaceAndDescriptionsTabControl.DescriptionsListView.ScrollToCenterOfView(description); } } }; description.NavigateToRequested += (sender1, e1) => { UpdateMarkerPosition((description.StartInVideo / _videoDuration) * (_audioCanvas.Width) - MarkerOffset); UpdateVideoPosition((int)description.StartInVideo); //Scroll 1 second before the start in video of the space TimeLineScrollViewer.ScrollToHorizontalOffset((_audioCanvas.Width / _videoDuration) * (description.StartInVideo - 1000)); if (description.IsExtendedDescription) { _descriptionInfoTabViewModel.SelectedExtendedDescription = description; SpaceAndDescriptionsTabControl.ExtendedDescriptionsListView.ScrollToCenterOfView(description); } else { _descriptionInfoTabViewModel.SelectedRegularDescription = description; SpaceAndDescriptionsTabControl.DescriptionsListView.ScrollToCenterOfView(description); } }; }
private void Select(ref Description description) { description.IsSelected = true; //we don't want the text to appear in the textbox if a description is playing description.PropertyChanged += DescriptionFinishedPlaying; if (description.IsExtendedDescription) { _selectedExtendedDescription = description; TabSelectedIndex = ExtendedDescriptionTab; } else { _selectedRegularDescription = description; TabSelectedIndex = RegularDescriptionTab; } SelectedItem = description; }
public void RemoveDescriptionAndTrackForUndo(Description desc) { if (desc.IsExtendedDescription) { ExtendedDescriptions.Remove(desc); _undoRedoManager.InsertDescriptionForDeleteUndoRedo(AllDescriptions, ExtendedDescriptions, desc); } else if (!desc.IsExtendedDescription) { RegularDescriptions.Remove(desc); _undoRedoManager.InsertDescriptionForDeleteUndoRedo(AllDescriptions, RegularDescriptions, desc); } AllDescriptions.Remove(desc); }
public void SelectDescription(Description description, Point clickPoint) { description.IsSelected = true; description.MouseDownCommand.Execute(); MouseSelection = new CanvasMouseSelection(IntervalMouseAction.Dragging, description, XPosToMilliseconds(clickPoint.X) - description.StartInVideo); CaptureMouse(); }
private void RemoveDescriptionEventHandlers(Description desc) { desc.DeleteRequested -= DeleteDescription; }
public void AddDescriptionAndTrackForUndo(Description desc) { if (Defines.Zagga && desc.IsExtendedDescription) return; AllDescriptions.Add(desc); if (!desc.IsExtendedDescription) { RegularDescriptions.Add(desc); _undoRedoManager.InsertDescriptionForInsertUndoRedo(AllDescriptions, RegularDescriptions, desc); } else if (desc.IsExtendedDescription) { ExtendedDescriptions.Add(desc); _undoRedoManager.InsertDescriptionForInsertUndoRedo(AllDescriptions, ExtendedDescriptions, desc); } }
private void OnDescriptionRecorded(Description d) { EventHandler<EventArgs<Description>> handler = DescriptionRecorded; if (handler != null) handler(this, new EventArgs<Description>(d)); }
/// <summary> /// Method to setup events on a descriptions no graphics setup should be included in here, /// that should be in the view /// </summary> /// <param name="desc">The description to setup the events on</param> private void AddDescriptionEventHandlers(Description desc) { desc.DeleteRequested += DeleteDescription; }
private void DescriptionFileNotFound(Description d) { //Pause from the UI thread. DispatcherHelper.UIDispatcher.Invoke(() => _mediaControlViewModel.PauseCommand.Execute()); //TODO: Delete description if not found, or ask for file location? Log.ErrorFormat("The description file could not be found at {0}", d.AudioFile); MessageBoxFactory.ShowError(string.Format(UiStrings.MessageBox_Format_AudioFileNotFound, d.AudioFile)); }
private void OnPlayingDescription(Description description) { var handler = PlayingDescription; if (handler != null) handler(this, description); }
private void PrepareForDescription(Description description) { if (description.IsExtendedDescription) { DispatcherHelper.UIDispatcher.Invoke(() => { // _mediaControlViewModel.PauseCommand.Execute(this); _mediaControlViewModel.PauseForExtendedDescriptionCommand.Execute(this); Log.Info("Playing Extended Description"); }); _descriptionInfoTabViewModel.SelectedExtendedDescription = description; } else { if (!description.IsPlaying) { Log.Info("Playing Regular Description"); //Reduce volume on the graphics thread to avoid an invalid operation exception. DispatcherHelper.UIDispatcher.Invoke(() => _mediaControlViewModel.ReduceVolume()); } _lastRegularDescriptionPlayed = description; _descriptionInfoTabViewModel.SelectedRegularDescription = description; } }
/// <summary> /// Restores the media back to its original state before playing the given description. /// </summary> /// <param name="description"></param> public void ResumeFromDescription(Description description) { //if the description is an extended description, we want to move the video forward to get out of the interval of //where the extended description will play //then we want to replay the video if (description.IsExtendedDescription) { double offset = _mediaVideo.Position.TotalMilliseconds - description.StartInVideo; //+1 so we are out of the interval and it doesn't repeat the description int newStartInVideo = (int)(_mediaVideo.Position.TotalMilliseconds + (LiveDescribeConstants.ExtendedDescriptionStartIntervalMax - offset + 1)); _mediaVideo.Position = new TimeSpan(0, 0, 0, 0, newStartInVideo); PlayCommand.Execute(); Log.Info("Extended description finished"); } else RestoreVolume(); }
public void InsertDescriptionForInsertUndoRedo(ObservableCollection<Description> allDescriptions, ObservableCollection<Description> descriptions, Description element) { var cmd = new InsertDescriptionHistoryItem(allDescriptions, descriptions, element); Push(_undoStack, cmd); _redoStack.Clear(); }