Search code examples
c#.net.net-4.0soundplayer

Soundplayer refusing to replay after stopping it once


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?


Solution

  • 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.