예제 #1
0
        /// <summary>
        /// Gets called whenever the player has been initialized.
        /// </summary>
        public override void OnPlayerInitialized( )
        {
            MediaComponent comp = MainWindow.Player.GetComponent <MediaComponent>( );

            comp.OnMediaLoaded += (Sender, Args) =>
            {
                OpenLocalSubs.IsEnabled = true;
                OpenOSSubs.IsEnabled    = true;
            };
            comp.OnMediaFailedToLoad += (Sender, Args) =>
            {
                OpenLocalSubs.IsEnabled = false;
                OpenOSSubs.IsEnabled    = false;
                EnableSubs.IsEnabled    = false;
                EnableSubs.IsChecked    = false;
            };

            InputComponent inputComponent = Player.GetComponent <InputComponent>( );

            inputComponent.OnShowControls += (Sender, Args) => this.Visibility = Visibility.Visible;
            inputComponent.OnHideControls += (Sender, Args) => this.Visibility = Visibility.Collapsed;

            SubtitlesComponent subs = MainWindow.Player.GetComponent <SubtitlesComponent>( );

            subs.OnSubtitlesFailedToLoad += SubsOnOnSubtitlesFailedToLoad;
            subs.OnSubtitlesLoaded       += SubsOnOnSubtitlesLoaded;
        }
예제 #2
0
 public void AddAll(OptionArgs args)
 {
     foreach (Song song in songs)
     {
         MediaComponent.addSong(song);
     }
 }
        public void Play(object sender, EventArgs e)
        {
            MediaComponent.start();

            MediaComponent.getInfo(out artist, out album, out song);

            albumArt = MediaComponent.getArt();
        }
        public void Previous(object sender, EventArgs e)
        {
            MediaComponent.movePreviousSong();

            MediaComponent.getInfo(out artist, out album, out song);

            albumArt = MediaComponent.getArt();
        }
예제 #5
0
        public int IndexOf(MediaComponent component)
        {
            if (component == null)
            {
                throw new System.ArgumentNullException();
            }

            return(System.Array.IndexOf(Components, component));
        }
예제 #6
0
        public MediaFormat(MediaType mediaType, Common.Binary.ByteOrder byteOrder, DataLayout dataLayout, int components, int[] componentSizes, byte[] componentIds)
        {
            //Assign the media type
            MediaType = mediaType;

            if (byteOrder == Common.Binary.ByteOrder.Unknown)
            {
                throw new System.ArgumentException("byteOrder", "Cannot be Unknown");
            }
            ByteOrder = byteOrder;

            //Validate the datalayout
            if (dataLayout == Media.Codec.DataLayout.Unknown)
            {
                throw new System.ArgumentException("dataLayout", "Cannot be Unknown");
            }
            DataLayout = dataLayout;

            //Validate the amount of components
            if (components < 1)
            {
                throw new System.ArgumentException("components", "Must be greater than 0.");
            }

            //Create the array
            Components = new MediaComponent[components];

            long length;

            //Validate the sizes array
            if (Common.Extensions.Array.ArrayExtensions.IsNullOrEmpty(componentSizes, out length) || length < components)
            {
                throw new System.ArgumentException("componentSizes", "Must have the amount of elements indicated by 'components'");
            }

            //Validate the length of the id array
            if (Common.Extensions.Array.ArrayExtensions.IsNullOrEmpty(componentIds, out length) || length < components)
            {
                throw new System.ArgumentException("componentIds", "Must have the amount of elements indicated by 'components'");
            }

            //Creates each component
            for (int i = 0; i < components; ++i)
            {
                length = componentSizes[i];

                int ilen = (int)length;

                Components[i] = new MediaComponent(componentIds[i], ilen);

                Size += ilen;
            }
        }
        public void Stop(object sender, EventArgs e)
        {
            playPause.revert();

            artist = "<Artist>";
            album  = "<Album>";
            song   = "<Song>";

            MediaComponent.stop();

            albumArt = null;
        }
        public override void update(InputHandler input)
        {
            playPause.update(input);
            stop.update(input);
            next.update(input);
            previous.update(input);
            shuffle.update(input);
            repeat.update(input);

            if (MediaComponent.playing)
            {
                MediaComponent.getInfo(out artist, out album, out song);
            }
        }
예제 #9
0
 public MediaActor(ulong id, string path = "") : base(id)
 {
     InitializeComponent();
     Name = "Media-" + id;
     _cmp = new MediaComponent(this);
     AddComponent(_cmp);
     if (string.IsNullOrEmpty(path))
     {
         path = "http://flv3.bn.netease.com/videolib3/1801/04/MsbTq9983/SD/MsbTq9983-mobile.mp4";
     }
     Media = new MediaElement()
     {
         Source = new Uri(string.Format("{0}", path))
     };
 }
예제 #10
0
        /// <summary>
        /// Gets called whenever the player has been initialized.
        /// </summary>
        public override void OnPlayerInitialized( )
        {
            Player.GetComponent <TimeComponent>( ).OnPositionChanged += OnOnPositionChanged;
            Player.GetComponent <StateComponent>( ).OnStateChanged   += OnOnStateChanged;

            MediaComponent media = Player.GetComponent <MediaComponent>( );

            media.OnMediaLoaded   += MediaOnOnMediaLoaded;
            media.OnMediaUnloaded += MediaOnOnMediaUnloaded;

            InputComponent inputComponent = Player.GetComponent <InputComponent>( );

            inputComponent.OnShowControls += (Sender, Args) => this.Visibility = Visibility.Visible;
            inputComponent.OnHideControls += (Sender, Args) => this.Visibility = Visibility.Collapsed;
        }
        private void WaitForPackets(MediaComponent mediaComponent, int cycleCount = -1)
        {
            var cycleIndex = 0;

            while (mediaComponent.PacketBufferCount <= 0 &&
                   CanReadMorePackets &&
                   ShouldReadMorePackets)
            {
                PacketReadingCycle.Wait(Constants.Interval.LowPriority);
                if (cycleCount <= 0)
                {
                    continue;
                }

                cycleIndex++;
                if (cycleCount >= cycleIndex)
                {
                    break;
                }
            }
        }
예제 #12
0
    private void SetMediaMessage(Message message)
    {
        if (message.IsStickerMessage)
        {
            mediaComponent = Instantiate(AssetController.GetGameObject("SimpleImage"), mediaParent).AddComponent <Sticker>();
            ((Sticker)mediaComponent).ToggleClick(false);
        }
        else if (message.IsAudioMessage)
        {
            mediaComponent = Instantiate(AssetController.GetGameObject("SimpleImage"), mediaParent).AddComponent <Sound>();
        }
        else if (message.IsPhotoMessage)
        {
            mediaComponent = Instantiate(AssetController.GetGameObject("SimpleImage"), mediaParent).AddComponent <Photo>();
        }
        else if (message.IsVideoMessage)
        {
            mediaComponent = Instantiate(AssetController.GetGameObject("SimpleImage"), mediaParent).AddComponent <Video>();
        }

        mediaComponent.InitiateComponent(message.GetMessageContent(), this);
    }
