Ctrl K
ComunidadGuías…

MonoGame.Framework/Media/MediaPlayer.cs

Rama develop · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// MonoGame - Copyright (C) MonoGame Foundation, Inc
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.

using System;

namespace Microsoft.Xna.Framework.Media
{
    /// <summary>
    /// Provides methods and properties to play, pause, resume, and stop songs.
    /// MediaPlayer also exposes shuffle, repeat, volume, play position, and visualization capabilities.
    /// </summary>
    public static partial class MediaPlayer
    {
		// Need to hold onto this to keep track of how many songs
		// have played when in shuffle mode
		private static int _numSongsInQueuePlayed = 0;
		private static MediaState _state = MediaState.Stopped;
		private static float _volume = 1.0f;
		private static bool _isMuted;
        private static bool _isRepeating;
        private static bool _isShuffled;
		private static readonly MediaQueue _queue = new MediaQueue();

        /// <summary>
        /// Raised when the active song changes due to active playback or due to explicit calls to the
        /// <see cref="MoveNext()"/> or <see cref="MovePrevious()"/> methods.
        /// </summary>
		public static event EventHandler<EventArgs> ActiveSongChanged;
        /// <summary>
        /// Raised when the media player play state changes.
        /// </summary>
        public static event EventHandler<EventArgs> MediaStateChanged;

        static MediaPlayer()
        {
            PlatformInitialize();
        }

        #region Properties

        /// <summary>
        /// Gets the media playback queue, <see cref="MediaQueue"/>.
        /// </summary>
        public static MediaQueue Queue { get { return _queue; } }

        /// <summary>
        /// Gets or set the muted setting for the media player.
        /// </summary>
		public static bool IsMuted
        {
            get { return PlatformGetIsMuted(); }
            set { PlatformSetIsMuted(value); }
        }

        /// <summary>
        /// Gets or sets the repeat setting for the media player.
        /// </summary>
        /// <remarks>
        /// When set to <see langword="true"/>, the playback queue will begin
        /// playing again after all songs in the queue have been played.
        /// </remarks>
        public static bool IsRepeating 
        {
            get { return PlatformGetIsRepeating(); }
            set { PlatformSetIsRepeating(value); }
        }

        /// <summary>
        /// Gets or sets the shuffle setting for the media player.
        /// </summary>
        /// <remarks>
        /// When set to <see langword="true"/>, songs in the playback queue are
        /// played in random order rather than from first to last.
        /// </remarks>
        public static bool IsShuffled
        {
            get { return PlatformGetIsShuffled(); }
            set { PlatformSetIsShuffled(value); }
        }

        /// <summary>
        /// Gets or sets the visualization enabled setting for the media player.
        /// </summary>
        /// <remarks>
        /// Always returns <see langword="false"/>
        /// </remarks>
        public static bool IsVisualizationEnabled { get { return false; } }

        /// <summary>
        /// Gets the play position within the currently playing song.
        /// </summary>
        public static TimeSpan PlayPosition
        {
            get { return PlatformGetPlayPosition(); }
#if (IOS && !TVOS) || ANDROID
            set { PlatformSetPlayPosition(value); }
#endif
        }

