Question

My problem:

I use the Media Class from Cordova. The MP3 file is only played once (the first time).

Code:

Add this code to the Cordova Starter project to reproduce my problem:

    var playCounter = 0;
    function playMP3(){
      console.log("playMP3() counter " + playCounter);
      var my_media = new Media("app/www/test.mp3");//ressource buildAction == content
      my_media.play();
      playCounter++;
    }
    [...]
    <p onclick="playMP3();">Click to Play MP3</p>

VS output:

[...]
GapBrowser_Navigated :: /app/www/index.html
'UI Task' (Managed): Loaded 'System.ServiceModel.Web.dll'
'UI Task' (Managed): Loaded 'System.ServiceModel.dll'
Log:"onDeviceReady. You should see this message in Visual Studio's output window."
'UI Task' (Managed): Loaded 'Microsoft.Xna.Framework.dll'
Log:"playMP3() counter 0"
'UI Task' (Managed): Loaded 'System.SR.dll'
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 1}"
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 2}"
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 2, \"value\": 2.141}"
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 4}"
Log:"playMP3() counter 1"
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
A first chance exception of type 'System.IO.IsolatedStorage.IsolatedStorageException' occurred in mscorlib.dll
Log:"media on status :: {\"id\": \"2de3388c-bbb6-d896-9e27-660f1402bc2a\", \"msg\": 9, \"value\": 5}"

My Config:

  • cordova-1.6.1.js
  • Lumia 800
  • WP 7.5 (7.10.7740.16)

WorkAround (kind of):

  • Desactivate the app (turn off the screen)
  • reactivate the app (turn on the screen)
  • -> you get one more shot.

Any help is welcome as I am blocked on this since may days and I found no usefull information anywhere.

Also, Can you tell me if this code work on your config ?

.

.

.

Update: add a demo code, Cordova 1.8.0rc1

using a global var. Keeping the instance alive.

result

  • The test2.mp3 is played and can replay fine.
  • the test.mp3 is not played at all.
  • It is the first file you play that will work.

Code

  function onDeviceReady()
  {
  document.getElementById("welcomeMsg").innerHTML += "Cordova is ready! version=" + window.device.cordova;
  console.log("onDeviceReady. You should see this message in Visual Studio's output window.");
  my_media = new Media("app/www/test.mp3");//ressource buildAction == content
  my_media2 = new Media("app/www/test2.mp3");//ressource buildAction == content
  }

  var playCounter = 0;
  var my_media = null;
  function playMP3(){
    console.log("playMP3() counter " + playCounter);
    my_media.play();
    playCounter++;
  }

  var my_media2 = null;
  function playMP32(){
    console.log("playMP32() counter " + playCounter);
    my_media2.play();
    playCounter++;
  }

</script>
[...]

<p onclick="playMP3();">Click to Play MP3</p>
<p onclick="playMP32();">Click to Play MP3 2</p>

VS output:

Log:"onDeviceReady. You should see this message in Visual Studio's output window."
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b
Log:"playMP32() counter 0"
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b
Log:"playMP32() counter 1"
Log:"playMP3() counter 2"
INFO: startPlayingAudio could not find mediaPlayer for b60fa266-d105-a295-a5be-fa2c6b824bc1
A first chance exception of type 'System.ArgumentException' occurred in System.Windows.dll
Error: El parámetro es incorrecto. 
Log:"playMP32() counter 3"
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b

.

.

.

Update: Cordova 2.0.0

I upated the Apache bug report with a test case for 2.0.0.

Can anybody reproduce this ?

link to bug report: https://issues.apache.org/jira/browse/CB-941

Was it helpful?

Solution 5

was a Cordova bug https://issues.apache.org/jira/browse/CB-941

solved by purpulecabbage in his repo of gitHub. see comment on bug report.

OTHER TIPS

I see you are getting an IsolatedStorageException on the second click, which makes me think the file is being held open by the first Media instance which prevents it from being accessed again.

I suggest ensuring that you either only create one instance of Media per file or see if there is a way to dispose of the old instance first.

Here is what I would try (but I haven't tested):

 var playCounter = 0;

 // moved my_media here so it won't be recreated
 var my_media = new Media("app/www/test.mp3");//ressource buildAction == content

    function playMP3(){
      console.log("playMP3() counter " + playCounter);
      my_media.play();
      playCounter++;
    }
    [...]
    <p onclick="playMP3();">Click to Play MP3</p>

almost forgot ... this works for my purposes. Hope it helps ;-)

WP7.5/Cordova 1.9.0

REQUIREMENT: Only works with .wav files as far as I know. I had to convert my .mp3 files, as they throw ugly exceptions.

PLUGIN:C#:

namespace Cordova.Extension.Commands
{
    public class PGSoundFX : BaseCommand
    {
        public Dictionary <string, SoundEffect> fxSoundMap = new Dictionary<string,SoundEffect>();

    public enum FXType
    {
        Load=0,
        Play=1
    }

    [DataContract]
    public class FXOption
    {
        [DataMember]
        public string audioSrc;
        [DataMember]
        public string audioRef;
        [DataMember]
        public FXType fxType; 
    }

    public void groAudio(string options)
    {
        FrameworkDispatcher.Update(); 
        FXOption opts;

        opts = WP7CordovaClassLib.Cordova.JSON.JsonHelper.Deserialize<FXOption>(options);

        if (opts != null)
        {
            try
            {
                switch (opts.fxType)
                {
                    case FXType.Load:
                        loadSound(opts.audioSrc, opts.audioRef);
                        break;
                    case FXType.Play:
                        Dictionary<string, SoundEffect>.KeyCollection keyCol = fxSoundMap.Keys;
                        foreach (string tmp in keyCol)
                        {
                            if ((opts.audioRef).Equals(tmp))
                                playSound(fxSoundMap[tmp]);
                        }
                        break;
                }
            }
            catch
            {
                Debug.WriteLine("PGSoundFX: loadSound Error ... null parameter(s).");
            }
        }
    }

    /// <summary> 
    /// Loads a wav file into an XNA Framework SoundEffect. 
    /// </summary> 
    /// <param name="Sound">The SoundEffect to play.</param> 
    private void playSound(SoundEffect Sound)
    {
        Sound.Play();
        DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
    }

    /// <summary> 
    /// Loads a wav file into an XNA Framework SoundEffect. 
    /// </summary> 
    /// <param name="SoundFilePath">Relative path to the wav file.</param> 
    /// <param name="Sound">The SoundEffect to load the audio into.</param> 
    private void loadSound(String SoundFilePath, String SoundName)
    {
        if (fxSoundMap.Keys != null)
        {
            Dictionary<string, SoundEffect>.KeyCollection keyColl = fxSoundMap.Keys;
            foreach (string tmp in keyColl)
            {
                if (SoundName.Equals(tmp))
                    return;
            }
        }

        SoundEffect Sound = null;

        try
        {
            // Holds informations about a file stream. 
            StreamResourceInfo SoundFileInfo = Application.GetResourceStream(new Uri(SoundFilePath, UriKind.Relative));
            // Create the SoundEffect from the Stream 
            Sound = SoundEffect.FromStream(SoundFileInfo.Stream);
            fxSoundMap[SoundName] = Sound;
            DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
        }
        catch (NullReferenceException)
        {
            Debug.WriteLine("Couldn't load sound " + SoundFilePath);
        }
        } 
    }
}

Javascript:Plugin:

PhoneGap.addConstructor(function() {

navigator.plugins.pgSoundFX = 
{
    playSound:function(fxName)
    {
    var options = {"audioRef":fxName,"fxType":1};
    PhoneGap.exec(null, null, "PGSoundFX", "groAudio", options);
    },

    loadSound:function(fxSrc, fxName)
    {
    var options = {"audioSrc":fxSrc,"audioRef":fxName,"fxType":0};
    PhoneGap.exec(null, null, "PGSoundFX", "groAudio", options);
    }
}
});

Javascript:Use:

//NOTE: Allows you to pre-load sound effect files

//initialize pgSoundFX plugin
if (!navigator.plugins) {
    console.log("plugIns do not exist!");
    navigator.plugins = {};
}

navigator.plugins.pgSoundFX.loadSound("www/audio/file1.wav", "item1");
navigator.plugins.pgSoundFX.loadSound("www/audio/file2.wav", "item2");
navigator.plugins.pgSoundFX.loadSound("www/audio/file3.wav", "item3");
    :
    :

//NOTE: Play whenever needed
navigator.plugins.pgSoundFX.playSound("item1");

Of course, your file location (www/audio/), names (file1, etc.) and reference names (item1, etc) are whatever you want. As with most, lots of ways to improve this code...feel free. My use case pre-loads five .wav files ranging in size from 28k - 364k and plays them throughout user game play.

I am not sure it is the correct answer as I did not try it but consider it as a brain storming.

first create your audio with var my_media = new Media(src, onSuccess, onError); ctor and on success just play it and on error first try to release it with media.release code.

Well if you know some other event or action to release it would be more appropriate.

Edit : I just noticed it, you are not using stop for media you can also try to use it when it is needed for example beginning of the playMP3() if media is not null try to stop it first.

Cheers.

I think the issue may be with the limitation that Silverlight only allows one media instance per page...and since PG/Cordova is essentially a single-page webBrowser instance, it can only have one media instance. I am playing around with building an XNA SoundEffect plugin to get around this issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top