예제 #13
0
        void initializeMediaPlayer()
        {
            mediaPlayer = new MediaComponent(this);

            mediaPlayer.setMenuBackgrounds("Menus/Standard Menu", new Vector2(), Color.White, new FadeComponent(15, 1), new FadeComponent(15, -1));

            mediaPlayer.setMenuTitles("Fonts/MaturaTitle", new Vector2(60, 40), Color.Red, new FadeComponent(15, 1), new FadeComponent(15, -1));

            mediaPlayer.setMenuDisplayLists("Fonts/MaturaOptions", "Menus/Highlighter", new Rectangle(30, 100, 212, 320), Color.Red,
                                            new Vector2(30, 100), 30, new MoveCollection(new Vector2(-200, 0), 15, true), new MoveCollection(null, new Vector2(200, 0), 15, true),
                                            new MoveCollection(new Vector2(-200, 0), 15, false), new MoveCollection(new Vector2(200, 0), 15, false));

            mediaPlayer.setMenuBackOption("Fonts/MaturaOptions", new Vector2(136, 440), Color.Red, "Menus/Highlighter", new Vector2(136, 440), TextAlignment.center,
                                          new MoveCollection(new Vector2(-200, 0), 15, true), new MoveCollection(null, new Vector2(200, 0), 15, true),
                                          new MoveCollection(new Vector2(-200, 0), 15, false), new MoveCollection(new Vector2(200, 0), 15, false));

            mediaPlayer.setMenuQueue(false);

            mediaPlayer.addMenus(menus);

            Components.Add(mediaPlayer);
        }
