ReferenceError: Media is not defined


#1

I’m new to Ionic, so a couple of questions about using audio.

Will using the cordova.media plugin work in the normal browser with $ionic serve? Are there any configurations I need to perform in the .run() part of the application?

I’ve installed both cordova.media, and cordova.file, but I get the ReferenceError: Media is not defined when I try to use Media with my own javascript or with the ngCordova $cordovaMedia service.


#2

Hi, yep, the code in ngCordova for Media seems to be whacky/impossible and basically never tested. I modified it to get it working so that I can

 var angSound = $cordovaMedia.newMedia(getSound('ang1'));
            $cordovaMedia.play(angSound).then(
                function(succ){
                    console.log('yay! '+succ);
                    $scope.soundDisabled = false;
                },
                function(err){
                    console.log('boo! '+err);
                    $scope.soundDisabled = false;
                }
            )

I assume this was the sort of use case that was in mind.

the play function now looks like this:

      play: function (source) {
         source.media.play();
         return source.promise;
}

before it looked like this:

   play: function (source) {
         return source.play();
}

#3

Actually, here is my change in its full “glory”. Totally tested to the extent that “it works for me”. It would be great if this (or something that was really tested) could find its way into the official build.
Thanks,

angular.module('ngCordova.plugins.media', [])

.factory(’$cordovaMedia’, [’$q’, function ($q) {

return {
  newMedia: function (src) {
    var q = $q.defer();
    var mediaStatus = null;

    var media = new Media(src,
      function (success) {
        q.resolve(success);
      }, function (error) {
        q.reject(error);
      }, function (status) {
        mediaStatus = status;
      });

    return {
      media: media,
      mediaStatus: mediaStatus,
      promise: q.promise
    }

  },

  getCurrentPosition: function (source) {
    var q = $q.defer();

    source.media.getCurrentPosition(function (success) {
      q.resolve(success);

    }, function (error) {
      q.reject(error);
    });

    return q.promise;
  },

  getDuration: function (source) {

    return source.getDuration();
  },

  play: function (source) {
     source.media.play();
     return source.promise;

    // iOS quirks :
    // -  myMedia.play({ numberOfLoops: 2 }) -> looping
    // -  myMedia.play({ playAudioWhenScreenIsLocked : false })
  },

  pause: function (source) {
    return source.pause();
  },

  release: function (source) {
    return source.release();
  },


  seekTo: function (source, milliseconds) {

    return source.seekTo(milliseconds);
  },

  setVolume: function (source, volume) {
    return source.setVolume(volume);
  },

  startRecord: function (source) {

    return source.startRecord();
  },

  stopRecord: function (source) {

    return source.stopRecord();
  },

  stop: function (source) {

    return source.stop();
  }
}

}]);


#4

thank you very much for taking the time to highlight this issue and thanks very much for this post, it’s taken me most of the weekend to get to the bottom of this!! just for info. If you take this approach you’ll need to do something similar for the other media functions too, i.e. stop pause etc…

but you know after some reflection, it would be better to change the constructor to a non-promisey one, but only make certain functions…like getDuration promisey. The reasoning here is that the media callbacks need to fire every time the file is played to allow ui updates, for example the play button could change to a pause button. If you make the constructor promisey it will only fire these callbacks the first time the file is played.

therefore you might want to change the constructor to the following

  newMedia: function (src,success,error,mediaStatus) { 
    var media = new Media(src,success,error,mediaStatus);
    return media;
  },

so the finished module would be something like

angular.module('ngCordova.plugins.media', [])

  .factory('$cordovaMedia', ['$q', function ($q) {

    return {
      newMedia: function (src,success,error,mediaStatus) { 
        var media = new Media(src,success,error,mediaStatus);
        return media;
      },

      getCurrentPosition: function (source) {
        var q = $q.defer();

        source.getCurrentPosition(function (success) {
          q.resolve(success);

        }, function (error) {
          q.reject(error);
        });

        return q.promise;
      },

      getDuration: function (source) {

        return source.getDuration();
      },

      play: function (source) {
        source.play();

        // iOS quirks :
        // -  myMedia.play({ numberOfLoops: 2 }) -> looping
        // -  myMedia.play({ playAudioWhenScreenIsLocked : false })
      },

      pause: function (source) {
        return source.pause();
      },

      release: function (source) {
        return source.release();
      },


      seekTo: function (source, milliseconds) {

        return source.seekTo(milliseconds);
      },

      setVolume: function (source, volume) {
        return source.setVolume(volume);
      },

      startRecord: function (source) {
        return source.startRecord();
      },

      stopRecord: function (source) {

        return source.stopRecord();
      },

      stop: function (source) {
        return source.stop();
      }
    };