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);
        }
Esempio n. 11
0
        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);
     }
 }
Esempio n. 17
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;
        }
Esempio n. 19
0
        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();
        }
Esempio n. 21
0
 private void RemoveDescriptionEventHandlers(Description desc)
 {
     desc.DeleteRequested -= DeleteDescription;
 }
Esempio n. 22
0
        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));
 }
Esempio n. 24
0
 /// <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();
 }