예제 #14
0
 public void AddSong(OptionArgs args)
 {
     MediaComponent.addSong(songs[args.index - 1]);
 }
        /// <summary>
        /// Continually decodes the available packet buffer to have as
        /// many frames as possible in each frame queue and
        /// up to the MaxFrames on each component
        /// </summary>
        /// <returns>The task.</returns>
        internal async Task RunFrameDecodingWorker()
        {
            var decodedFrameCount = 0;

            var wallClock    = TimeSpan.Zero;
            var rangePercent = 0d;
            var isInRange    = false;

            // Holds the main media type
            var main = Container.Components.Main.MediaType;

            // Holds the auxiliary media types
            var auxs = Container.Components.MediaTypes.Where(x => x != main).ToArray();

            // Holds all components
            var all = Container.Components.MediaTypes.ToArray();

            var isBuffering     = false;
            var resumeClock     = false;
            var hasPendingSeeks = false;

            MediaComponent   comp   = null;
            MediaBlockBuffer blocks = null;

            while (IsTaskCancellationPending == false)
            {
                #region 1. Setup the Decoding Cycle

                hasPendingSeeks = Commands.PendingCountOf(MediaCommandType.Seek) > 0;
                if (IsSeeking == false && hasPendingSeeks)
                {
                    IsSeeking = true;
                    RaiseSeekingStartedEvent();
                }

                // Execute the following command at the beginning of the cycle
                await Commands.ProcessNext();

                hasPendingSeeks = Commands.PendingCountOf(MediaCommandType.Seek) > 0;
                if (IsSeeking == true && hasPendingSeeks == false)
                {
                    SnapVideoPosition(Clock.Position);
                    IsSeeking = false;

                    // Call the seek method on all renderers
                    foreach (var kvp in Renderers)
                    {
                        kvp.Value.Seek();
                    }

                    RaiseSeekingEndedEvent();
                }

                // Wait for a seek operation to complete (if any)
                // and initiate a frame decoding cycle.
                SeekingDone.WaitOne();

                // Check if one of the commands has requested an exit
                if (IsTaskCancellationPending)
                {
                    break;
                }

                // Initiate the frame docding cycle
                FrameDecodingCycle.Reset();

                // Set initial state
                wallClock         = Clock.Position;
                decodedFrameCount = 0;

                #endregion

                #region 2. Main Component Decoding

                // Capture component and blocks for easier readability
                comp   = Container.Components[main];
                blocks = Blocks[main];

                // Handle the main component decoding; Start by checking we have some packets
                if (comp.PacketBufferCount > 0)
                {
                    // Detect if we are in range for the main component
                    isInRange = blocks.IsInRange(wallClock);

                    if (isInRange == false)
                    {
                        // Clear the media blocks if we are outside of the required range
                        // we don't need them and we now need as many playback blocks as we can have available
                        if (blocks.IsFull)
                        {
                            blocks.Clear();
                        }

                        // detect a buffering scenario
                        if (blocks.Count <= 0)
                        {
                            HasDecoderSeeked = true;
                            isBuffering      = true;
                            resumeClock      = Clock.IsRunning;
                            Clock.Pause();
                            Logger.Log(MediaLogMessageType.Debug, $"SYNC BUFFER: Buffering Started.");
                        }

                        // Read some frames and try to get a valid range
                        while (comp.PacketBufferCount > 0 && blocks.IsFull == false)
                        {
                            decodedFrameCount = AddBlocks(main);
                            isInRange         = blocks.IsInRange(wallClock);
                            if (isInRange)
                            {
                                break;
                            }

                            // Try to get more packets by waiting for read cycles.
                            if (CanReadMorePackets && comp.PacketBufferCount <= 0 && isInRange == false)
                            {
                                PacketReadingCycle.WaitOne();
                            }
                        }

                        // Unfortunately at this point we will need to adjust the clock after creating the frames.
                        // to ensure tha mian component is within the clock range if the decoded
                        // frames are not with range. This is normal while buffering though.
                        if (isInRange == false)
                        {
                            wallClock = wallClock <= blocks.RangeStartTime ?
                                        blocks.RangeStartTime : blocks.RangeEndTime;

                            if (isBuffering == false)
                            {
                                Logger.Log(MediaLogMessageType.Warning, $"SYNC CLOCK: {Clock.Position.Format()} set to {wallClock.Format()}");
                            }

                            // Update the clock to what the main component range mandates
                            Clock.Position = wallClock;
                        }
                    }
                    else
                    {
                        // Check if we need more blocks for the current components
                        rangePercent = blocks.GetRangePercent(wallClock);

                        // Read as many blocks as we possibly can
                        while (comp.PacketBufferCount > 0 &&
                               ((rangePercent > 0.75d && blocks.IsFull) || blocks.IsFull == false))
                        {
                            decodedFrameCount = AddBlocks(main);
                            rangePercent      = blocks.GetRangePercent(wallClock);
                        }
                    }
                }

                #endregion

                #region 3. Auxiliary Component Decoding

                foreach (var t in auxs)
                {
                    if (IsSeeking)
                    {
                        continue;
                    }

                    // Capture the current block buffer and component
                    // for easier readability
                    comp   = Container.Components[t];
                    blocks = Blocks[t];

                    // wait for component to get there if we only have furutre blocks
                    // in auxiliary component.
                    if (blocks.RangeStartTime > wallClock)
                    {
                        continue;
                    }

                    // Wait for packets if we are buffering or we don't have enough packets
                    if (CanReadMorePackets && (isBuffering || comp.PacketBufferCount <= 0))
                    {
                        PacketReadingCycle.WaitOne();
                    }

                    // catch up with the wall clock
                    while (comp.PacketBufferCount > 0 && blocks.RangeEndTime <= wallClock)
                    {
                        decodedFrameCount = AddBlocks(t);

                        // don't care if we are buffering
                        // always try to catch up by reading more packets.
                        if (comp.PacketBufferCount <= 0 && CanReadMorePackets)
                        {
                            PacketReadingCycle.WaitOne();
                        }
                    }

                    rangePercent = blocks.GetRangePercent(wallClock);
                    isInRange    = blocks.IsInRange(wallClock);

                    // Wait for packets if we are buffering
                    if (CanReadMorePackets && isBuffering)
                    {
                        PacketReadingCycle.WaitOne();
                    }

                    while (comp.PacketBufferCount > 0 &&
                           (
                               (blocks.IsFull == true && isInRange && rangePercent > 0.75d && rangePercent < 1d) ||
                               (blocks.IsFull == false)
                           ))
                    {
                        decodedFrameCount = AddBlocks(t);
                        rangePercent      = blocks.GetRangePercent(wallClock);
                        isInRange         = blocks.IsInRange(wallClock);

                        if (CanReadMorePackets && isBuffering)
                        {
                            PacketReadingCycle.WaitOne();
                        }
                    }
                }

                #endregion

                #region 4. Detect End of Media

                // Detect end of block rendering
                if (isBuffering == false &&
                    IsSeeking == false &&
                    CanReadMoreFramesOf(main) == false &&
                    Blocks[main].IndexOf(wallClock) == Blocks[main].Count - 1)
                {
                    if (HasMediaEnded == false)
                    {
                        // Rendered all and nothing else to read
                        Clock.Pause();
                        Clock.Position = NaturalDuration.HasTimeSpan ?
                                         NaturalDuration.TimeSpan : Blocks[main].RangeEndTime;
                        wallClock = Clock.Position;

                        HasMediaEnded = true;
                        MediaState    = MediaState.Pause;
                        RaiseMediaEndedEvent();
                    }
                }
                else
                {
                    HasMediaEnded = false;
                }

                #endregion

                #region 6. Finish the Cycle

                // complete buffering notifications
                if (isBuffering)
                {
                    isBuffering = false;
                    if (resumeClock)
                    {
                        Clock.Play();
                    }
                    Logger.Log(MediaLogMessageType.Debug, $"SYNC BUFFER: Buffering Finished. Clock set to {wallClock.Format()}");
                }

                // Complete the frame decoding cycle
                FrameDecodingCycle.Set();

                // After a seek operation, always reset the has seeked flag.
                HasDecoderSeeked = false;

                // Simply exit the thread when cancellation has been requested
                if (IsTaskCancellationPending)
                {
                    break;
                }

                // Give it a break if there was nothing to decode.
                // We probably need to wait for some more input
                if (decodedFrameCount <= 0 && Commands.PendingCount <= 0)
                {
                    await Task.Delay(1);
                }

                #endregion
            }

            // Always exit notifying the cycle is done.
            FrameDecodingCycle.Set();
        }
        /// <summary>
        /// Continually decodes the available packet buffer to have as
        /// many frames as possible in each frame queue and
        /// up to the MaxFrames on each component
        /// </summary>
        internal void RunFrameDecodingWorker()
        {
            #region Worker State Setup

            // The delay provider prevents 100% core usage
            var delay = new DelayProvider();

            // State variables
            var decodedFrameCount = 0;
            var wallClock         = TimeSpan.Zero;
            var rangePercent      = 0d;
            var isInRange         = false;

            // Holds the main media type
            var main = Container.Components.Main.MediaType;

            // Holds the auxiliary media types
            var auxs = Container.Components.MediaTypes.Except(main);

            // State properties
            var isBuffering = false;
            var resumeClock = false;

            MediaComponent   comp   = null;
            MediaBlockBuffer blocks = null;

            #endregion

            #region Worker Loop

            try
            {
                while (Commands.IsStopWorkersPending == false)
                {
                    #region 1. Setup the Decoding Cycle

                    // Determine what to do on a priority command
                    if (Commands.IsExecutingDirectCommand)
                    {
                        if (Commands.IsClosing)
                        {
                            break;
                        }
                        if (Commands.IsChanging)
                        {
                            Commands.WaitForDirectCommand();
                        }
                    }

                    // Update state properties -- this must be after processing commanmds as
                    // a direct command might have changed the components
                    main = Container.Components.Main.MediaType;
                    auxs = Container.Components.MediaTypes.Except(main);

                    // Execute the following command at the beginning of the cycle
                    Commands.ExecuteNextQueuedCommand();

                    // Signal a Seek starting operation
                    FrameDecodingCycle.Begin();

                    // Set initial state
                    wallClock         = WallClock;
                    decodedFrameCount = 0;

                    #endregion

                    if (State.HasMediaEnded == false)
                    {
                        #region 2. Main Component Decoding

                        // Capture component and blocks for easier readability
                        // comp is current component, blocks is the block collection for the component
                        comp   = Container.Components[main];
                        blocks = Blocks[main];

                        // Detect if we are in range for the main component
                        isInRange = blocks.IsInRange(wallClock);

                        if (isInRange == false)
                        {
                            // Signal the start of a sync-buffering scenario
                            isBuffering = true;
                            State.SignalBufferingStarted();
                            resumeClock = Clock.IsRunning;
                            Clock.Pause();
                            Log(MediaLogMessageType.Debug, $"SYNC-BUFFER: Started.");

                            // Read some frames and try to get a valid range
                            do
                            {
                                // Try to get more packets by waiting for read cycles.
                                WaitForPackets(comp, 1);

                                // Decode some frames and check if we are in reange now
                                if (AddNextBlock(main) == false)
                                {
                                    break;
                                }

                                decodedFrameCount += 1;
                                isInRange          = blocks.IsInRange(wallClock);

                                // Break the cycle if we are in range
                                if (isInRange || CanReadMorePackets == false || ShouldReadMorePackets == false)
                                {
                                    break;
                                }
                            }while (blocks.IsFull == false);

                            // Unfortunately at this point we will need to adjust the clock after creating the frames.
                            // to ensure tha mian component is within the clock range if the decoded
                            // frames are not with range. This is normal while buffering though.
                            if (isInRange == false)
                            {
                                // Update the wall clock to the most appropriate available block.
                                if (blocks.Count > 0)
                                {
                                    wallClock = blocks[wallClock].StartTime;
                                }
                                else
                                {
                                    resumeClock = false; // Hard stop the clock.
                                }
                                // Update the clock to what the main component range mandates
                                Clock.Update(wallClock);

                                // Force renderer invalidation
                                InvalidateRenderer(main);

                                // Try to recover the regular loop
                                isInRange = true;
                            }
                        }

                        if (isInRange)
                        {
                            // Check if we need more blocks for the current components
                            rangePercent = blocks.GetRangePercent(wallClock);

                            // Read as much as we can for this cycle but always within range.
                            while (blocks.IsFull == false || (blocks.IsFull && rangePercent > 0.75d && rangePercent < 1d))
                            {
                                if (AddNextBlock(main) == false)
                                {
                                    break;
                                }

                                decodedFrameCount += 1;
                                rangePercent       = blocks.GetRangePercent(wallClock);
                                continue;
                            }
                        }

                        #endregion

                        #region 3. Auxiliary Component Decoding

                        foreach (var t in auxs)
                        {
                            if (State.IsSeeking)
                            {
                                continue;
                            }

                            // Capture the current block buffer and component
                            // for easier readability
                            comp      = Container.Components[t];
                            blocks    = Blocks[t];
                            isInRange = blocks.IsInRange(wallClock);

                            // wait for component to get there if we only have furutre blocks
                            // in auxiliary component.
                            if (blocks.Count > 0 && blocks.RangeStartTime > wallClock)
                            {
                                continue;
                            }

                            // We need the other components to catch up with the main
                            while (blocks.Count == 0 || blocks.RangeEndTime <= wallClock ||
                                   (Blocks[main].Count > 0 && blocks.RangeEndTime < Blocks[main].RangeEndTime))
                            {
                                // give up if we never received frames for the expected component
                                if (AddNextBlock(t) == false)
                                {
                                    break;
                                }
                            }

                            // Check if we are finally within range
                            isInRange = blocks.IsInRange(wallClock);

                            // Invalidate the renderer if we don't have the block.
                            if (isInRange == false)
                            {
                                InvalidateRenderer(t);
                            }

                            // Move to the next component if we don't meet a regular conditions
                            if (isInRange == false || isBuffering)
                            {
                                continue;
                            }

                            // Decode as much as we can off the packet buffer for this cycle.
                            rangePercent = blocks.GetRangePercent(wallClock);
                            while (blocks.IsFull == false || (blocks.IsFull && rangePercent > 0.75d && rangePercent < 1d))
                            {
                                if (AddNextBlock(t) == false)
                                {
                                    break;
                                }

                                rangePercent = blocks.GetRangePercent(wallClock);
                            }
                        }

                        #endregion
                    }

                    #region 4. Detect End of Media

                    // Detect end of block rendering
                    // TODO: Maybe this detection should be performed on the BlockRendering worker?
                    if (isBuffering == false &&
                        decodedFrameCount <= 0 &&
                        State.IsSeeking == false &&
                        CanReadMoreFramesOf(main) == false &&
                        Blocks[main].IndexOf(wallClock) == Blocks[main].Count - 1)
                    {
                        if (State.HasMediaEnded == false)
                        {
                            // Rendered all and nothing else to read
                            Clock.Pause();
                            wallClock = Blocks[main].RangeEndTime;
                            Clock.Update(wallClock);

                            if (State.NaturalDuration != null &&
                                State.NaturalDuration != TimeSpan.MinValue &&
                                State.NaturalDuration < wallClock)
                            {
                                Log(MediaLogMessageType.Warning,
                                    $"{nameof(State.HasMediaEnded)} conditions met at {wallClock.Format()} but " +
                                    $"{nameof(State.NaturalDuration)} reports {State.NaturalDuration.Value.Format()}");
                            }

                            State.UpdateMediaEnded(true);
                            State.UpdateMediaState(PlaybackStatus.Stop, wallClock);
                            SendOnMediaEnded();
                        }
                    }
                    else
                    {
                        State.UpdateMediaEnded(false);
                    }

                    #endregion

                    #region 6. Finish the Cycle

                    // complete buffering notifications
                    if (isBuffering)
                    {
                        // Always reset the buffering flag
                        isBuffering = false;

                        // Resume the clock if it was playing
                        if (resumeClock)
                        {
                            Clock.Play();
                        }

                        // log some message
                        Log(MediaLogMessageType.Debug, $"SYNC-BUFFER: Finished. Clock set to {wallClock.Format()}");
                    }

                    // If not already set, guess the 1-second buffer length
                    State.GuessBufferingProperties();

                    // Complete the frame decoding cycle
                    FrameDecodingCycle.Complete();

                    // Give it a break if there was nothing to decode.
                    // We probably need to wait for some more input
                    if (Commands.IsStopWorkersPending == false &&
                        decodedFrameCount <= 0 &&
                        Commands.HasQueuedCommands == false)
                    {
                        delay.WaitOne();
                    }

                    #endregion
                }
            }
            catch { throw; }
            finally
            {
                // Always exit notifying the cycle is done.
                FrameDecodingCycle.Complete();
                delay.Dispose();
            }

            #endregion
        }
 public void Pause(object sender, EventArgs e)
 {
     MediaComponent.pause();
 }
