using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Media.Imaging; using Tango.Core.Commands; using Tango.Scripting.IDE.ProjectTypes; using Tango.SharedUI; using Microsoft.WindowsAPICodePack.Dialogs; using Microsoft.Win32; namespace Tango.Scripting.IDE.Dialogs { public class NewProjectViewVM : BaseProjectDialogVM { /// /// Gets or sets the last solution locations. /// public ObservableCollection LastSolutionPaths { get; set; } private String _solutionName = "App1"; public String SolutionName { get { return _solutionName; } set { _solutionName = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } #region Commands public RelayCommand BrowseFileCommand { get; set; } #endregion public NewProjectViewVM(List projectTypes) : base(projectTypes) { Title = "New Project"; BrowseFileCommand = new RelayCommand(BrowseFile); } public NewProjectViewVM(IEnumerable lastSolutionFolders, List projectTypes) : this(projectTypes) { LastSolutionPaths = new ObservableCollection(lastSolutionFolders); ProjectLocation = LastSolutionPaths.FirstOrDefault(); } private void BrowseFile() { CommonOpenFileDialog dialog = new CommonOpenFileDialog(); dialog.InitialDirectory = LastSolutionPaths.LastOrDefault(); dialog.IsFolderPicker = true; if (dialog.ShowDialog() == CommonFileDialogResult.Ok) { if (Directory.Exists(dialog.FileName) == true) { if (false == LastSolutionPaths.Contains(dialog.FileName)) { LastSolutionPaths.Add(dialog.FileName); } ProjectLocation = dialog.FileName; } } } protected override bool CanOK() { return base.CanOK() && !String.IsNullOrWhiteSpace(SolutionName); } } }
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core.Commands;
using Tango.Core.Helpers;
using Tango.Integration.Diagnostics;
using Tango.Integration.Operation;
using Tango.Integration.ExternalBridge;
using Tango.MachineStudio.Common.Diagnostics;
using Tango.MachineStudio.Common.EventLogging;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.MachineStudio.Common.Video;
using Tango.MachineStudio.DataCapture.Recording;
using Tango.MachineStudio.DataCapture.Views;
using Tango.MachineStudio.Logging.ViewModels;
using Tango.PMR.Diagnostics;
using Tango.Settings;
using Tango.SharedUI;
using Tango.Video.DirectCapture;

namespace Tango.MachineStudio.DataCapture.ViewModels
{
    /// <summary>
    /// Represents the data capture main view, view model.
    /// </summary>
    /// <seealso cref="Tango.SharedUI.ViewModel" />
    public class MainViewVM : ViewModel
    {
        private INotificationProvider _notification;
        private IStudioApplicationManager _applicationManager;
        private IDiagnosticsFrameProvider _frameProvider;
        private IEventLogger _eventLogger;
        private String _recordingsFolder;
        private BarItem _recordingBarItem;
        private BarItem _playerBarItem;

        #region Properties

        private ObservableCollection<DataRecording> _recordings;
        /// <summary>
        /// Gets or sets the recordings collection.
        /// </summary>
        public ObservableCollection<DataRecording> Recordings
        {
            get { return _recordings; }
            set { _recordings = value; RaisePropertyChangedAuto(); }
        }

        private DataRecording _selectedRecording;
        /// <summary>
        /// Gets or sets the selected recording.
        /// </summary>
        public DataRecording SelectedRecording
        {
            get { return _selectedRecording; }
            set { _selectedRecording = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
        }

        /// <summary>
        /// Gets or sets the video capture provider.
        /// </summary>
        public IVideoCaptureProvider VideoCaptureProvider { get; set; }

        private DiagnosticsFileRecorder _recorder;
        /// <summary>
        /// Gets or sets the diagnostics file recorder.
        /// </summary>
        public DiagnosticsFileRecorder Recorder
        {
            get { return _recorder; }
            set { _recorder = value; RaisePropertyChangedAuto(); }
        }

        private DiagnosticsFilePlayer _player;
        /// <summary>
        /// Gets or sets the diagnostics file player.
        /// </summary>
        public DiagnosticsFilePlayer Player
        {
            get { return _player; }
            set { _player = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets or sets the machine operator.
        /// </summary>
        public IMachineOperator MachineOperator { get; set; }

        private List<CaptureDevice> _captureDevices;
        /// <summary>
        /// Gets or sets the capture devices.
        /// </summary>
        public List<CaptureDevice> CaptureDevices
        {
            get { return _captureDevices; }
            set { _captureDevices = value; RaisePropertyChangedAuto(); }
        }

        private TimelineViewVM _timelineViewVM;
        /// <summary>
        /// Gets or sets the timeline view VM.
        /// </summary>
        public TimelineViewVM TimelineViewVM
        {
            get { return _timelineViewVM; }
            set { _timelineViewVM = value; RaisePropertyChangedAuto(); }
        }

        #endregion

        #region Commands

        /// <summary>
        /// Gets or sets the remove recording command.
        /// </summary>
        public RelayCommand<DataRecording> RemoveRecordingCommand { get; set; }

        /// <summary>
        /// Gets or sets the toggle camera command.
        /// </summary>
        public RelayCommand<CaptureDevice> ToggleCameraCommand { get; set; }

        /// <summary>
        /// Gets or sets the media recording command.
        /// </summary>
        public RelayCommand MediaRecordingCommand { get; set; }

        /// <summary>
        /// Gets or sets the media stop command.
        /// </summary>
        public RelayCommand MediaStopCommand { get; set; }

        /// <summary>
        /// Gets or sets the media toggle play pause command.
        /// </summary>
        public RelayCommand MediaTogglePlayPauseCommand { get; set; }

        /// <summary>
        /// Gets or sets the media play pause command.
        /// </summary>
        public RelayCommand MediaPlayPauseCommand { get; set; }

        /// <summary>
        /// Gets or sets the media seek forward command.
        /// </summary>
        public RelayCommand MediaSeekForwardCommand { get; set; }

        /// <summary>
        /// Gets or sets the media seek backward command.
        /// </summary>
        public RelayCommand MediaSeekBackwardCommand { get; set; }

        /// <summary>
        /// Gets or sets the media seek command.
        /// </summary>
        public RelayCommand<double> MediaSeekCommand { get; set; }

        /// <summary>
        /// Gets or sets the media seek hold command.
        /// </summary>
        public RelayCommand MediaSeekHoldCommand { get; set; }

        #endregion

        #region Constructors

        public MainViewVM()
        {

        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MainViewVM"/> class.
        /// </summary>
        public MainViewVM(IVideoCaptureProvider videoCaptureProvider, INotificationProvider notification, IStudioApplicationManager applicationManager, IDiagnosticsFrameProvider frameProvider, IEventLogger eventLogger)
        {
            _notification = notification;
            _applicationManager = applicationManager;
            _frameProvider = frameProvider;
            _eventLogger = eventLogger;

            _eventLogger.NewLog += _eventLogger_NewLog;

            Recorder = new DiagnosticsFileRecorder();
            Player = new DiagnosticsFilePlayer();

            TimelineViewVM = new TimelineViewVM(notification) { EnableTimeMarker = true };

            VideoCaptureProvider = videoCaptureProvider;
            Recordings = new ObservableCollection<DataRecording>();

            ToggleCameraCommand = new RelayCommand<CaptureDevice>(ToggleCamera);

            RemoveRecordingCommand = new RelayCommand<DataRecording>(RemoveRecording);

            MediaRecordingCommand = new RelayCommand(StartDiagnosticsRecording, () => !Recorder.IsRecording && MachineOperator != null && !Player.IsPlaying);
            MediaStopCommand = new RelayCommand(StopRecorderOrPlayer, () => Recorder.IsRecording || Player.IsPlaying);
            MediaPlayPauseCommand = new RelayCommand(DiagnosticsTogglePlayPause, () => !Recorder.IsRecording && SelectedRecording != null);
            MediaSeekForwardCommand = new RelayCommand(MediaSeekForward, () => !Recorder.IsRecording && Player.IsPlaying);
            MediaSeekBackwardCommand = new RelayCommand(MediaSeekBackward, () => !Recorder.IsRecording && Player.IsPlaying);
            MediaSeekCommand = new RelayCommand<double>(MediaSeek, (x) => Player.IsPlaying);
            MediaSeekHoldCommand = new RelayCommand(MediaSeekHold, () => Player.IsPlaying);

            _recordingsFolder = Path.Combine(Path.GetDirectoryName(SettingsManager.Default.Folder), "Recordings");
            Directory.CreateDirectory(_recordingsFolder);

            _frameProvider.FrameReceived += _frameProvider_FrameReceived;

            applicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged;

            _recordingBarItem = new BarItem(_notification, new RecordingBarView() { DataContext = this });
            _playerBarItem = new BarItem(_notification, new PlayingBarView() { DataContext = this });

            CaptureDevices = VideoCaptureProvider.AvailableCaptureDevices.ToList();

            LoadRecordings();
        }

        #endregion

        #region Event Handlers

        private void _eventLogger_NewLog(object sender, MachinesEvent ev)
        {
            if (Recorder.IsRecording)
            {
                Recorder.Write(ev);
            }
        }

        private void ApplicationManager_ConnectedMachineChanged(object sender, IExternalBridgeClient machine)
        {
            MachineOperator = machine;
            InvalidateRelayCommands();
        }

        private void _frameProvider_FrameReceived(object sender, StartDiagnosticsResponse frame)
        {
            if (!_frameProvider.Disable)
            {
                if (Recorder.IsRecording)
                {
                    Recorder.Write(frame);

                    Task.Factory.StartNew(() =>
                    {
                        CaptureDevices.First().Invoke(() =>
                        {
                            if (Recorder.IsRecording)
                            {
                                Recorder.Write(CaptureDevices.Where(x => x.VideoSource != null).Select(x => x.VideoSource.GetAsFrozen() as BitmapSource));
                            }
                        });
                    });
                }
            }
        }


        #endregion

        #region Private Methods

        private void LoadRecordings()
        {
            foreach (var file in Directory.GetFiles(_recordingsFolder, "*.tdr"))
            {
                Recordings.Add(new DataRecording(file, File.GetCreationTime(file)));
            }

            Recordings = Recordings.OrderByDescending(x => x.Date).ToObservableCollection();
        }

        /// <summary>
        /// Removes the recording.
        /// </summary>
        /// <param name="recording">The recording.</param>
        private void RemoveRecording(DataRecording recording)
        {
            if (_notification.ShowQuestion("Are you sure you want to remove the specified recording?"))
            {
                Recordings.Remove(recording);
                PathHelper.TryDeleteFile(recording.FilePath);
            }
        }

        /// <summary>
        /// Toggles the camera.
        /// </summary>
        /// <param name="captureDevice">The capture device.</param>
        private void ToggleCamera(CaptureDevice captureDevice)
        {
            if (captureDevice.Device != null)
            {
                captureDevice.IsStarted = !captureDevice.IsStarted;
            }
        }

        private async void DiagnosticsTogglePlayPause()
        {
            if (!Player.IsPlaying || Player.IsPaused)
            {
                _frameProvider.Disable = true;

                if (SelectedRecording.Player == null)
                {
                    using (_notification.PushTaskItem("Loading Recording..."))
                    {
                        SelectedRecording.Player = new DiagnosticsFilePlayer();
                        await SelectedRecording.Player.Load(SelectedRecording.FilePath);
                        TimelineViewVM.Initialize(SelectedRecording.Player.MachineEvents);
                        TimelineViewVM.TimelineMaxTime = SelectedRecording.Player.TotalTime;
                    }
                }

                RegisterPlayer(SelectedRecording.Player);

                if (!Player.IsPlaying)
                {
                    _playerBarItem.Push();
                }

                Player.Play();
            }
            else
            {
                Player.Pause();
            }

            InvalidateRelayCommands();
        }

        private void RegisterPlayer(DiagnosticsFilePlayer player)
        {
            foreach (var recording in Recordings)
            {
                if (recording.Player != null)
                {
                    recording.Player.FrameReceived -= Player_FrameReceived;
                }
            }

            if (player != null)
            {
                Player = player;
                Player.FrameReceived += Player_FrameReceived;
            }

            CaptureDevices.ForEach(x => x.DisableSourceUpdate());
        }

        private void Player_FrameReceived(object sender, DataFileFrame frame)
        {
            if (_frameProvider.Disable)
            {
                _frameProvider.PushFrame(frame.StartDiagnosticsResponse);

                CaptureDevices.First().BeginInvoke(() =>
                {
                    for (int i = 0; i < frame.VideoFrames.Count; i++)
                    {
                        CaptureDevices[i].VideoSource = frame.VideoFrames[i].ToByteArray().ToBitmapSource();
                    }
                });

                TimelineViewVM.CurrentPosition = (sender as DiagnosticsFilePlayer).CurrentTime;
            }
        }

        public void StartDiagnosticsRecording()
        {
            using (_notification.PushTaskItem("Starting Recording..."))
            {
                Recorder.Start();
                //_eventLogger.Log(EventTypes.RECORDING_STARTED, "Recording Started...");
                _recordingBarItem.Push();
            }

            InvalidateRelayCommands();
        }

        public async void StopRecorderOrPlayer()
        {
            if (Recorder.IsRecording)
            {
                using (_notification.PushTaskItem("Stopping Recording..."))
                {
                    await Recorder.Stop();
                    _recordingBarItem.Pop();

                    //_eventLogger.Log(EventTypes.RECORDING_STOPPED, "Recording Stopped...");
                }

                String recordingName = _notification.ShowTextInput("Enter recording name", "Recording name");

                if (!String.IsNullOrWhiteSpace(recordingName))
                {
                    using (_notification.PushTaskItem("Saving Recording..."))
                    {
                        String filePath = Path.Combine(_recordingsFolder, recordingName + ".tdr");
                        await Recorder.Save(filePath);
                        Recordings.Insert(0, new DataRecording(filePath));
                    }
                }

                Recorder.Dispose();
                Recorder = new DiagnosticsFileRecorder();
            }
            else if (Player.IsPlaying)
            {
                await Player.Stop();
                TimelineViewVM.CurrentPosition = TimeSpan.Zero;
                CaptureDevices.ForEach(x => x.EnableSourceUpdate());
                _frameProvider.Disable = false;
                _playerBarItem.Pop();
            }

            InvalidateRelayCommands();
        }

        private void MediaSeekBackward()
        {
            if (Player.IsPlaying)
            {
                Player.Seek(Player.CurrentFrame - 200);
            }
        }

        private void MediaSeekForward()
        {
            if (Player.IsPlaying)
            {
                Player.Seek(Player.CurrentFrame + 200);
            }
        }

        private void MediaSeek(double frame)
        {
            if (Player != null)
            {
                Player.Seek((int)frame);
                Player.Play();
            }
        }

        private void MediaSeekHold()
        {
            if (Player != null)
            {
                Player.Pause();
            }
        }

        #endregion
    }
}