API Docs for:
Show:

File: src/internal/stream_collection.coffee

  1. {Deferred} = require('./promise')
  2. EventEmitter = require('events').EventEmitter
  3.  
  4. ###*
  5. # @module rtc.internal
  6. ###
  7. ###*
  8. # Helper handling the mapping of streams for RemotePeer
  9. # @class rtc.internal.StreamCollection
  10. #
  11. # @constructor
  12. ###
  13. class exports.StreamCollection extends EventEmitter
  14.  
  15. ###*
  16. # A new stream was added to the collection
  17. # @event steam_added
  18. # @param {String} name The user defined name of the stream
  19. # @param {Promise -> rtc.Stream} stream Promise to the stream
  20. ###
  21.  
  22. constructor: () ->
  23. ###*
  24. # Contains the promises which will resolve to the streams
  25. # @property {Object} streams
  26. ###
  27. @streams = {}
  28.  
  29. @_defers = {}
  30. @_waiting = {}
  31. @_pending = {}
  32.  
  33. @wait_d = new Deferred()
  34. @wait_p = @wait_d.promise
  35.  
  36.  
  37. ###*
  38. # Set stream description and generate promises
  39. # @method update
  40. # @param data {Object} An object mapping the stream ids to stream names
  41. ###
  42. update: (data) ->
  43. members = []
  44. @_waiting = {}
  45.  
  46. # remove old streams
  47.  
  48. for name, stream_p in @streams
  49. if not data[name]?
  50. # remove
  51.  
  52. delete @streams[name]
  53. @emit('stream_removed', name)
  54.  
  55. # close/fail
  56.  
  57. # TODO: this does not work anymore ...
  58. if stream_p.isFullfilled()
  59. stream_p.then (stream) ->
  60. stream.close()
  61. else if stream_p.isPending()
  62. stream_p.reject(new Error("Stream removed before being established"))
  63.  
  64. # update mappings
  65.  
  66. for name, id of data
  67. # does stream exist?
  68.  
  69. if not @streams[name]?
  70. # create stream promise
  71.  
  72. defer = new Deferred()
  73.  
  74. @streams[name] = defer.promise
  75. @_defers[name] = defer
  76.  
  77. @emit('stream_added', name, defer.promise)
  78.  
  79. # do we adjust stream initialization?
  80.  
  81. if @_defers[name]?
  82. if @_pending[id]?
  83. # got it!
  84.  
  85. stream = @_pending[id]
  86. delete @_pending[id]
  87.  
  88. @_defers[name].resolve(stream)
  89. delete @_defers[name]
  90.  
  91. else
  92. # add waiting mapping
  93.  
  94. @_waiting[id] = name
  95.  
  96. @wait_d.resolve()
  97.  
  98.  
  99. ###*
  100. # Add stream to the collection and resolve promises waiting for it
  101. # @method resolve
  102. # @param {rtc.Stream} stream
  103. ###
  104. resolve: (stream) ->
  105. id = stream.id()
  106.  
  107. # streams from Chrome to Firefox are coming in with id set to 'default' ...
  108. if id == 'default'
  109. if Object.keys(@streams).length == 1 and Object.keys(@_waiting).length == 1
  110. console.log("Working around incompatibility between Firefox and Chrome concerning stream identification")
  111. id = Object.keys(@_waiting)[0]
  112. else
  113. console.log("Unable to work around incompatibility between Firefox and Chrome concerning stream identification")
  114.  
  115. if @_waiting[id]?
  116. # stream is expected
  117.  
  118. name = @_waiting[id]
  119. delete @_waiting[id]
  120.  
  121. @_defers[name].resolve(stream)
  122. delete @_defers[name]
  123.  
  124. else
  125. # lets hope someone wants this later ...
  126.  
  127. @_pending[id] = stream
  128.  
  129.  
  130. ###*
  131. # Gets a promise for a stream with the given name. Might be rejected after `update()`
  132. #
  133. # @method get
  134. # @param {String} name
  135. # @return {Promise} The promise for the `rtc.Stream`
  136. ###
  137. get: (name) ->
  138. @wait_p.then () =>
  139. if @streams[name]?
  140. return @streams[name]
  141. else
  142. throw new Error("Stream not offered")
  143.  
  144.