2

I've found a strange problem and I'll try to explain it as short as possible.

ASSUMTIONS:

According to my knowledge as you set a new AudioTrack to AudioPlayerAgent, two task are queued: Stop(), and TrackReady();. Seems logic and in most cases works perfect. But as I was working with my program, I spotted that sometimes it's not so good:

PROBLEM:

So I decided to write a very simple example - you can get it here. There is only one buton that calls BackgroundAudioPlayer.Instance.Play();. (You have to add only music.mp3 file in that example - for example 5-6 Mb mp3 file). In Audio Agent I have:

case UserAction.Play:
if (player.PlayerState != PlayState.Playing)
      player.Track = myMusic.ReturnTrack();
break;

I run program in Debug mode on Device (WP8) and push my play button. And then I see in most cases that OnPlayStateChanged in Audio Agent is not fired, and looking at processes, I see I have Headless 'Zombie'. Seems to be a deadlock. (BTW: in this simple example I'm not using any Mutexes or other concurrency techniques) Strange (or maybe not) is also that Stop() and TrackReady are waiting in a queue - if you fire any other method that calls NotifyComplete(); you will see that queue gets unblocked.
I've tried Realese version without debbuging and it works better BUT - sometimes happens the same.

If I only add:

case UserAction.Play:
if (player.PlayerState != PlayState.Playing)
{
      player.Track = myMusic.ReturnTrack();
      Thread.Sleep(100);
}
break;

everything works a lot better.

CONCLUSION:

It seems to me that loading new track works asynchronously and NotifyComplete() is called before track is loaded - what creates this 'headless zombie' process. The worst thing is that you have limited time for operation waiting in queue, after it runs out, your Agent is being killed.
In my opinion it shouldn't work like that, as setting new track is one of the major functions.

Does anybody know something about this problem? Is it a bug or misbehaviour of OS or my lack of knowledge?

Romasz
  • 29,662
  • 13
  • 79
  • 154

1 Answers1

0

You've wired this up incorrectly - it's worth trying to check the default implementation of a background audio agent and compare with that. The main issue would appear that you are trying to change track in OnUserAction.Play, which the APIs don't expect...

You need to specify your track in:

    protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
    {
        switch (playState)
        {
            case PlayState.TrackEnded:
                player.Track = myMusic.ReturnTrack();
                break;

And leave the OnUserAction as:

    protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)
    {
        switch (action)
        {
            case UserAction.Play:
                if (player.PlayerState != PlayState.Playing)
                {
                    player.Play();
                }
                break;
Paul Annetts
  • 9,554
  • 1
  • 27
  • 43
  • But please look that when I want for example use SkipNext() and use that method I face the same problem with loading track and NotifyComplete. By the way I've also problem with the code you provided - please look that OnPlayStateChanged also consists NotifyComplete, and it seems to be similar situation. I'm also facing similar problem when listening to a list of tracks, and after some tracks - endtrack should load new, but sometimes my agent gets killed. Though it's hard to debug as it concers little percentage of cases. – Romasz Dec 06 '13 at 12:30
  • You don't have any code in SkipNext/Previous at least in your BAP_Bug project... SkipNext *should* directly set the track - if you look in the default implementation of a new BAP project that's what it does. – Paul Annetts Dec 06 '13 at 12:39
  • Yes, bacouse it had to be a simple example. There is no difference if it's a play button or SkipNext. And look that I'm setting this track directly - new Audiotrack(). I've also tried without this music.RetrunTrack() - the same result. – Romasz Dec 06 '13 at 12:42
  • Works for me on both Emulator and Phone *as long as I move the player.Track line*... Forget about NotifyComplete for a moment - does it work for you? – Paul Annetts Dec 06 '13 at 12:48
  • API does expect loading track in OnUseAction.Play - http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202978(v=vs.105).aspx - although the main clue may be that directly after changing track player.Play() is called. Which is little confusing for me, because music is already playing, and Playstates are invoked in such order: (if your player.track != null) PlayState.Playing, PlayState.Stopped, PlayState.TrackReady, and once more Playstate.Playing. BTW: thank you for your time and help. – Romasz Dec 06 '13 at 13:30
  • And according to code in your solution - it also produces the same problem (I'm working with Debuger on Lumia 820). Unless you provide player.Play() after changing track your program can get deadlock. – Romasz Dec 06 '13 at 14:35