Beispiel #1
0
        /// <inheritdoc />
        /// <summary>
        ///   Class constructor
        /// </summary>
        /// <param name="container">HUD container information</param>
        public Toolbar(HudContainerInfo container) : base(container)
        {
            if (DesktopWrapper != null)
            {
                DesktopWrapper.PassThrough = false;
                DesktopWrapper.Resizable   = false;

                // bind mouse event handlers
                DesktopWrapper.MouseMove  += OnToolbarMouseMove;
                DesktopWrapper.MouseDown  += OnToolbarMouseDown;
                DesktopWrapper.MouseUp    += OnToolbarMouseUp;
                DesktopWrapper.MouseLeave += delegate {
                    foreach (ToolbarControl control in Controls.Values)
                    {
                        control.State &= ~ToolbarControlState.Hovered;
                    }
                };
            }

            Bounds = new Rectangle(320, 320, 256, toolbarHeight);
        }
        /// <summary>
        ///   Starts the workflow interactively
        /// </summary>
        internal async Task StartAsync(HudContainerInfo container)
        {
            this.currentContainer = container;

            Log.Info($"starting {Type} workflow on {container.ContainerType} container");
            await AcquireRegionAsync();

            if (Region.Size.Width <= Clipper.MinimumWidth || Region.Size.Height <= Clipper.MinimumHeight)
            {
                Log.Trace("capture dismissed");
                Finish();
                return;
            }

            if (this.captureDevice == null || !Equals(this.captureDevice.Size.ToTuple(), Region.Size.ToTuple()))
            {
                // dispose old video provider if size changed
                this.captureDevice?.Dispose();

                // video provider will capture frames
                Log.Debug("creating capture device");
                this.captureDevice = CaptureDeviceFactory.CreateVideoCaptureDevice(
                    Region.Location.X,
                    Region.Location.Y,
                    Region.Size.Width,
                    Region.Size.Height);

                // TODO: create and bind transforms
            }

            // create destination stream, a MultiStream which will act as some kind of stream multiplexer wrapping multiple
            // "sub-streams" onto one
            // TODO: add IImmediateHandler's to the MultiStream
            this.stream = new MultiStream();

            // create codec instance
            if (Type == WorkflowType.Still)
            {
                this.codec = Application.ExtensionManager.CreateObject <StillImageCodec>(Codec.TypeName,
                                                                                         Region.Size.Width,
                                                                                         Region.Size.Height,
                                                                                         this.stream);
            }
            else if (Type == WorkflowType.Motion)
            {
                this.codec = Application.ExtensionManager.CreateObject <VideoCodec>(Codec.TypeName,
                                                                                    Region.Size.Width,
                                                                                    Region.Size.Height,
                                                                                    this.stream);
            }

            // create handlers
            this.handlers = Handlers.Select(handlerData => {
                Handler handler = Application.ExtensionManager.CreateObject <Handler>(
                    handlerData.TypeName,
                    this,
                    this.codec,
                    this.stream,
                    handlerData.Options);

                if (handler is IStreamWrapper streamWrapperHandler)
                {
                    // add stream wrapper to the multi-stream
                    this.stream.Add(streamWrapperHandler.OutputStream);
                    Log.Trace("added stream wrapper handler: " + handlerData.TypeName);
                }

                return(handler);
            }).ToArray();

            if (Type == WorkflowType.Still)
            {
                // still image -- we do not need our stream to be filesystem-backed, as still images can't really be *that*
                // large... I hope
                this.stream.Add(new MemoryStream());

                Log.Info("capturing screen");
                this.captureDevice.AcquireFrame();
                VideoFrame frame = this.captureDevice.LockFrame();

                Log.Info("encoding capture");
                this.codec.Start();
                this.codec.Feed(frame);
                this.codec.Dispose();

                // unlock and release capture
                this.captureDevice.UnlockFrame(frame);
                this.captureDevice.ReleaseFrame();

                Finish();
            }
            else
            {
                // motion capture -- stand back and don't underestimate my expertise on googling
                // save output to a temporary file
                Log.Info("starting recording session");

                // create toolbar
                this.toolbar = new Toolbar(Application.HudManager.GetContainer());
                this.clipper?.AttachToolbar(this.toolbar);

                /* bind toolbar events */
                // option events
                this.toolbar.OnOptionsRequested += delegate(object sender, ToolbarOptionRequestType optionType) {
                    switch (optionType)
                    {
                    case ToolbarOptionRequestType.Generic:
                        try {
                            new OptionsWindow().Show();
                        } catch {
                            /* already open */
                        }

                        break;

                    default:
                        throw new NotImplementedException();
                    }
                };

                // recording control intents
                this.toolbar.OnRecordingIntentReceived += delegate(object sender, ToolbarRecordingControlIntent controlIntent) {
                    try {
                        Log.Info($"received recording control intent: {controlIntent}");
                        this.toolbar.SetPrimaryButtonState(enabled: false);

                        switch (controlIntent)
                        {
                        case ToolbarRecordingControlIntent.Start:
                            /* start recording */
                            if (!(this.motionSession?.Disposed ?? true))
                            {
                                throw new InvalidOperationException("A previous motion capture session has not been closed");
                            }

                            if (!(this.codec is VideoCodec))
                            {
                                throw new NotSupportedException("The current codec does not allow multiple frames");
                            }

                            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                            if (
                                this.captureDevice is DxgiVideoCaptureDevice
                                dxgiCaptureDevice && // make sure our capture device is DXGI-enabled
                                this.codec is IDxgiEnabledVideoCodec dxgiCodec)
                            {
                                // make sure our codec is DXGI-compatible
                                // make sure we have the same D3D device for all sources
                                Device device = dxgiCaptureDevice.Devices.First();
                                if (dxgiCaptureDevice.Devices.All(d => d == device))
                                {
                                    // set device to be bound to the DXGI device manager
                                    // TODO: optimize DxgiVideoProvider so that it only creates one device for each adapter
                                    // TODO: allow ID3DCodec's to operate on multiple DXGI devices
                                    dxgiCodec.BindDevice(device);
                                    Log.Info("bound DXGI device to codec");
                                }
                            }

                            // create motion capture session and change toolbar button intent
                            this.motionSession = new MotionCaptureSession((VideoCodec)this.codec, this.captureDevice);
                            this.toolbar.SetPrimaryButtonState(ToolbarRecordingControlIntent.Stop);
                            break;

                        case ToolbarRecordingControlIntent.Stop:
                            this.motionSession.Dispose();
                            Finish();
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    } finally {
                        this.toolbar?.SetPrimaryButtonState(enabled: true);
                    }
                };
            }
        }
Beispiel #3
0
 /// <summary>
 ///   Class constructor
 /// </summary>
 /// <param name="container">HUD container</param>
 internal TidbitManager(HudContainerInfo container) =>
 this.containerInfo = container;