        /// <summary>
        /// Gets the media playback state, <see cref="MediaState"/>
        /// </summary>
        public static MediaState State
        {
            get { return PlatformGetState(); }
            private set
            {
                if (_state != value)
                {
                    _state = value;
                    EventHelpers.Raise(null, MediaStateChanged, EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Determines whether the game has control of the background music.
        /// </summary>
        /// <remarks>
        /// If a gamer is currently playing their own music as the background to your game,
        /// calls to <see cref="Play(Song)"/>, <see cref="Stop()"/>, <see cref="Pause()"/>,
        /// <see cref="Resume()"/>, <see cref="MoveNext()"/>, and <see cref="MovePrevious"/>
        /// might have no effect, depending on the platform.
        /// </remarks>
        public static bool GameHasControl
        {
            get
            {
                return PlatformGetGameHasControl();
            }
        }

        /// <summary>
        /// Gets or sets the media player volume
        /// </summary>
        /// <value>
        /// Media player volume, from 0.0f (silence) to 1.0f (full volume relative to the current device volume)
        /// </value>
        /// <remarks>
        /// <para>
        /// Volume adjustment is based on a decibel, not multiplicative, scale.
        /// Setting <see cref="Volume"/> to 0.0 subtracts 96 dB from the volume.
        /// Setting <see cref="Volume"/> to 1.0 subtracts 0 dB from the volume.
        /// Values in between 0.0f and 1.0f subtract dB from the volume proportionally.
        /// </para>
        /// </remarks>
        public static float Volume
        {
            get { return PlatformGetVolume(); }
            set
            {
                var volume = MathHelper.Clamp(value, 0, 1);

                PlatformSetVolume(volume);
            }
        }

        #endregion

        /// <summary>
        /// Pauses the currently playing song.
        /// </summary>
        public static void Pause()
        {
            if (State != MediaState.Playing || _queue.ActiveSong == null)
                return;

            PlatformPause();

            State = MediaState.Paused;
        }

        /// <summary>
        /// Play clears the current playback queue, and then queues up the specified song for playback. 
        /// Playback starts immediately at the beginning of the song.
        /// </summary>
        public static void Play(Song song)
        {
            Play(song, null);
        }

        /// <summary>
        /// Play clears the current playback queue, and then queues up the specified song for playback. 
        /// Playback starts immediately at the given position of the song.
        /// </summary>
        public static void Play(Song song, TimeSpan? startPosition)
        {
            if (song == null)
                throw new ArgumentNullException("song", "This method does not accept null for this parameter.");

            var previousSong = _queue.Count > 0 ? _queue[0] : null;
            _queue.Clear();
            _numSongsInQueuePlayed = 0;
            _queue.Add(song);
            _queue.ActiveSongIndex = 0;
            
            PlaySong(song, startPosition);

            if (previousSong != song)
                EventHelpers.Raise(null, ActiveSongChanged, EventArgs.Empty);
        }

        /// <summary>
        /// Play clears the current playback queue, and then queues up the specified song collection for playback. 
        /// Playback starts immediately at the beginning of the song, specified by song collection index.
        /// </summary>
        public static void Play(SongCollection collection, int index = 0)
		{
            if (collection == null)
                throw new ArgumentNullException("collection", "This method does not accept null for this parameter.");

            _queue.Clear();
            _numSongsInQueuePlayed = 0;

			foreach(var song in collection)
				_queue.Add(song);
			
			_queue.ActiveSongIndex = index;
			
			PlaySong(_queue.ActiveSong, null);
		}

        private static void PlaySong(Song song, TimeSpan? startPosition)
        {
            if (song != null && song.IsDisposed)
                throw new ObjectDisposedException("song");

            PlatformPlaySong(song, startPosition);
            State = MediaState.Playing;
        }

        internal static void OnSongFinishedPlaying(object sender, EventArgs args)
		{
			// TODO: Check args to see if song sucessfully played
			_numSongsInQueuePlayed++;
			
			if (_numSongsInQueuePlayed >= _queue.Count)
			{
				_numSongsInQueuePlayed = 0;
				if (!IsRepeating)
				{
					Stop();
					EventHelpers.Raise(null, ActiveSongChanged, EventArgs.Empty);
					return;
				}
			}

			MoveNext();
		}

        /// <summary>
        /// Resumes a paused song.
        /// </summary>
        public static void Resume()
        {
            if (State != MediaState.Paused)
                return;

            PlatformResume();
			State = MediaState.Playing;
        }

        /// <summary>
        /// Stops playing a song.
        /// </summary>
        public static void Stop()
        {
            if (State == MediaState.Stopped)
                return;

            PlatformStop();
			State = MediaState.Stopped;
		}

        /// <summary>
        /// Stops currently playing song, moves to the next song in the queue of playing songs and plays it.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the current song is the last song in the queue, <see cref="MoveNext()"/> will stay on current song
        /// </para>
        /// </remarks>
		public static void MoveNext()
		{
			NextSong(1);
		}

        /// <summary>
        /// Stops currently playing song, moves to the previous song in the queue of playing songs and plays it.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the current song is the first song in the queue, <see cref="MovePrevious()"/> will stay on current song
        /// </para>
        /// </remarks>
        public static void MovePrevious()
		{
			NextSong(-1);
		}
		
		private static void NextSong(int direction)
		{
            Stop();

            if (IsRepeating && _queue.ActiveSongIndex >= _queue.Count - 1)
            {
                _queue.ActiveSongIndex = 0;
                
                // Setting direction to 0 will force the first song
                // in the queue to be played.
                // if we're on "shuffle", then it'll pick a random one
                // anyway, regardless of the "direction".
                direction = 0;
            }

			var nextSong = _queue.GetNextSong(direction, IsShuffled);

            if (nextSong != null)
                PlaySong(nextSong, null);

            EventHelpers.Raise(null, ActiveSongChanged, EventArgs.Empty);
		}
    }
}