/MonoGame.Framework/Android/Audio/Sound.cs

https://github.com/notJUSTguitar/MonoGame
C# | 180 lines | 145 code | 33 blank | 2 comment | 15 complexity | f474a082db99d44270de5055bda6a203 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using Android.App;
  7. using Android.Content;
  8. using Android.Media;
  9. using Android.OS;
  10. using Android.Runtime;
  11. using Android.Util;
  12. using Android.Views;
  13. using Android.Widget;
  14. namespace Microsoft.Xna.Framework.Audio
  15. {
  16. public class Sound
  17. {
  18. internal MediaPlayer _player;
  19. private float _Volume;
  20. private bool _Looping;
  21. private static bool Running = true;
  22. private static Queue<Action> WorkItems = new Queue<Action>();
  23. private static void Enqueue(Action workItem)
  24. {
  25. lock (Sound.WorkItems)
  26. {
  27. Sound.WorkItems.Enqueue(workItem);
  28. Monitor.Pulse(Sound.WorkItems);
  29. }
  30. }
  31. private static void Worker(object state)
  32. {
  33. while (Sound.Running)
  34. {
  35. Action workItem;
  36. lock (Sound.WorkItems)
  37. {
  38. if (Sound.WorkItems.Count == 0)
  39. Monitor.Wait(Sound.WorkItems);
  40. workItem = Sound.WorkItems.Dequeue();
  41. }
  42. try
  43. {
  44. workItem();
  45. }
  46. catch
  47. {
  48. Log.Debug("Sound.Worker" , "Sound thread: Work Exception");
  49. }
  50. }
  51. }
  52. static Sound()
  53. {
  54. ThreadPool.QueueUserWorkItem(Worker);
  55. }
  56. private Sound(MediaPlayer player)
  57. {
  58. _player = player;
  59. }
  60. public void Dispose()
  61. {
  62. _player.Dispose();
  63. }
  64. public float Volume
  65. {
  66. get { return this._Volume; }
  67. set
  68. {
  69. this._Volume = value;
  70. if (this._player == null)
  71. return;
  72. _player.SetVolume(value, value);
  73. }
  74. }
  75. public bool Looping
  76. {
  77. get { return this._Looping; }
  78. set
  79. {
  80. if (this._Looping != value) {
  81. this._Looping = value;
  82. if (_player == null)
  83. return;
  84. _player.Looping = value;
  85. }
  86. }
  87. }
  88. public void Play()
  89. {
  90. if (this._player == null)
  91. return;
  92. Sound.Enqueue(_player.Start);
  93. }
  94. public void Pause()
  95. {
  96. if (this._player == null)
  97. return;
  98. lock (Sound.WorkItems) {
  99. _player.Pause();
  100. }
  101. }
  102. public void Stop()
  103. {
  104. if (this._player == null)
  105. return;
  106. lock (Sound.WorkItems) {
  107. _player.Stop();
  108. }
  109. }
  110. public float Pan
  111. {
  112. get;
  113. set;
  114. }
  115. public bool Playing
  116. {
  117. get
  118. {
  119. return _player.IsPlaying;
  120. }
  121. }
  122. internal bool IsPrepared { get; private set; }
  123. protected void OnPrepared(object sender, EventArgs e)
  124. {
  125. IsPrepared = true;
  126. }
  127. public static Sound Create(string assetPath, float volume, bool looping)
  128. {
  129. MediaPlayer player = new MediaPlayer();
  130. Sound sound = new Sound(player);
  131. //This breaks the platformer sample. Not sure if it works anywhere else
  132. //player.SetDataSource(Game.contextInstance.Assets.OpenFd(assetPath).FileDescriptor);
  133. player.SetDataSource(assetPath);
  134. player.Prepared += sound.OnPrepared;
  135. sound.Looping = looping;
  136. sound.Volume = volume;
  137. Sound.Enqueue(player.Prepare);
  138. return sound;
  139. }
  140. public static Sound CreateAndPlay(string url, float volume, bool looping)
  141. {
  142. Sound sound = Sound.Create(url, volume, looping);
  143. sound.Play();
  144. return sound;
  145. }
  146. }
  147. }