예제 #18
0
        //POST: /admin/pages/create
        public async Task <IActionResult> Create(IFormCollection request,
                                                 [Bind("Name", "Description", "Section")] Page page)
        {
            PageTemplate template = await _Db.PageTemplates.FindAsync(
                request.Int("templateId"));

            if (template == null)
            {
                return(NotFound($"The chosen template was not found."));
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest("Server side validation failed."));
            }

            try
            {
                await _Db.AddAsync(page);

                // Create initial page revision
                PageRevision pageRevision = new PageRevision
                {
                    Page      = page,
                    Template  = template,
                    CreatedBy = await _Db.Accounts.FindAsync(User.AccountId())
                };
                await _Db.AddAsync(pageRevision);

                // Create empty text fields, and associate to new page
                for (int i = 0; i < template.TextAreas; i++)
                {
                    TextComponent textField = new TextComponent {
                        SlotNo = i
                    };
                    await _Db.AddAsync(textField);

                    await _Db.AddAsync(new RevisionTextComponent
                    {
                        TextComponent = textField,
                        PageRevision  = pageRevision,
                    });
                }

                // Create empty media fields, and associate to new page
                for (int i = 0; i < template.MediaAreas; i++)
                {
                    MediaComponent mediaComponent = new MediaComponent {
                        SlotNo = i
                    };
                    await _Db.AddAsync(mediaComponent);

                    await _Db.AddAsync(new RevisionMediaComponent
                    {
                        PageRevisionId   = pageRevision.Id,
                        MediaComponentId = mediaComponent.Id
                    });
                }

                // Save all to database in one transaction
                await _Db.SaveChangesAsync();

                // Return new page URL to the caller
                return(Ok(page.AbsoluteUrl));
            }
            catch (Exception ex)
            {
                _Logger.LogWarning("Error creating new page: {0}", ex.Message);
                _Logger.LogWarning(ex.StackTrace);
                return(BadRequest("There was an error creating the page. Please try again later."));
            }
        }
