0

I've created a sound player to play a certian sound out of a collection of sounds at any given time. One of the sounds in the collect needs to be played in a looping manner. Below is my code:

    public class SoundService : ISoundService
{
    private Dictionary<string, SoundPlayer> SoundCollections { get; set; }
    private SoundPlayer _soundPlayerPlaceHolder;
    private readonly CancellationTokenSource _cancellationToken = new CancellationTokenSource();
    private CancellationToken _token;

    public void Play(SoundType soundType)
    {
        _token = _cancellationToken.Token;
        Task.Factory.StartNew(() => PlaySound(soundType), _token);
    }

    private void PlayLooping(SoundType soundType)
    {
        if (!SoundCollections.ContainsKey(soundType.ToString()))
        {
            s_Log.Error("Error retrieving sound from Sound collection. XXX.SoundService");
            return;
        }
        _soundPlayerPlaceHolder = SoundCollections[soundType.ToString()];
        if (_token.IsCancellationRequested)
        {
            if (_soundPlayerPlaceHolder != null)
            {
                _soundPlayerPlaceHolder.Stop();
                _soundPlayerPlaceHolder = null;
            }
            return;
        }

        _soundPlayerPlaceHolder.PlayLooping();

    }

    public void StopSound()
    {
        _cancellationToken.Cancel();
    }

    public void LoadSounds()
    {
        var sounds = Enum.GetValues(typeof (SoundType));
        SoundCollections = new Dictionary<string,SoundPlayer>();
        foreach (var soundType in sounds)
        {
            var resourceName = GetResourceNameAttribute(soundType);
            if (string.IsNullOrEmpty(resourceName))
                continue;

            try
            {
                var stream = Resources.ResourceManager.GetStream(resourceName);

                var soundPlayer = new SoundPlayer(stream);
                soundPlayer.LoadAsync();

                SoundCollections.Add(soundType.ToString(), soundPlayer);
                s_Log.Info(string.Format(@"loading sound {0}", soundType));
            }
            catch (Exception e)
            {
                s_Log.Error(e);
            }
        }

    }

    private string GetResourceNameAttribute(object enumToQuery)
    {
        var fi = enumToQuery.GetType().GetField(enumToQuery.ToString());

        var attributes = (ResourceNameAttribute[])fi.GetCustomAttributes(
            typeof(ResourceNameAttribute), false);

        return attributes.Length > 0 ? attributes[0].ResourceName : enumToQuery.ToString();
    }


    /// <summary>
    /// .
    /// </summary>
    /// <param name="aSoundType"></param>
    private void PlaySound(SoundType aSoundType)
    {
        s_Log.Info("loading sound {0}", aSoundType.ToString());

        if (aSoundType == SoundType.ItemNotFound)
        {
            PlayLooping(aSoundType);
        }
        else
        {
            if (_soundPlayerPlaceHolder == null)
            SoundCollections[aSoundType.ToString()].Play();
        }
    }
}

The issue with this I'm experiencing is after a sound player plays in a loop(which is working) and the cancellation token is cancelled I'm unable to play the same sound in loop anymore. I'm not sure why this is the case and I've tried many other thread options (Task, BackgroundWorker) but I've had no luck. The single plays work fine, its just replaying the looping thats not working. No exceptions, nothing in the logs.... I'm lost... Thoughts?

Eric
  • 419
  • 4
  • 9
  • Actually I think it might be the Task that's the issue now.... seems to be sporadically hitting the PlaySound Method. – Eric Nov 26 '13 at 05:27

1 Answers1

0

Such a noob.... The cancellation token was the same each time the method was called. So when I cancelled it prior the Task wasn't firing.... Derp.

Eric
  • 419
  • 4
  • 9