Skip to content

Commit

Permalink
#35 Provide <audio> or <video> elements to MediaHandler - first cut
Browse files Browse the repository at this point in the history
 Usage:

  var session = new SIP.UA().invite('welcome@junctionnetworks.com', {
    media: {
      render: {
        remote: {
          audio: document.createElement('audio'),
          video: document.createElement('video')
        },
        local: {
          audio: document.createElement('audio'),
          video: document.createElement('video')
        }
      }
    }
  });
  • Loading branch information
joseph-onsip committed Jun 22, 2014
1 parent 3009069 commit 4096365
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 15 deletions.
20 changes: 20 additions & 0 deletions src/WebRTC/MediaHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ var MediaHandler = function(session, options) {

this.peerConnection.onaddstream = function(e) {
self.logger.log('stream added: '+ e.stream.id);
self.render();
};

this.peerConnection.onremovestream = function(e) {
Expand Down Expand Up @@ -169,6 +170,7 @@ MediaHandler.prototype = Object.create(SIP.MediaHandler.prototype, {
if (mediaHint.dataChannel === true) {
mediaHint.dataChannel = {};
}
this.mediaHint = mediaHint;

/*
* 1. acquire stream (skip if MediaStream passed in)
Expand Down Expand Up @@ -374,6 +376,24 @@ MediaHandler.prototype = Object.create(SIP.MediaHandler.prototype, {
pc.remoteStreams || [];
}},

render: {writable: true, value: function render (renderHint) {
renderHint = renderHint || this.mediaHint.render;
if (!renderHint) {
return false;
}
var streamGetters = {
local: 'getLocalStreams',
remote: 'getRemoteStreams'
};
Object.keys(streamGetters).forEach(function (loc) {
var streamGetter = streamGetters[loc];
var streams = this[streamGetter]();
if (streams.length) {
SIP.WebRTC.MediaStreamManager.render(streams[0], renderHint[loc]);
}
}.bind(this));
}},

// Internal functions
hasOffer: {writable: true, value: function hasOffer (where) {
var offerState = 'have-' + where + '-offer';
Expand Down
73 changes: 58 additions & 15 deletions src/WebRTC/MediaStreamManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ var MediaStreamManager = function MediaStreamManager (defaultMediaHint) {
'userMedia',
'userMediaFailed'
];
this.setMediaHint(defaultMediaHint);
this.mediaHint = defaultMediaHint || {
constraints: {audio: true, video: true}
};

this.initEvents(events);

Expand All @@ -35,6 +37,53 @@ MediaStreamManager.streamId = function (stream) {
})
.join('');
};

MediaStreamManager.render = function render (stream, elements) {
if (!elements) {
return false;
}

function attachAndPlay (element, stream) {
attachMediaStream(element, stream);
ensureMediaPlaying(element);
}

function attachMediaStream(element, stream) {
if (typeof element.src !== 'undefined') {
URL.revokeObjectURL(element.src);
element.src = URL.createObjectURL(stream);
} else if (typeof (element.srcObject || element.mozSrcObject) !== 'undefined') {
element.srcObject = element.mozSrcObject = stream;
} else {
return false;
}

return true;
}

function ensureMediaPlaying (mediaElement) {
var interval = 100;
mediaElement.ensurePlayingIntervalId = setInterval(function () {
if (mediaElement.paused) {
mediaElement.play();
}
else {
clearInterval(mediaElement.ensurePlayingIntervalId);
}
}, interval);
}

if (elements.video) {
if (elements.audio) {
elements.video.volume = 0;
}
attachAndPlay(elements.video, stream);
}
if (elements.audio) {
attachAndPlay(elements.audio, stream);
}
};

MediaStreamManager.prototype = Object.create(SIP.EventEmitter.prototype, {
'acquire': {value: function acquire (onSuccess, onFailure, mediaHint) {
mediaHint = Object.keys(mediaHint || {}).length ? mediaHint : this.mediaHint;
Expand All @@ -47,8 +96,13 @@ MediaStreamManager.prototype = Object.create(SIP.EventEmitter.prototype, {

if (mediaHint.stream) {
saveSuccess(mediaHint.stream, true);
} else if (mediaHint.constraints) {
this.emit('userMediaRequest', mediaHint.constraints);
} else {
// Fallback to audio/video enabled if no mediaHint can be found.
var constraints = mediaHint.constraints ||
(this.mediaHint && this.mediaHint.constraints) ||
{audio: true, video: true};

this.emit('userMediaRequest', constraints);

var emitThenCall = function (eventName, callback) {
var callbackArgs = Array.prototype.slice.call(arguments, 2);
Expand All @@ -60,14 +114,10 @@ MediaStreamManager.prototype = Object.create(SIP.EventEmitter.prototype, {
callback.apply(null, callbackArgs);
}.bind(this);

SIP.WebRTC.getUserMedia(mediaHint.constraints,
SIP.WebRTC.getUserMedia(constraints,
emitThenCall.bind(this, 'userMedia', saveSuccess),
emitThenCall.bind(this, 'userMediaFailed', onFailure)
);
} else {
var errorMessage = 'mediaHint specifies neither constraints nor stream: ';
errorMessage += JSON.stringify(mediaHint);
onFailure(new Error(errorMessage));
}
}},

Expand All @@ -78,13 +128,6 @@ MediaStreamManager.prototype = Object.create(SIP.EventEmitter.prototype, {
}
delete this.acquisitions[streamId];
}},

'setMediaHint': {value: function setMediaHint (mediaHint) {
// Assume audio/video constraints if no default mediaHint passed.
this.mediaHint = mediaHint || {
constraints: {audio: true, video: true}
};
}}
});

// Return since it will be assigned to a variable.
Expand Down

0 comments on commit 4096365

Please sign in to comment.