예제 #19
0
        /// <summary>
        /// Continually decodes the available packet buffer to have as
        /// many frames as possible in each frame queue and
        /// up to the MaxFrames on each component
        /// </summary>
        internal void RunFrameDecodingWorker()
        {
            try
            {
                // State variables
                var decodedFrameCount = 0;
                var wallClock         = TimeSpan.Zero;
                var rangePercent      = 0d;
                var isInRange         = false;

                // Holds the main media type
                var main = Container.Components.Main.MediaType;

                // Holds the auxiliary media types
                var auxs = Container.Components.MediaTypes.Where(x => x != main).ToArray();

                // Holds all components
                var all = Container.Components.MediaTypes.ToArray();

                var isBuffering     = false;
                var resumeClock     = false;
                var hasPendingSeeks = false;

                MediaComponent   comp   = null;
                MediaBlockBuffer blocks = null;

                while (IsTaskCancellationPending == false)
                {
                    #region 1. Setup the Decoding Cycle

                    // Singal a Seek starting operation
                    hasPendingSeeks = Commands.PendingCountOf(MediaCommandType.Seek) > 0;
                    if (IsSeeking == false && hasPendingSeeks)
                    {
                        IsSeeking = true;
                        RaiseSeekingStartedEvent();
                    }

                    // Execute the following command at the beginning of the cycle
                    Commands.ProcessNext();

                    // Signal a Seek ending operation
                    hasPendingSeeks = Commands.PendingCountOf(MediaCommandType.Seek) > 0;
                    if (IsSeeking == true && hasPendingSeeks == false)
                    {
                        SnapVideoPosition(Clock.Position);
                        IsSeeking = false;

                        // Call the seek method on all renderers
                        foreach (var kvp in Renderers)
                        {
                            kvp.Value.Seek();
                        }

                        RaiseSeekingEndedEvent();
                    }

                    // Wait for a seek operation to complete (if any)
                    // and initiate a frame decoding cycle.
                    SeekingDone?.WaitOne();

                    // Initiate the frame docding cycle
                    FrameDecodingCycle?.Reset();

                    // Set initial state
                    wallClock         = Clock.Position;
                    decodedFrameCount = 0;

                    #endregion

                    #region 2. Main Component Decoding

                    // Capture component and blocks for easier readability
                    comp   = Container.Components[main];
                    blocks = Blocks[main];

                    // Handle the main component decoding; Start by checking we have some packets
                    if (comp.PacketBufferCount > 0)
                    {
                        // Detect if we are in range for the main component
                        isInRange = blocks.IsInRange(wallClock);

                        if (isInRange == false)
                        {
                            // Signal the start of a sync-buffering scenario
                            HasDecoderSeeked = true;
                            isBuffering      = true;
                            resumeClock      = Clock.IsRunning;
                            Clock.Pause();
                            Logger.Log(MediaLogMessageType.Debug, $"SYNC-BUFFER: Started.");

                            // Read some frames and try to get a valid range
                            do
                            {
                                // Try to get more packets by waiting for read cycles.
                                if (CanReadMorePackets && comp.PacketBufferCount <= 0)
                                {
                                    PacketReadingCycle?.WaitOne();
                                }

                                // Decode some frames and check if we are in reange now
                                decodedFrameCount += AddBlocks(main);
                                isInRange          = blocks.IsInRange(wallClock);

                                // Break the cycle if we are in range
                                if (isInRange || CanReadMorePackets == false)
                                {
                                    break;
                                }
                            }while (decodedFrameCount <= 0 && blocks.IsFull == false);

                            // Unfortunately at this point we will need to adjust the clock after creating the frames.
                            // to ensure tha mian component is within the clock range if the decoded
                            // frames are not with range. This is normal while buffering though.
                            if (isInRange == false)
                            {
                                // Update the wall clock to the most appropriate available block.
                                if (blocks.Count > 0)
                                {
                                    wallClock = blocks[wallClock].StartTime;
                                }
                                else
                                {
                                    resumeClock = false; // Hard stop the clock.
                                }
                                // Update the clock to what the main component range mandates
                                Clock.Position = wallClock;

                                // Call seek to invalidate renderer
                                Renderers[main].Seek();
                            }
                        }
                        else
                        {
                            // Check if we need more blocks for the current components
                            rangePercent = blocks.GetRangePercent(wallClock);

                            // Read as many blocks as we possibly can
                            while (comp.PacketBufferCount > 0 &&
                                   ((rangePercent > 0.75d && blocks.IsFull) || blocks.IsFull == false))
                            {
                                decodedFrameCount += AddBlocks(main);
                                rangePercent       = blocks.GetRangePercent(wallClock);
                            }
                        }
                    }

                    #endregion

                    #region 3. Auxiliary Component Decoding

                    foreach (var t in auxs)
                    {
                        if (IsSeeking)
                        {
                            continue;
                        }

                        // Capture the current block buffer and component
                        // for easier readability
                        comp      = Container.Components[t];
                        blocks    = Blocks[t];
                        isInRange = blocks.IsInRange(wallClock);

                        // Invalidate the renderer if we don't have the block.
                        if (isInRange == false)
                        {
                            Renderers[t].Seek();
                        }

                        // wait for component to get there if we only have furutre blocks
                        // in auxiliary component.
                        if (blocks.Count > 0 && blocks.RangeStartTime > wallClock)
                        {
                            continue;
                        }

                        // Try to catch up with the wall clock
                        while (blocks.Count == 0 || blocks.RangeEndTime <= wallClock)
                        {
                            // Wait for packets if we don't have enough packets
                            if (CanReadMorePackets && comp.PacketBufferCount <= 0)
                            {
                                PacketReadingCycle?.WaitOne();
                            }

                            if (comp.PacketBufferCount <= 0)
                            {
                                break;
                            }
                            else
                            {
                                decodedFrameCount += AddBlocks(t);
                            }
                        }

                        isInRange = blocks.IsInRange(wallClock);

                        // Move to the next component if we don't meet a regular conditions
                        if (isInRange == false || isBuffering || comp.PacketBufferCount <= 0)
                        {
                            continue;
                        }

                        // Read as much as we can for this cycle.
                        while (comp.PacketBufferCount > 0)
                        {
                            rangePercent = blocks.GetRangePercent(wallClock);

                            if (blocks.IsFull == false || (blocks.IsFull && rangePercent > 0.75d && rangePercent < 1d))
                            {
                                decodedFrameCount += AddBlocks(t);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    #endregion

                    #region 4. Detect End of Media

                    // Detect end of block rendering
                    if (isBuffering == false &&
                        IsSeeking == false &&
                        CanReadMoreFramesOf(main) == false &&
                        Blocks[main].IndexOf(wallClock) == Blocks[main].Count - 1)
                    {
                        if (HasMediaEnded == false)
                        {
                            // Rendered all and nothing else to read
                            Clock.Pause();
                            Clock.Position = NaturalDuration.HasTimeSpan ?
                                             NaturalDuration.TimeSpan : Blocks[main].RangeEndTime;
                            wallClock = Clock.Position;

                            HasMediaEnded = true;
                            MediaState    = MediaState.Pause;
                            RaiseMediaEndedEvent();
                        }
                    }
                    else
                    {
                        HasMediaEnded = false;
                    }

                    #endregion

                    #region 6. Finish the Cycle

                    // complete buffering notifications
                    if (isBuffering)
                    {
                        // Reset the buffering flag
                        isBuffering = false;

                        // Resume the clock if it was playing
                        if (resumeClock)
                        {
                            Clock.Play();
                        }

                        // log some message
                        Logger.Log(
                            MediaLogMessageType.Debug,
                            $"SYNC-BUFFER: Finished. Clock set to {wallClock.Format()}");
                    }

                    // Complete the frame decoding cycle
                    FrameDecodingCycle?.Set();

                    // After a seek operation, always reset the has seeked flag.
                    HasDecoderSeeked = false;

                    // Give it a break if there was nothing to decode.
                    // We probably need to wait for some more input
                    if (decodedFrameCount <= 0 && Commands.PendingCount <= 0)
                    {
                        Task.Delay(1).GetAwaiter().GetResult();
                    }

                    #endregion
                }
            }
            catch (ThreadAbortException)
            {
            }
            finally
            {
                // Always exit notifying the cycle is done.
                FrameDecodingCycle?.Set();
            }
        }
예제 #20
0
        /// <summary>
        /// Initializes Player.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInitialized(EventArgs e)
        {
            Application.Current.DispatcherUnhandledException += (Sender, Args) =>
            {
                using (FileStream FS = File.Create("exception.txt"))
                    using (TextWriter Writer = new StreamWriter(FS))
                        WriteExceptionDetails(Args.Exception, Writer);

                MessageBox.Show("An exception has been encountered. The exact details have been saved in exception.txt. Please contact the developer and hand them this file.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
#if !DEBUG
                Args.Handled = true;
#endif
                Application.Current.Shutdown( );
            };

            Player = new ViderePlayer(new WindowData {
                Window = this, MediaControlsContainer = MediaControlsContainer, MediaPlayer = new VLCPlayer(MediaArea.MediaPlayer), MediaArea = MediaArea
            });

            MediaComponent mediaComponent = Player.GetComponent <MediaComponent>( );
            mediaComponent.OnMediaLoaded       += OnOnMediaLoaded;
            mediaComponent.OnMediaUnloaded     += OnOnMediaUnloaded;
            mediaComponent.OnMediaFailedToLoad += MediaComponentOnOnMediaFailedToLoad;

            WindowButtonCommandsOverlayBehavior = WindowCommandsOverlayBehavior.Never;
            RightWindowCommandsOverlayBehavior  = WindowCommandsOverlayBehavior.Never;
            LeftWindowCommandsOverlayBehavior   = WindowCommandsOverlayBehavior.Never;

            Client = new Client(UserAgent);

            Application.Current.Exit += (sender, args) =>
            {
                Settings.Default.SubtitleTimeOffset = 0;
                Settings.Default.Save( );
            };

            KeyDown += OnKeyDown;

            StateComponent  stateComponent  = Player.GetComponent <StateComponent>( );
            ScreenComponent screenComponent = Player.GetComponent <ScreenComponent>( );

            stateComponent.OnStateChanged += (Sender, Args) =>
            {
                switch (Args.State)
                {
                case StateComponent.PlayerState.Playing:
                    screenComponent.DisableSleeping( );
                    break;

                case StateComponent.PlayerState.Paused:
                case StateComponent.PlayerState.Stopped:
                    screenComponent.EnableSleeping( );
                    break;
                }
            };

            string[] cmdArgs = Environment.GetCommandLineArgs( );
            if (cmdArgs.Length > 1)
            {
                Player.GetComponent <MediaComponent>( ).LoadMedia(cmdArgs[1]);
            }

            base.OnInitialized(e);

            (( OpenSubtitlesControl )this.OSFlyout.Content).InitWindow(this);
        }
예제 #21
0
        public async Task <IActionResult> CreateRevision(int pageId, IFormCollection request)
        {
            /* To be supplied in request body -
             *
             * Reason for change - e.g. Updated pricing information
             * Template ID
             * Collection of text components
             * Collection of media components
             *
             */
            try
            {
                // Load page from database
                Page page = await _Db.Pages.FindAsync(pageId);

                if (page == null)
                {
                    return(BadRequest("No page exists for given page ID"));
                }

                List <TextComponent> newRevisionTextComponents =
                    request.Deserialize(typeof(List <TextComponent>), "textComponents");

                List <MediaComponent> newRevisionMediaComponents =
                    request.Deserialize(typeof(List <MediaComponent>), "imageComponents");

                // Todo: Do this after the view has had template switching enabled
                // Load template from database
                // PageTemplate template = await _Db.PageTemplates
                //    .FindAsync(request.Int("templateId"));

                // Fetch the original revision
                PageRevision old = await _Db.PageRevisions
                                   .Include(pr => pr.Template)
                                   .Include(pr => pr.RevisionMediaComponents)
                                   .ThenInclude(rmc => rmc.MediaComponent)
                                   .Include(pr => pr.RevisionTextComponents)
                                   .ThenInclude(rtc => rtc.TextComponent)
                                   .ThenInclude(tc => tc.CmsButton)
                                   .Where(pr => pr.Page == page)
                                   .OrderByDescending(pr => pr.CreatedAt)
                                   .FirstOrDefaultAsync();

                var oldRevision = new
                {
                    old.Template,
                    TextComponents = old.RevisionTextComponents
                                     .Select(rtc => rtc.TextComponent)
                                     .OrderBy(tc => tc.SlotNo)
                                     .ToList(),

                    MediaComponents = old.RevisionMediaComponents
                                      .Select(rmc => rmc.MediaComponent)
                                      .OrderBy(tc => tc.SlotNo)
                                      .ToList()
                };

                // Create the new page revision
                PageRevision newRevision = new PageRevision
                {
                    Page      = page,
                    Template  = oldRevision.Template,
                    Reason    = request.Str("reason"),
                    CreatedBy = await _Db.Accounts.FindAsync(User.AccountId()),
                };

                // Assign the new revision an ID
                await _Db.AddAsync(newRevision);

                for (int i = 0; i < newRevision.Template.TextAreas; i++)
                {
                    TextComponent textComponentToSave = null;

                    // Only save a new text component if it has changed
                    if (!newRevisionTextComponents[i].Equals(oldRevision.TextComponents[i]))
                    {
                        textComponentToSave = newRevisionTextComponents[i];

                        // Set ID to 0 so that EF Core assigns us a new one
                        textComponentToSave.Id = 0;

                        // Save a new button if the components button does not yet exist in database.
                        if (textComponentToSave.CmsButton != null &&
                            !textComponentToSave.CmsButton.Equals(oldRevision.TextComponents[i].CmsButton))
                        {
                            await _Db.AddAsync(textComponentToSave.CmsButton);
                        }

                        // Generate ID for the new TextComponent
                        await _Db.AddAsync(textComponentToSave);
                    }

                    // Add association between component and new revision
                    await _Db.AddAsync(new RevisionTextComponent
                    {
                        // Use the new components ID if it exists, other use existing (unchanged) component
                        // from previous revision
                        TextComponentId = textComponentToSave?.Id ?? oldRevision.TextComponents[i].Id,
                        PageRevisionId  = newRevision.Id
                    });
                }

                // Do the same for media components
                for (int i = 0; i < newRevision.Template.MediaAreas; i++)
                {
                    MediaComponent mediaComponentToSave = null;

                    // Only create new media component if the old one was modified
                    if (!newRevisionMediaComponents[i].Equals(oldRevision.MediaComponents[i]))
                    {
                        mediaComponentToSave = newRevisionMediaComponents[i];

                        // Generate new ID
                        mediaComponentToSave.Id = 0;
                        await _Db.AddAsync(mediaComponentToSave);
                    }

                    // Add association to new revision
                    await _Db.AddAsync(new RevisionMediaComponent
                    {
                        PageRevisionId   = newRevision.Id,
                        MediaComponentId = mediaComponentToSave?.Id ?? oldRevision.MediaComponents[i].Id
                    });
                }

                // Save changes
                await _Db.SaveChangesAsync();

                _Logger.LogDebug("New page revision created for page {0} ({1}): {2}", pageId, page.Name, newRevision.Reason);

                return(Ok());
            }
            catch (Exception ex)
            {
                _Logger.LogError("Error creating new revision for page {0}: {1}", pageId, ex.Message);
                _Logger.LogError(ex.StackTrace);
                return(BadRequest("Something went wrong, please try again later."));
            }
        }
        /// <summary>
        /// Continually decodes the available packet buffer to have as
        /// many frames as possible in each frame queue and
        /// up to the MaxFrames on each component
        /// </summary>
        internal void RunFrameDecodingWorker()
        {
            #region Worker State Setup

            // The delay provider prevents 100% core usage
            var delay = new DelayProvider();

            // State variables
            var decodedFrameCount = 0;
            var wallClock         = TimeSpan.Zero;
            var rangePercent      = 0d;
            var isInRange         = false;
            var playAfterSeek     = false;

            // Holds the main media type
            var main = Container.Components.Main.MediaType;

            // Holds the auxiliary media types
            var auxs = Container.Components.MediaTypes.ExcludeMediaType(main);

            // Holds all components
            var all = Container.Components.MediaTypes.DeepCopy();

            var isBuffering     = false;
            var resumeClock     = false;
            var hasPendingSeeks = false;

            MediaComponent   comp   = null;
            MediaBlockBuffer blocks = null;

            #endregion

            #region Worker Loop

            try
            {
                while (IsTaskCancellationPending == false)
                {
                    #region 1. Setup the Decoding Cycle

                    // Singal a Seek starting operation
                    hasPendingSeeks = Commands.PendingCountOf(MediaCommandType.Seek) > 0;
                    if (State.IsSeeking == false && hasPendingSeeks)
                    {
                        playAfterSeek   = State.IsPlaying;
                        State.IsSeeking = true;
                        SendOnSeekingStarted();
                    }

                    // Execute the following command at the beginning of the cycle
                    Commands.ProcessNext();

                    // Wait for a seek operation to complete (if any)
                    // and initiate a frame decoding cycle.
                    SeekingDone.Wait();

                    // Set initial state
                    wallClock         = WallClock;
                    decodedFrameCount = 0;

                    // Signal a Seek ending operation
                    // TOD: Maybe this should go on the block rendering worker?
                    hasPendingSeeks = Commands.PendingCountOf(MediaCommandType.Seek) > 0;
                    if (State.IsSeeking && hasPendingSeeks == false)
                    {
                        // Detect a end of seek cycle and update to the final position
                        wallClock = SnapToFramePosition(WallClock);
                        Clock.Update(wallClock);
                        State.UpdatePosition(wallClock);

                        // Call the seek method on all renderers
                        foreach (var kvp in Renderers)
                        {
                            LastRenderTime[kvp.Key] = TimeSpan.MinValue;
                            kvp.Value.Seek();
                        }

                        SendOnSeekingEnded();
                        State.IsSeeking = false;
                        if (playAfterSeek)
                        {
                            Clock.Play();
                            State.UpdateMediaState(PlaybackStatus.Play);
                        }
                        else
                        {
                            State.UpdateMediaState(PlaybackStatus.Pause);
                        }
                    }
                    else if (State.IsSeeking == false)
                    {
                        // Notify position changes
                        State.UpdatePosition(wallClock);
                    }

                    // Initiate the frame docding cycle
                    FrameDecodingCycle.Begin();

                    #endregion

                    #region 2. Main Component Decoding

                    // Capture component and blocks for easier readability
                    comp   = Container.Components[main];
                    blocks = Blocks[main];

                    // Handle the main component decoding; Start by checking we have some packets
                    while (comp.PacketBufferCount <= 0 && CanReadMorePackets && ShouldReadMorePackets)
                    {
                        PacketReadingCycle.Wait(Constants.Interval.LowPriority);
                    }

                    if (comp.PacketBufferCount > 0)
                    {
                        // Detect if we are in range for the main component
                        isInRange = blocks.IsInRange(wallClock);

                        if (isInRange == false)
                        {
                            // Signal the start of a sync-buffering scenario
                            HasDecoderSeeked = true;
                            isBuffering      = true;
                            resumeClock      = Clock.IsRunning;
                            Clock.Pause();
                            Log(MediaLogMessageType.Debug, $"SYNC-BUFFER: Started.");

                            // Read some frames and try to get a valid range
                            do
                            {
                                // Try to get more packets by waiting for read cycles.
                                if (CanReadMorePackets && comp.PacketBufferCount <= 0)
                                {
                                    PacketReadingCycle.Wait();
                                }

                                // Decode some frames and check if we are in reange now
                                decodedFrameCount += AddBlocks(main);
                                isInRange          = blocks.IsInRange(wallClock);

                                // Break the cycle if we are in range
                                if (isInRange || CanReadMorePackets == false)
                                {
                                    break;
                                }
                            }while (decodedFrameCount <= 0 && blocks.IsFull == false);

                            // Unfortunately at this point we will need to adjust the clock after creating the frames.
                            // to ensure tha mian component is within the clock range if the decoded
                            // frames are not with range. This is normal while buffering though.
                            if (isInRange == false)
                            {
                                // Update the wall clock to the most appropriate available block.
                                if (blocks.Count > 0)
                                {
                                    wallClock = blocks[wallClock].StartTime;
                                }
                                else
                                {
                                    resumeClock = false; // Hard stop the clock.
                                }
                                // Update the clock to what the main component range mandates
                                Clock.Update(wallClock);

                                // Call seek to invalidate renderer
                                LastRenderTime[main] = TimeSpan.MinValue;
                                Renderers[main].Seek();

                                // Try to recover the regular loop
                                isInRange = true;
                                while (CanReadMorePackets && comp.PacketBufferCount <= 0)
                                {
                                    PacketReadingCycle.Wait();
                                }
                            }
                        }

                        if (isInRange)
                        {
                            // Check if we need more blocks for the current components
                            rangePercent = blocks.GetRangePercent(wallClock);

                            // Read as much as we can for this cycle.
                            while (comp.PacketBufferCount > 0)
                            {
                                rangePercent = blocks.GetRangePercent(wallClock);

                                if (blocks.IsFull == false || (blocks.IsFull && rangePercent > 0.75d && rangePercent < 1d))
                                {
                                    decodedFrameCount += AddBlocks(main);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region 3. Auxiliary Component Decoding

                    foreach (var t in auxs)
                    {
                        if (State.IsSeeking)
                        {
                            continue;
                        }

                        // Capture the current block buffer and component
                        // for easier readability
                        comp      = Container.Components[t];
                        blocks    = Blocks[t];
                        isInRange = blocks.IsInRange(wallClock);

                        // Invalidate the renderer if we don't have the block.
                        if (isInRange == false)
                        {
                            LastRenderTime[t] = TimeSpan.MinValue;
                            Renderers[t].Seek();
                        }

                        // wait for component to get there if we only have furutre blocks
                        // in auxiliary component.
                        if (blocks.Count > 0 && blocks.RangeStartTime > wallClock)
                        {
                            continue;
                        }

                        // Try to catch up with the wall clock
                        while (blocks.Count == 0 || blocks.RangeEndTime <= wallClock)
                        {
                            // Wait for packets if we don't have enough packets
                            if (CanReadMorePackets && comp.PacketBufferCount <= 0)
                            {
                                PacketReadingCycle.Wait();
                            }

                            if (comp.PacketBufferCount <= 0)
                            {
                                break;
                            }
                            else
                            {
                                decodedFrameCount += AddBlocks(t);
                            }
                        }

                        isInRange = blocks.IsInRange(wallClock);

                        // Move to the next component if we don't meet a regular conditions
                        if (isInRange == false || isBuffering || comp.PacketBufferCount <= 0)
                        {
                            continue;
                        }

                        // Read as much as we can for this cycle.
                        while (comp.PacketBufferCount > 0)
                        {
                            rangePercent = blocks.GetRangePercent(wallClock);

                            if (blocks.IsFull == false || (blocks.IsFull && rangePercent > 0.75d && rangePercent < 1d))
                            {
                                decodedFrameCount += AddBlocks(t);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    #endregion

                    #region 4. Detect End of Media

                    // Detect end of block rendering
                    // TODO: Maybe this detection should be performed on the BlockRendering worker?
                    if (isBuffering == false &&
                        State.IsSeeking == false &&
                        CanReadMoreFramesOf(main) == false &&
                        Blocks[main].IndexOf(wallClock) == Blocks[main].Count - 1)
                    {
                        if (State.HasMediaEnded == false)
                        {
                            // Rendered all and nothing else to read
                            Clock.Pause();

                            if (State.NaturalDuration != null && State.NaturalDuration != TimeSpan.MinValue)
                            {
                                wallClock = State.NaturalDuration.Value;
                            }
                            else
                            {
                                wallClock = Blocks[main].RangeEndTime;
                            }

                            Clock.Update(wallClock);
                            State.HasMediaEnded = true;
                            State.UpdateMediaState(PlaybackStatus.Stop, wallClock);
                            SendOnMediaEnded();
                        }
                    }
                    else
                    {
                        State.HasMediaEnded = false;
                    }

                    #endregion

                    #region 6. Finish the Cycle

                    // complete buffering notifications
                    if (isBuffering)
                    {
                        // Reset the buffering flag
                        isBuffering = false;

                        // Resume the clock if it was playing
                        if (resumeClock)
                        {
                            Clock.Play();
                        }

                        // log some message
                        Log(
                            MediaLogMessageType.Debug,
                            $"SYNC-BUFFER: Finished. Clock set to {wallClock.Format()}");
                    }

                    // Complete the frame decoding cycle
                    FrameDecodingCycle.Complete();

                    // After a seek operation, always reset the has seeked flag.
                    HasDecoderSeeked = false;

                    // If not already set, guess the 1-second buffer length
                    State.GuessBufferingProperties();

                    // Give it a break if there was nothing to decode.
                    // We probably need to wait for some more input
                    if (decodedFrameCount <= 0 && Commands.PendingCount <= 0)
                    {
                        delay.WaitOne();
                    }

                    #endregion
                }
            }
            catch (ThreadAbortException) { /* swallow */ }
            catch { if (!IsDisposed)
                    {
                        throw;
                    }
            }
            finally
            {
                // Always exit notifying the cycle is done.
                FrameDecodingCycle.Complete();
                delay.Dispose();
            }

            #endregion
        }
예제 #23
0
        private void RemoveSong(OptionArgs args)
        {
            MediaComponent.removeSong(args.text);

            dynamicInitialize();
        }