正在显示
35 个修改的文件
包含
236 行增加
和
497 行删除
| @@ -153,9 +153,9 @@ constructor( | @@ -153,9 +153,9 @@ constructor( | ||
| 153 | sendRequest(request) | 153 | sendRequest(request) |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | - fun sendMuteTrack(trackSid: Track.Sid, muted: Boolean) { | 156 | + fun sendMuteTrack(trackSid: String, muted: Boolean) { |
| 157 | val muteRequest = LivekitRtc.MuteTrackRequest.newBuilder() | 157 | val muteRequest = LivekitRtc.MuteTrackRequest.newBuilder() |
| 158 | - .setSid(trackSid.sid) | 158 | + .setSid(trackSid) |
| 159 | .setMuted(muted) | 159 | .setMuted(muted) |
| 160 | .build() | 160 | .build() |
| 161 | 161 | ||
| @@ -166,9 +166,9 @@ constructor( | @@ -166,9 +166,9 @@ constructor( | ||
| 166 | sendRequest(request) | 166 | sendRequest(request) |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | - fun sendAddTrack(cid: Track.Cid, name: String, type: LivekitModels.TrackType) { | 169 | + fun sendAddTrack(cid: String, name: String, type: LivekitModels.TrackType) { |
| 170 | val addTrackRequest = LivekitRtc.AddTrackRequest.newBuilder() | 170 | val addTrackRequest = LivekitRtc.AddTrackRequest.newBuilder() |
| 171 | - .setCid(cid.cid) | 171 | + .setCid(cid) |
| 172 | .setName(name) | 172 | .setName(name) |
| 173 | .setType(type) | 173 | .setType(type) |
| 174 | .build() | 174 | .build() |
| @@ -45,7 +45,7 @@ constructor( | @@ -45,7 +45,7 @@ constructor( | ||
| 45 | } | 45 | } |
| 46 | } | 46 | } |
| 47 | val pendingCandidates = mutableListOf<IceCandidate>() | 47 | val pendingCandidates = mutableListOf<IceCandidate>() |
| 48 | - private val pendingTrackResolvers: MutableMap<Track.Cid, Continuation<LivekitModels.TrackInfo>> = | 48 | + private val pendingTrackResolvers: MutableMap<String, Continuation<LivekitModels.TrackInfo>> = |
| 49 | mutableMapOf() | 49 | mutableMapOf() |
| 50 | 50 | ||
| 51 | private val publisherObserver = PublisherTransportObserver(this) | 51 | private val publisherObserver = PublisherTransportObserver(this) |
| @@ -76,7 +76,7 @@ constructor( | @@ -76,7 +76,7 @@ constructor( | ||
| 76 | client.join(url, token) | 76 | client.join(url, token) |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | - suspend fun addTrack(cid: Track.Cid, name: String, kind: LivekitModels.TrackType): LivekitModels.TrackInfo { | 79 | + suspend fun addTrack(cid: String, name: String, kind: LivekitModels.TrackType): LivekitModels.TrackInfo { |
| 80 | if (pendingTrackResolvers[cid] != null) { | 80 | if (pendingTrackResolvers[cid] != null) { |
| 81 | throw TrackException.DuplicateTrackException("Track with same ID $cid has already been published!") | 81 | throw TrackException.DuplicateTrackException("Track with same ID $cid has already been published!") |
| 82 | } | 82 | } |
| @@ -87,7 +87,7 @@ constructor( | @@ -87,7 +87,7 @@ constructor( | ||
| 87 | } | 87 | } |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | - fun updateMuteStatus(sid: Track.Sid, muted: Boolean) { | 90 | + fun updateMuteStatus(sid: String, muted: Boolean) { |
| 91 | client.sendMuteTrack(sid, muted) | 91 | client.sendMuteTrack(sid, muted) |
| 92 | } | 92 | } |
| 93 | 93 | ||
| @@ -137,7 +137,7 @@ constructor( | @@ -137,7 +137,7 @@ constructor( | ||
| 137 | interface Listener { | 137 | interface Listener { |
| 138 | fun onJoin(response: LivekitRtc.JoinResponse) | 138 | fun onJoin(response: LivekitRtc.JoinResponse) |
| 139 | fun onAddTrack(track: MediaStreamTrack, streams: Array<out MediaStream>) | 139 | fun onAddTrack(track: MediaStreamTrack, streams: Array<out MediaStream>) |
| 140 | - fun onPublishLocalTrack(cid: Track.Cid, track: LivekitModels.TrackInfo) | 140 | + fun onPublishLocalTrack(cid: String, track: LivekitModels.TrackInfo) |
| 141 | fun onAddDataChannel(channel: DataChannel) | 141 | fun onAddDataChannel(channel: DataChannel) |
| 142 | fun onUpdateParticipants(updates: List<LivekitModels.ParticipantInfo>) | 142 | fun onUpdateParticipants(updates: List<LivekitModels.ParticipantInfo>) |
| 143 | fun onUpdateSpeakers(speakers: List<LivekitRtc.SpeakerInfo>) | 143 | fun onUpdateSpeakers(speakers: List<LivekitRtc.SpeakerInfo>) |
| @@ -253,7 +253,7 @@ constructor( | @@ -253,7 +253,7 @@ constructor( | ||
| 253 | Timber.e { "local track published with null cid?" } | 253 | Timber.e { "local track published with null cid?" } |
| 254 | return | 254 | return |
| 255 | } | 255 | } |
| 256 | - val cid = Track.Cid(signalCid) | 256 | + val cid = signalCid |
| 257 | 257 | ||
| 258 | val track = response.track | 258 | val track = response.track |
| 259 | if (track == null) { | 259 | if (track == null) { |
| @@ -9,7 +9,6 @@ import io.livekit.android.ConnectOptions | @@ -9,7 +9,6 @@ import io.livekit.android.ConnectOptions | ||
| 9 | import io.livekit.android.room.participant.LocalParticipant | 9 | import io.livekit.android.room.participant.LocalParticipant |
| 10 | import io.livekit.android.room.participant.Participant | 10 | import io.livekit.android.room.participant.Participant |
| 11 | import io.livekit.android.room.participant.RemoteParticipant | 11 | import io.livekit.android.room.participant.RemoteParticipant |
| 12 | -import io.livekit.android.room.track.Track | ||
| 13 | import io.livekit.android.room.util.unpackedTrackLabel | 12 | import io.livekit.android.room.util.unpackedTrackLabel |
| 14 | import livekit.LivekitModels | 13 | import livekit.LivekitModels |
| 15 | import livekit.LivekitRtc | 14 | import livekit.LivekitRtc |
| @@ -24,7 +23,7 @@ constructor( | @@ -24,7 +23,7 @@ constructor( | ||
| 24 | @Assisted private val connectOptions: ConnectOptions, | 23 | @Assisted private val connectOptions: ConnectOptions, |
| 25 | private val engine: RTCEngine, | 24 | private val engine: RTCEngine, |
| 26 | private val eglBase: EglBase, | 25 | private val eglBase: EglBase, |
| 27 | -) : RTCEngine.Listener, RemoteParticipant.Listener, LocalParticipant.Listener { | 26 | +) : RTCEngine.Listener, RemoteParticipant.Listener { |
| 28 | init { | 27 | init { |
| 29 | engine.listener = this | 28 | engine.listener = this |
| 30 | } | 29 | } |
| @@ -48,8 +47,8 @@ constructor( | @@ -48,8 +47,8 @@ constructor( | ||
| 48 | private set | 47 | private set |
| 49 | var localParticipant: LocalParticipant? = null | 48 | var localParticipant: LocalParticipant? = null |
| 50 | private set | 49 | private set |
| 51 | - private val mutableRemoteParticipants = mutableMapOf<Participant.Sid, RemoteParticipant>() | ||
| 52 | - val remoteParticipants: Map<Participant.Sid, RemoteParticipant> | 50 | + private val mutableRemoteParticipants = mutableMapOf<String, RemoteParticipant>() |
| 51 | + val remoteParticipants: Map<String, RemoteParticipant> | ||
| 53 | get() = mutableRemoteParticipants | 52 | get() = mutableRemoteParticipants |
| 54 | 53 | ||
| 55 | private val mutableActiveSpeakers = mutableListOf<Participant>() | 54 | private val mutableActiveSpeakers = mutableListOf<Participant>() |
| @@ -73,17 +72,17 @@ constructor( | @@ -73,17 +72,17 @@ constructor( | ||
| 73 | listener?.onDisconnect(this, null) | 72 | listener?.onDisconnect(this, null) |
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | - private fun handleParticipantDisconnect(sid: Participant.Sid, participant: RemoteParticipant) { | 75 | + private fun handleParticipantDisconnect(sid: String, participant: RemoteParticipant) { |
| 77 | val removedParticipant = mutableRemoteParticipants.remove(sid) ?: return | 76 | val removedParticipant = mutableRemoteParticipants.remove(sid) ?: return |
| 78 | removedParticipant.tracks.values.forEach { publication -> | 77 | removedParticipant.tracks.values.forEach { publication -> |
| 79 | - removedParticipant.unpublishTrack(publication.trackSid) | 78 | + removedParticipant.unpublishTrack(publication.sid) |
| 80 | } | 79 | } |
| 81 | 80 | ||
| 82 | listener?.onParticipantDisconnected(this, removedParticipant) | 81 | listener?.onParticipantDisconnected(this, removedParticipant) |
| 83 | } | 82 | } |
| 84 | 83 | ||
| 85 | private fun getOrCreateRemoteParticipant( | 84 | private fun getOrCreateRemoteParticipant( |
| 86 | - sid: Participant.Sid, | 85 | + sid: String, |
| 87 | info: LivekitModels.ParticipantInfo? = null | 86 | info: LivekitModels.ParticipantInfo? = null |
| 88 | ): RemoteParticipant { | 87 | ): RemoteParticipant { |
| 89 | var participant = remoteParticipants[sid] | 88 | var participant = remoteParticipants[sid] |
| @@ -103,10 +102,10 @@ constructor( | @@ -103,10 +102,10 @@ constructor( | ||
| 103 | 102 | ||
| 104 | private fun handleSpeakerUpdate(speakerInfos: List<LivekitRtc.SpeakerInfo>) { | 103 | private fun handleSpeakerUpdate(speakerInfos: List<LivekitRtc.SpeakerInfo>) { |
| 105 | val speakers = mutableListOf<Participant>() | 104 | val speakers = mutableListOf<Participant>() |
| 106 | - val seenSids = mutableSetOf<Participant.Sid>() | 105 | + val seenSids = mutableSetOf<String>() |
| 107 | val localParticipant = localParticipant | 106 | val localParticipant = localParticipant |
| 108 | speakerInfos.forEach { speakerInfo -> | 107 | speakerInfos.forEach { speakerInfo -> |
| 109 | - val speakerSid = Participant.Sid(speakerInfo.sid) | 108 | + val speakerSid = speakerInfo.sid!! |
| 110 | seenSids.add(speakerSid) | 109 | seenSids.add(speakerSid) |
| 111 | 110 | ||
| 112 | if (speakerSid == localParticipant?.sid) { | 111 | if (speakerSid == localParticipant?.sid) { |
| @@ -185,7 +184,7 @@ constructor( | @@ -185,7 +184,7 @@ constructor( | ||
| 185 | } | 184 | } |
| 186 | if (response.otherParticipantsList.isNotEmpty()) { | 185 | if (response.otherParticipantsList.isNotEmpty()) { |
| 187 | response.otherParticipantsList.forEach { | 186 | response.otherParticipantsList.forEach { |
| 188 | - getOrCreateRemoteParticipant(Participant.Sid(it.sid), it) | 187 | + getOrCreateRemoteParticipant(it.sid, it) |
| 189 | } | 188 | } |
| 190 | } | 189 | } |
| 191 | 190 | ||
| @@ -203,8 +202,8 @@ constructor( | @@ -203,8 +202,8 @@ constructor( | ||
| 203 | return | 202 | return |
| 204 | } | 203 | } |
| 205 | 204 | ||
| 206 | - val participantSid = Participant.Sid(streams.first().id) | ||
| 207 | - val trackSid = Track.Sid(track.id()) | 205 | + val participantSid = streams.first().id |
| 206 | + val trackSid = track.id() | ||
| 208 | val participant = getOrCreateRemoteParticipant(participantSid) | 207 | val participant = getOrCreateRemoteParticipant(participantSid) |
| 209 | participant.addSubscribedMediaTrack(track, trackSid) | 208 | participant.addSubscribedMediaTrack(track, trackSid) |
| 210 | } | 209 | } |
| @@ -222,7 +221,7 @@ constructor( | @@ -222,7 +221,7 @@ constructor( | ||
| 222 | /** | 221 | /** |
| 223 | * @suppress | 222 | * @suppress |
| 224 | */ | 223 | */ |
| 225 | - override fun onPublishLocalTrack(cid: Track.Cid, track: LivekitModels.TrackInfo) { | 224 | + override fun onPublishLocalTrack(cid: String, track: LivekitModels.TrackInfo) { |
| 226 | } | 225 | } |
| 227 | 226 | ||
| 228 | /** | 227 | /** |
| @@ -230,7 +229,7 @@ constructor( | @@ -230,7 +229,7 @@ constructor( | ||
| 230 | */ | 229 | */ |
| 231 | override fun onUpdateParticipants(updates: List<LivekitModels.ParticipantInfo>) { | 230 | override fun onUpdateParticipants(updates: List<LivekitModels.ParticipantInfo>) { |
| 232 | for (info in updates) { | 231 | for (info in updates) { |
| 233 | - val participantSid = Participant.Sid(info.sid) | 232 | + val participantSid = info.sid |
| 234 | 233 | ||
| 235 | if(localParticipant?.sid == participantSid) { | 234 | if(localParticipant?.sid == participantSid) { |
| 236 | localParticipant?.updateFromInfo(info) | 235 | localParticipant?.updateFromInfo(info) |
| @@ -8,28 +8,16 @@ import org.webrtc.DataChannel | @@ -8,28 +8,16 @@ import org.webrtc.DataChannel | ||
| 8 | import org.webrtc.RtpTransceiver | 8 | import org.webrtc.RtpTransceiver |
| 9 | import java.util.* | 9 | import java.util.* |
| 10 | 10 | ||
| 11 | -class LocalParticipant(sid: Sid, name: String? = null) : | ||
| 12 | - Participant(sid, name) { | ||
| 13 | - | ||
| 14 | - /** | ||
| 15 | - * @suppress | ||
| 16 | - */ | ||
| 17 | - constructor(info: LivekitModels.ParticipantInfo, engine: RTCEngine) : this( | ||
| 18 | - Sid(info.sid), | ||
| 19 | - info.identity | ||
| 20 | - ) { | ||
| 21 | - metadata = info.metadata | ||
| 22 | - this.engine = engine | 11 | +class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine: RTCEngine) : |
| 12 | + Participant(info.sid, info.identity) { | ||
| 13 | + | ||
| 14 | + init { | ||
| 15 | + updateFromInfo(info) | ||
| 23 | } | 16 | } |
| 24 | 17 | ||
| 25 | - val localAudioTrackPublications | ||
| 26 | - get() = audioTracks.values.toList() | ||
| 27 | - val localVideoTrackPublications | ||
| 28 | - get() = videoTracks.values.toList() | ||
| 29 | - val localDataTrackPublications | ||
| 30 | - get() = dataTracks.values.toList() | 18 | + val localTrackPublications |
| 19 | + get() = tracks.values.toList() | ||
| 31 | 20 | ||
| 32 | - private var engine: RTCEngine? = null | ||
| 33 | var listener: Listener? = null | 21 | var listener: Listener? = null |
| 34 | set(v) { | 22 | set(v) { |
| 35 | field = v | 23 | field = v |
| @@ -38,98 +26,77 @@ class LocalParticipant(sid: Sid, name: String? = null) : | @@ -38,98 +26,77 @@ class LocalParticipant(sid: Sid, name: String? = null) : | ||
| 38 | 26 | ||
| 39 | suspend fun publishAudioTrack( | 27 | suspend fun publishAudioTrack( |
| 40 | track: LocalAudioTrack, | 28 | track: LocalAudioTrack, |
| 41 | - options: LocalTrackPublicationOptions? = null | 29 | + publishListener: PublishListener? = null |
| 42 | ) { | 30 | ) { |
| 43 | - if (localAudioTrackPublications.any { it.track == track }) { | ||
| 44 | - listener?.onFailToPublishAudioTrack(TrackException.PublishException("Track has already been published")) | 31 | + if (localTrackPublications.any { it.track == track }) { |
| 32 | + publishListener?.onPublishFailure(TrackException.PublishException("Track has already been published")) | ||
| 45 | return | 33 | return |
| 46 | } | 34 | } |
| 47 | 35 | ||
| 48 | val cid = track.rtcTrack.id() | 36 | val cid = track.rtcTrack.id() |
| 49 | - val engine = this.engine ?: run { | ||
| 50 | - listener?.onFailToPublishAudioTrack(IllegalStateException("engine is null!")) | ||
| 51 | - return | ||
| 52 | - } | ||
| 53 | - | ||
| 54 | val trackInfo = | 37 | val trackInfo = |
| 55 | - engine.addTrack(cid = Track.Cid(cid), name = track.name, kind = LivekitModels.TrackType.AUDIO) | 38 | + engine.addTrack(cid = cid, name = track.name, kind = track.kind) |
| 56 | val transInit = RtpTransceiver.RtpTransceiverInit( | 39 | val transInit = RtpTransceiver.RtpTransceiverInit( |
| 57 | RtpTransceiver.RtpTransceiverDirection.SEND_ONLY, | 40 | RtpTransceiver.RtpTransceiverDirection.SEND_ONLY, |
| 58 | - listOf(this.sid.sid) | 41 | + listOf(this.sid) |
| 59 | ) | 42 | ) |
| 43 | + // TODO: sendEncodings to customize | ||
| 60 | val transceiver = | 44 | val transceiver = |
| 61 | engine.publisher.peerConnection.addTransceiver(track.rtcTrack, transInit) | 45 | engine.publisher.peerConnection.addTransceiver(track.rtcTrack, transInit) |
| 62 | 46 | ||
| 63 | if (transceiver == null) { | 47 | if (transceiver == null) { |
| 64 | - listener?.onFailToPublishAudioTrack(TrackException.PublishException("null sender returned from peer connection")) | 48 | + publishListener?.onPublishFailure(TrackException.PublishException("null sender returned from peer connection")) |
| 65 | return | 49 | return |
| 66 | } | 50 | } |
| 67 | 51 | ||
| 68 | - val publication = LocalAudioTrackPublication(trackInfo) | ||
| 69 | - val trackSid = Track.Sid(trackInfo.sid) | ||
| 70 | - track.sid = trackSid | ||
| 71 | - audioTracks[trackSid] = publication | ||
| 72 | - listener?.onPublishAudioTrack(track) | 52 | + val publication = TrackPublication(trackInfo, track) |
| 53 | + addTrackPublication(publication) | ||
| 54 | + publishListener?.onPublishSuccess(publication) | ||
| 73 | } | 55 | } |
| 74 | 56 | ||
| 75 | suspend fun publishVideoTrack( | 57 | suspend fun publishVideoTrack( |
| 76 | track: LocalVideoTrack, | 58 | track: LocalVideoTrack, |
| 77 | - options: LocalTrackPublicationOptions? = null | 59 | + publishListener: PublishListener? = null |
| 78 | ) { | 60 | ) { |
| 79 | - | ||
| 80 | - if (localVideoTrackPublications.any { it.track == track }) { | ||
| 81 | - listener?.onFailToPublishVideoTrack(TrackException.PublishException("Track has already been published")) | 61 | + if (localTrackPublications.any { it.track == track }) { |
| 62 | + publishListener?.onPublishFailure(TrackException.PublishException("Track has already been published")) | ||
| 82 | return | 63 | return |
| 83 | } | 64 | } |
| 84 | 65 | ||
| 85 | val cid = track.rtcTrack.id() | 66 | val cid = track.rtcTrack.id() |
| 86 | - val engine = this.engine ?: run { | ||
| 87 | - listener?.onFailToPublishVideoTrack(IllegalStateException("engine is null!")) | ||
| 88 | - return | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | val trackInfo = | 67 | val trackInfo = |
| 92 | - engine.addTrack(cid = Track.Cid(cid), name = track.name, kind = LivekitModels.TrackType.VIDEO) | 68 | + engine.addTrack(cid = cid, name = track.name, kind = LivekitModels.TrackType.VIDEO) |
| 93 | val transInit = RtpTransceiver.RtpTransceiverInit( | 69 | val transInit = RtpTransceiver.RtpTransceiverInit( |
| 94 | RtpTransceiver.RtpTransceiverDirection.SEND_ONLY, | 70 | RtpTransceiver.RtpTransceiverDirection.SEND_ONLY, |
| 95 | - listOf(this.sid.sid) | 71 | + listOf(this.sid) |
| 96 | ) | 72 | ) |
| 73 | + // TODO: video encodings & simulcast | ||
| 97 | val transceiver = | 74 | val transceiver = |
| 98 | engine.publisher.peerConnection.addTransceiver(track.rtcTrack, transInit) | 75 | engine.publisher.peerConnection.addTransceiver(track.rtcTrack, transInit) |
| 99 | 76 | ||
| 100 | if (transceiver == null) { | 77 | if (transceiver == null) { |
| 101 | - listener?.onFailToPublishVideoTrack(TrackException.PublishException("null sender returned from peer connection")) | 78 | + publishListener?.onPublishFailure(TrackException.PublishException("null sender returned from peer connection")) |
| 102 | return | 79 | return |
| 103 | } | 80 | } |
| 104 | 81 | ||
| 105 | - val publication = LocalVideoTrackPublication(trackInfo) | ||
| 106 | - val trackSid = Track.Sid(trackInfo.sid) | ||
| 107 | - track.sid = trackSid | ||
| 108 | - videoTracks[trackSid] = publication | ||
| 109 | - listener?.onPublishVideoTrack(track) | 82 | + val publication = TrackPublication(trackInfo, track) |
| 83 | + addTrackPublication(publication) | ||
| 84 | + publishListener?.onPublishSuccess(publication) | ||
| 110 | } | 85 | } |
| 111 | 86 | ||
| 112 | suspend fun publishDataTrack( | 87 | suspend fun publishDataTrack( |
| 113 | track: LocalDataTrack, | 88 | track: LocalDataTrack, |
| 114 | - options: LocalTrackPublicationOptions? = null | 89 | + publishListener: PublishListener? = null |
| 115 | ) { | 90 | ) { |
| 116 | - | ||
| 117 | - if (localDataTrackPublications.any { it.track == track }) { | ||
| 118 | - listener?.onFailToPublishDataTrack(TrackException.PublishException("Track has already been published")) | 91 | + if (localTrackPublications.any { it.track == track }) { |
| 92 | + publishListener?.onPublishFailure(TrackException.PublishException("Track has already been published")) | ||
| 119 | return | 93 | return |
| 120 | } | 94 | } |
| 121 | 95 | ||
| 122 | val cid = track.cid | 96 | val cid = track.cid |
| 123 | - val engine = this.engine ?: run { | ||
| 124 | - listener?.onFailToPublishDataTrack(IllegalStateException("engine is null!")) | ||
| 125 | - return | ||
| 126 | - } | ||
| 127 | - | ||
| 128 | val trackInfo = | 97 | val trackInfo = |
| 129 | - engine.addTrack(cid = cid, name = track.name, kind = LivekitModels.TrackType.DATA) | ||
| 130 | - val publication = LocalDataTrackPublication(trackInfo, track) | ||
| 131 | - val trackSid = Track.Sid(trackInfo.sid) | ||
| 132 | - track.sid = trackSid | 98 | + engine.addTrack(cid = cid, name = track.name, track.kind) |
| 99 | + val publication = TrackPublication(trackInfo, track) | ||
| 133 | 100 | ||
| 134 | val config = DataChannel.Init().apply { | 101 | val config = DataChannel.Init().apply { |
| 135 | ordered = track.options.ordered | 102 | ordered = track.options.ordered |
| @@ -138,76 +105,51 @@ class LocalParticipant(sid: Sid, name: String? = null) : | @@ -138,76 +105,51 @@ class LocalParticipant(sid: Sid, name: String? = null) : | ||
| 138 | } | 105 | } |
| 139 | 106 | ||
| 140 | val dataChannel = engine.publisher.peerConnection.createDataChannel(track.name, config) | 107 | val dataChannel = engine.publisher.peerConnection.createDataChannel(track.name, config) |
| 141 | - if (dataChannel != null) { | ||
| 142 | - track.rtcTrack = dataChannel | ||
| 143 | - track.updateConfig(config) | ||
| 144 | - dataTracks[trackSid] = publication | ||
| 145 | - listener?.onPublishDataTrack(track) | ||
| 146 | - } else { | ||
| 147 | - Timber.d { "error creating data channel with name: $name" } | ||
| 148 | - unpublishDataTrack(track) | ||
| 149 | - } | ||
| 150 | - } | ||
| 151 | - | ||
| 152 | - fun unpublishAudioTrack(track: LocalAudioTrack) { | ||
| 153 | - val sid = track.sid ?: run { | ||
| 154 | - Timber.d { "this track was never published." } | 108 | + if (dataChannel == null) { |
| 109 | + publishListener?.onPublishFailure(TrackException.PublishException("could not create data channel")) | ||
| 155 | return | 110 | return |
| 156 | } | 111 | } |
| 157 | - unpublishMediaTrack(track, sid, audioTracks) | ||
| 158 | - } | 112 | + track.dataChannel = dataChannel |
| 113 | + track.updateConfig(config) | ||
| 114 | + addTrackPublication(publication) | ||
| 159 | 115 | ||
| 160 | - fun unpublishVideoTrack(track: LocalVideoTrack) { | ||
| 161 | - val sid = track.sid ?: run { | ||
| 162 | - Timber.d { "this track was never published." } | ||
| 163 | - return | ||
| 164 | - } | ||
| 165 | - unpublishMediaTrack(track, sid, audioTracks) | 116 | + publishListener?.onPublishSuccess(publication) |
| 166 | } | 117 | } |
| 167 | 118 | ||
| 168 | - fun unpublishDataTrack(track: LocalDataTrack) { | ||
| 169 | - val sid = track.sid ?: run { | 119 | + fun unpublishTrack(track: Track) { |
| 120 | + val publication = localTrackPublications.firstOrNull { it.track == track } | ||
| 121 | + if (publication === null) { | ||
| 170 | Timber.d { "this track was never published." } | 122 | Timber.d { "this track was never published." } |
| 171 | return | 123 | return |
| 172 | } | 124 | } |
| 173 | - | ||
| 174 | - val publication = dataTracks.remove(sid) as? LocalDataTrackPublication | ||
| 175 | - if (publication == null) { | ||
| 176 | - Timber.d { "track was not published with sid: $sid" } | ||
| 177 | - return | 125 | + track.stop() |
| 126 | + if (track is MediaTrack) { | ||
| 127 | + unpublishMediaTrack(track, sid) | ||
| 128 | + } | ||
| 129 | + val sid = publication.sid | ||
| 130 | + tracks.remove(sid) | ||
| 131 | + when (publication.kind) { | ||
| 132 | + LivekitModels.TrackType.AUDIO -> audioTracks.remove(sid) | ||
| 133 | + LivekitModels.TrackType.VIDEO -> videoTracks.remove(sid) | ||
| 134 | + LivekitModels.TrackType.DATA -> dataTracks.remove(sid) | ||
| 178 | } | 135 | } |
| 179 | - publication.dataTrack?.rtcTrack?.dispose() | ||
| 180 | } | 136 | } |
| 181 | 137 | ||
| 182 | private fun <T> unpublishMediaTrack( | 138 | private fun <T> unpublishMediaTrack( |
| 183 | track: T, | 139 | track: T, |
| 184 | - sid: Track.Sid, | ||
| 185 | - publications: MutableMap<Track.Sid, TrackPublication> | ||
| 186 | - ) where T : Track, T : MediaTrack { | ||
| 187 | - val removed = publications.remove(sid) | ||
| 188 | - if (removed != null) { | ||
| 189 | - Timber.d { "track was not published with sid: $sid" } | ||
| 190 | - return | ||
| 191 | - } | ||
| 192 | - | ||
| 193 | - track.mediaTrack.setEnabled(false) | 140 | + sid: String |
| 141 | + ) where T : MediaTrack { | ||
| 194 | val senders = engine?.publisher?.peerConnection?.senders ?: return | 142 | val senders = engine?.publisher?.peerConnection?.senders ?: return |
| 195 | for (sender in senders) { | 143 | for (sender in senders) { |
| 196 | val t = sender.track() ?: continue | 144 | val t = sender.track() ?: continue |
| 197 | - if (t == track.mediaTrack) { | 145 | + if (t == track.rtcTrack) { |
| 198 | engine?.publisher?.peerConnection?.removeTrack(sender) | 146 | engine?.publisher?.peerConnection?.removeTrack(sender) |
| 199 | } | 147 | } |
| 200 | } | 148 | } |
| 201 | } | 149 | } |
| 202 | 150 | ||
| 203 | - interface Listener : Participant.Listener { | ||
| 204 | - // TODO: can we move these to exceptions? instead of callbacks | ||
| 205 | - fun onPublishAudioTrack(track: LocalAudioTrack) {} | ||
| 206 | - fun onFailToPublishAudioTrack(exception: Exception) {} | ||
| 207 | - fun onPublishVideoTrack(track: LocalVideoTrack) {} | ||
| 208 | - fun onFailToPublishVideoTrack(exception: Exception) {} | ||
| 209 | - fun onPublishDataTrack(track: LocalDataTrack) {} | ||
| 210 | - fun onFailToPublishDataTrack(exception: Exception) {} | ||
| 211 | - //fun onNetworkQualityLevelChange | 151 | + interface PublishListener { |
| 152 | + fun onPublishSuccess(publication: TrackPublication) {} | ||
| 153 | + fun onPublishFailure(exception: Exception) {} | ||
| 212 | } | 154 | } |
| 213 | } | 155 | } |
| @@ -3,12 +3,10 @@ package io.livekit.android.room.participant | @@ -3,12 +3,10 @@ package io.livekit.android.room.participant | ||
| 3 | import io.livekit.android.room.track.* | 3 | import io.livekit.android.room.track.* |
| 4 | import livekit.LivekitModels | 4 | import livekit.LivekitModels |
| 5 | 5 | ||
| 6 | -open class Participant(var sid: Sid, name: String? = null) { | ||
| 7 | - inline class Sid(val sid: String) | ||
| 8 | - | 6 | +open class Participant(var sid: String, identity: String? = null) { |
| 9 | var participantInfo: LivekitModels.ParticipantInfo? = null | 7 | var participantInfo: LivekitModels.ParticipantInfo? = null |
| 10 | private set | 8 | private set |
| 11 | - var name: String? = name | 9 | + var identity: String? = identity |
| 12 | internal set | 10 | internal set |
| 13 | var audioLevel: Float = 0f | 11 | var audioLevel: Float = 0f |
| 14 | internal set | 12 | internal set |
| @@ -17,23 +15,23 @@ open class Participant(var sid: Sid, name: String? = null) { | @@ -17,23 +15,23 @@ open class Participant(var sid: Sid, name: String? = null) { | ||
| 17 | val hasInfo | 15 | val hasInfo |
| 18 | get() = participantInfo != null | 16 | get() = participantInfo != null |
| 19 | 17 | ||
| 20 | - var tracks = mutableMapOf<Track.Sid, TrackPublication>() | ||
| 21 | - var audioTracks = mutableMapOf<Track.Sid, TrackPublication>() | 18 | + var tracks = mutableMapOf<String, TrackPublication>() |
| 19 | + var audioTracks = mutableMapOf<String, TrackPublication>() | ||
| 22 | private set | 20 | private set |
| 23 | - var videoTracks = mutableMapOf<Track.Sid, TrackPublication>() | 21 | + var videoTracks = mutableMapOf<String, TrackPublication>() |
| 24 | private set | 22 | private set |
| 25 | - var dataTracks = mutableMapOf<Track.Sid, TrackPublication>() | 23 | + var dataTracks = mutableMapOf<String, TrackPublication>() |
| 26 | private set | 24 | private set |
| 27 | 25 | ||
| 28 | /** | 26 | /** |
| 29 | * @suppress | 27 | * @suppress |
| 30 | */ | 28 | */ |
| 31 | - fun addTrack(publication: TrackPublication) { | ||
| 32 | - tracks[publication.trackSid] = publication | ||
| 33 | - when (publication) { | ||
| 34 | - is RemoteAudioTrackPublication -> audioTracks[publication.trackSid] = publication | ||
| 35 | - is RemoteVideoTrackPublication -> videoTracks[publication.trackSid] = publication | ||
| 36 | - is RemoteDataTrackPublication -> dataTracks[publication.trackSid] = publication | 29 | + fun addTrackPublication(publication: TrackPublication) { |
| 30 | + tracks[publication.sid] = publication | ||
| 31 | + when (publication.kind) { | ||
| 32 | + LivekitModels.TrackType.AUDIO -> audioTracks[publication.sid] = publication | ||
| 33 | + LivekitModels.TrackType.VIDEO -> videoTracks[publication.sid] = publication | ||
| 34 | + LivekitModels.TrackType.DATA -> dataTracks[publication.sid] = publication | ||
| 37 | } | 35 | } |
| 38 | } | 36 | } |
| 39 | 37 | ||
| @@ -41,8 +39,8 @@ open class Participant(var sid: Sid, name: String? = null) { | @@ -41,8 +39,8 @@ open class Participant(var sid: Sid, name: String? = null) { | ||
| 41 | * @suppress | 39 | * @suppress |
| 42 | */ | 40 | */ |
| 43 | open fun updateFromInfo(info: LivekitModels.ParticipantInfo) { | 41 | open fun updateFromInfo(info: LivekitModels.ParticipantInfo) { |
| 44 | - sid = Sid(info.sid) | ||
| 45 | - name = info.identity | 42 | + sid = info.sid |
| 43 | + identity = info.identity | ||
| 46 | participantInfo = info | 44 | participantInfo = info |
| 47 | 45 | ||
| 48 | val prevMetadata = metadata | 46 | val prevMetadata = metadata |
| @@ -14,22 +14,15 @@ import org.webrtc.VideoTrack | @@ -14,22 +14,15 @@ import org.webrtc.VideoTrack | ||
| 14 | import java.nio.ByteBuffer | 14 | import java.nio.ByteBuffer |
| 15 | 15 | ||
| 16 | class RemoteParticipant( | 16 | class RemoteParticipant( |
| 17 | - sid: Sid, name: String? = null | 17 | + sid: String, name: String? = null |
| 18 | ) : Participant(sid, name), RemoteDataTrack.Listener { | 18 | ) : Participant(sid, name), RemoteDataTrack.Listener { |
| 19 | /** | 19 | /** |
| 20 | * @suppress | 20 | * @suppress |
| 21 | */ | 21 | */ |
| 22 | - constructor(info: LivekitModels.ParticipantInfo) : this(Sid(info.sid), info.identity) { | 22 | + constructor(info: LivekitModels.ParticipantInfo) : this(info.sid, info.identity) { |
| 23 | updateFromInfo(info) | 23 | updateFromInfo(info) |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | - val remoteAudioTracks | ||
| 27 | - get() = audioTracks.values.toList() | ||
| 28 | - val remoteVideoTracks | ||
| 29 | - get() = videoTracks.values.toList() | ||
| 30 | - val remoteDataTracks | ||
| 31 | - get() = dataTracks.values.toList() | ||
| 32 | - | ||
| 33 | var listener: Listener? = null | 26 | var listener: Listener? = null |
| 34 | set(v) { | 27 | set(v) { |
| 35 | field = v | 28 | field = v |
| @@ -38,8 +31,8 @@ class RemoteParticipant( | @@ -38,8 +31,8 @@ class RemoteParticipant( | ||
| 38 | 31 | ||
| 39 | private val coroutineScope = CloseableCoroutineScope(SupervisorJob()) | 32 | private val coroutineScope = CloseableCoroutineScope(SupervisorJob()) |
| 40 | 33 | ||
| 41 | - fun getTrackPublication(sid: Track.Sid): RemoteTrackPublication? = | ||
| 42 | - tracks[sid] as? RemoteTrackPublication | 34 | + fun getTrackPublication(sid: String): TrackPublication? = |
| 35 | + tracks[sid] | ||
| 43 | 36 | ||
| 44 | /** | 37 | /** |
| 45 | * @suppress | 38 | * @suppress |
| @@ -48,24 +41,18 @@ class RemoteParticipant( | @@ -48,24 +41,18 @@ class RemoteParticipant( | ||
| 48 | val hadInfo = hasInfo | 41 | val hadInfo = hasInfo |
| 49 | super.updateFromInfo(info) | 42 | super.updateFromInfo(info) |
| 50 | 43 | ||
| 51 | - val validTrackPublication = mutableMapOf<Track.Sid, RemoteTrackPublication>() | ||
| 52 | - val newTrackPublications = mutableMapOf<Track.Sid, RemoteTrackPublication>() | 44 | + val validTrackPublication = mutableMapOf<String, TrackPublication>() |
| 45 | + val newTrackPublications = mutableMapOf<String, TrackPublication>() | ||
| 53 | 46 | ||
| 54 | for (trackInfo in info.tracksList) { | 47 | for (trackInfo in info.tracksList) { |
| 55 | - val trackSid = Track.Sid(trackInfo.sid) | 48 | + val trackSid = trackInfo.sid |
| 56 | var publication = getTrackPublication(trackSid) | 49 | var publication = getTrackPublication(trackSid) |
| 57 | 50 | ||
| 58 | if (publication == null) { | 51 | if (publication == null) { |
| 59 | - publication = when (trackInfo.type) { | ||
| 60 | - LivekitModels.TrackType.AUDIO -> RemoteAudioTrackPublication(trackInfo) | ||
| 61 | - LivekitModels.TrackType.VIDEO -> RemoteVideoTrackPublication(trackInfo) | ||
| 62 | - LivekitModels.TrackType.DATA -> RemoteDataTrackPublication(trackInfo) | ||
| 63 | - LivekitModels.TrackType.UNRECOGNIZED -> throw TrackException.InvalidTrackTypeException() | ||
| 64 | - null -> throw NullPointerException("trackInfo.type is null") | ||
| 65 | - } | 52 | + publication = TrackPublication(trackInfo) |
| 66 | 53 | ||
| 67 | newTrackPublications[trackSid] = publication | 54 | newTrackPublications[trackSid] = publication |
| 68 | - addTrack(publication) | 55 | + addTrackPublication(publication) |
| 69 | } else { | 56 | } else { |
| 70 | publication.updateFromInfo(trackInfo) | 57 | publication.updateFromInfo(trackInfo) |
| 71 | } | 58 | } |
| @@ -75,25 +62,25 @@ class RemoteParticipant( | @@ -75,25 +62,25 @@ class RemoteParticipant( | ||
| 75 | 62 | ||
| 76 | if (hadInfo) { | 63 | if (hadInfo) { |
| 77 | for (publication in newTrackPublications.values) { | 64 | for (publication in newTrackPublications.values) { |
| 78 | - sendTrackPublishedEvent(publication) | 65 | + listener?.onPublish(publication, this) |
| 79 | } | 66 | } |
| 80 | } | 67 | } |
| 81 | 68 | ||
| 82 | val invalidKeys = tracks.keys - validTrackPublication.keys | 69 | val invalidKeys = tracks.keys - validTrackPublication.keys |
| 83 | for (invalidKey in invalidKeys) { | 70 | for (invalidKey in invalidKeys) { |
| 84 | val publication = tracks[invalidKey] ?: continue | 71 | val publication = tracks[invalidKey] ?: continue |
| 85 | - unpublishTrack(publication.trackSid, true) | 72 | + unpublishTrack(publication.sid, true) |
| 86 | } | 73 | } |
| 87 | } | 74 | } |
| 88 | 75 | ||
| 89 | /** | 76 | /** |
| 90 | * @suppress | 77 | * @suppress |
| 91 | */ | 78 | */ |
| 92 | - fun addSubscribedMediaTrack(rtcTrack: MediaStreamTrack, sid: Track.Sid, triesLeft: Int = 20) { | 79 | + fun addSubscribedMediaTrack(mediaTrack: MediaStreamTrack, sid: String, triesLeft: Int = 20) { |
| 93 | val publication = getTrackPublication(sid) | 80 | val publication = getTrackPublication(sid) |
| 94 | - val track: Track = when (val kind = rtcTrack.kind()) { | ||
| 95 | - KIND_AUDIO -> RemoteAudioTrack(sid = sid, rtcTrack = rtcTrack as AudioTrack, name = "") | ||
| 96 | - KIND_VIDEO -> RemoteVideoTrack(sid = sid, rtcTrack = rtcTrack as VideoTrack, name = "") | 81 | + val track: Track = when (val kind = mediaTrack.kind()) { |
| 82 | + KIND_AUDIO -> RemoteAudioTrack(sid = sid, mediaTrack = mediaTrack as AudioTrack, name = "") | ||
| 83 | + KIND_VIDEO -> RemoteVideoTrack(sid = sid, mediaTrack = mediaTrack as VideoTrack, name = "") | ||
| 97 | else -> throw TrackException.InvalidTrackTypeException("invalid track type: $kind") | 84 | else -> throw TrackException.InvalidTrackTypeException("invalid track type: $kind") |
| 98 | } | 85 | } |
| 99 | 86 | ||
| @@ -102,27 +89,12 @@ class RemoteParticipant( | @@ -102,27 +89,12 @@ class RemoteParticipant( | ||
| 102 | val message = "Could not find published track with sid: $sid" | 89 | val message = "Could not find published track with sid: $sid" |
| 103 | val exception = TrackException.InvalidTrackStateException(message) | 90 | val exception = TrackException.InvalidTrackStateException(message) |
| 104 | Timber.e { "remote participant ${this.sid} --- $message" } | 91 | Timber.e { "remote participant ${this.sid} --- $message" } |
| 105 | - when (rtcTrack.kind()) { | ||
| 106 | - KIND_AUDIO -> { | ||
| 107 | - listener?.onFailToSubscribe( | ||
| 108 | - audioTrack = track as RemoteAudioTrack, | ||
| 109 | - exception = exception, | ||
| 110 | - participant = this | ||
| 111 | - ) | ||
| 112 | - } | ||
| 113 | - | ||
| 114 | - KIND_VIDEO -> { | ||
| 115 | - listener?.onFailToSubscribe( | ||
| 116 | - videoTrack = track as RemoteVideoTrack, | ||
| 117 | - exception = exception, | ||
| 118 | - participant = this | ||
| 119 | - ) | ||
| 120 | - } | ||
| 121 | - } | 92 | + |
| 93 | + listener?.onFailToSubscribe(sid, exception, this) | ||
| 122 | } else { | 94 | } else { |
| 123 | coroutineScope.launch { | 95 | coroutineScope.launch { |
| 124 | delay(150) | 96 | delay(150) |
| 125 | - addSubscribedMediaTrack(rtcTrack, sid, triesLeft - 1) | 97 | + addSubscribedMediaTrack(mediaTrack, sid, triesLeft - 1) |
| 126 | } | 98 | } |
| 127 | } | 99 | } |
| 128 | return | 100 | return |
| @@ -130,103 +102,70 @@ class RemoteParticipant( | @@ -130,103 +102,70 @@ class RemoteParticipant( | ||
| 130 | 102 | ||
| 131 | val remoteTrack = track as RemoteTrack | 103 | val remoteTrack = track as RemoteTrack |
| 132 | publication.track = track | 104 | publication.track = track |
| 133 | - track.name = publication.trackName | ||
| 134 | - remoteTrack.sid = publication.trackSid | 105 | + track.name = publication.name |
| 106 | + remoteTrack.sid = publication.sid | ||
| 135 | 107 | ||
| 136 | - when (publication) { | ||
| 137 | - is RemoteAudioTrackPublication -> listener?.onSubscribe(publication, this) | ||
| 138 | - is RemoteVideoTrackPublication -> listener?.onSubscribe(publication, this) | ||
| 139 | - else -> throw TrackException.InvalidTrackTypeException() | ||
| 140 | - } | 108 | + // TODO: how does mediatrack send ended event? |
| 109 | + | ||
| 110 | + listener?.onSubscribe(track, publication, this) | ||
| 141 | } | 111 | } |
| 142 | 112 | ||
| 143 | /** | 113 | /** |
| 144 | * @suppress | 114 | * @suppress |
| 145 | */ | 115 | */ |
| 146 | - fun addSubscribedDataTrack(rtcTrack: DataChannel, sid: Track.Sid, name: String) { | ||
| 147 | - val track = RemoteDataTrack(sid, name, rtcTrack) | ||
| 148 | - var publication = getTrackPublication(sid) as? RemoteDataTrackPublication | 116 | + fun addSubscribedDataTrack(dataChannel: DataChannel, sid: String, name: String) { |
| 117 | + val track = DataTrack(name, dataChannel) | ||
| 118 | + var publication = getTrackPublication(sid) | ||
| 149 | 119 | ||
| 150 | if (publication != null) { | 120 | if (publication != null) { |
| 151 | publication.track = track | 121 | publication.track = track |
| 152 | } else { | 122 | } else { |
| 153 | val trackInfo = LivekitModels.TrackInfo.newBuilder() | 123 | val trackInfo = LivekitModels.TrackInfo.newBuilder() |
| 154 | - .setSid(sid.sid) | 124 | + .setSid(sid) |
| 155 | .setName(name) | 125 | .setName(name) |
| 156 | .setType(LivekitModels.TrackType.DATA) | 126 | .setType(LivekitModels.TrackType.DATA) |
| 157 | .build() | 127 | .build() |
| 158 | - publication = RemoteDataTrackPublication(info = trackInfo, track = track) | ||
| 159 | - addTrack(publication) | 128 | + publication = TrackPublication(info = trackInfo, track = track) |
| 129 | + addTrackPublication(publication) | ||
| 160 | if (hasInfo) { | 130 | if (hasInfo) { |
| 161 | - sendTrackPublishedEvent(publication) | 131 | + listener?.onPublish(publication, this) |
| 162 | } | 132 | } |
| 163 | } | 133 | } |
| 164 | 134 | ||
| 165 | - | ||
| 166 | - rtcTrack.registerObserver(object : DataChannel.Observer { | 135 | + dataChannel.registerObserver(object : DataChannel.Observer { |
| 167 | override fun onBufferedAmountChange(previousAmount: Long) {} | 136 | override fun onBufferedAmountChange(previousAmount: Long) {} |
| 168 | 137 | ||
| 169 | override fun onStateChange() { | 138 | override fun onStateChange() { |
| 170 | - val newState = rtcTrack.state() | 139 | + val newState = dataChannel.state() |
| 171 | if (newState == DataChannel.State.CLOSED) { | 140 | if (newState == DataChannel.State.CLOSED) { |
| 172 | - listener?.onUnsubscribe(publication, this@RemoteParticipant) | 141 | + publication.track = null |
| 142 | + listener?.onUnsubscribe(track, publication, this@RemoteParticipant) | ||
| 173 | } | 143 | } |
| 174 | } | 144 | } |
| 175 | 145 | ||
| 176 | override fun onMessage(buffer: DataChannel.Buffer) { | 146 | override fun onMessage(buffer: DataChannel.Buffer) { |
| 177 | - listener?.onReceive(buffer.data, publication, this@RemoteParticipant) | 147 | + listener?.onReceive(buffer.data, track, this@RemoteParticipant) |
| 178 | } | 148 | } |
| 179 | }) | 149 | }) |
| 180 | - listener?.onSubscribe(dataTrack = publication, participant = this) | 150 | + listener?.onSubscribe(track, publication, participant = this) |
| 181 | } | 151 | } |
| 182 | 152 | ||
| 183 | - fun unpublishTrack(trackSid: Track.Sid, sendUnpublish: Boolean = false) { | 153 | + fun unpublishTrack(trackSid: String, sendUnpublish: Boolean = false) { |
| 184 | val publication = tracks.remove(trackSid) ?: return | 154 | val publication = tracks.remove(trackSid) ?: return |
| 185 | - | ||
| 186 | - when (publication) { | ||
| 187 | - is RemoteAudioTrackPublication -> audioTracks.remove(trackSid) | ||
| 188 | - is RemoteVideoTrackPublication -> videoTracks.remove(trackSid) | ||
| 189 | - is RemoteDataTrackPublication -> { | ||
| 190 | - dataTracks.remove(trackSid) | ||
| 191 | - publication.dataTrack?.rtcTrack?.unregisterObserver() | ||
| 192 | - } | 155 | + when (publication.kind) { |
| 156 | + LivekitModels.TrackType.AUDIO -> audioTracks.remove(trackSid) | ||
| 157 | + LivekitModels.TrackType.VIDEO -> videoTracks.remove(trackSid) | ||
| 158 | + LivekitModels.TrackType.DATA -> dataTracks.remove(trackSid) | ||
| 193 | else -> throw TrackException.InvalidTrackTypeException() | 159 | else -> throw TrackException.InvalidTrackTypeException() |
| 194 | } | 160 | } |
| 195 | 161 | ||
| 196 | - if (publication.track != null) { | ||
| 197 | - // TODO: need to stop track? | ||
| 198 | - publication.track | ||
| 199 | - sendTrackUnsubscribedEvent(publication) | 162 | + val track = publication.track |
| 163 | + if (track != null) { | ||
| 164 | + track.stop() | ||
| 165 | + listener?.onUnsubscribe(track, publication, this) | ||
| 200 | } | 166 | } |
| 201 | if (sendUnpublish) { | 167 | if (sendUnpublish) { |
| 202 | - sendTrackUnpublishedEvent(publication) | ||
| 203 | - } | ||
| 204 | - } | ||
| 205 | - | ||
| 206 | - private fun sendTrackUnsubscribedEvent(publication: TrackPublication) { | ||
| 207 | - when (publication) { | ||
| 208 | - is RemoteAudioTrackPublication -> listener?.onUnsubscribe(publication, this) | ||
| 209 | - is RemoteVideoTrackPublication -> listener?.onUnsubscribe(publication, this) | ||
| 210 | - is RemoteDataTrackPublication -> listener?.onUnsubscribe(publication, this) | ||
| 211 | - else -> throw TrackException.InvalidTrackTypeException() | ||
| 212 | - } | ||
| 213 | - } | ||
| 214 | - | ||
| 215 | - private fun sendTrackUnpublishedEvent(publication: TrackPublication) { | ||
| 216 | - when (publication) { | ||
| 217 | - is RemoteAudioTrackPublication -> listener?.onUnpublish(publication, this) | ||
| 218 | - is RemoteVideoTrackPublication -> listener?.onUnpublish(publication, this) | ||
| 219 | - is RemoteDataTrackPublication -> listener?.onUnpublish(publication, this) | ||
| 220 | - else -> throw TrackException.InvalidTrackTypeException() | ||
| 221 | - } | ||
| 222 | - } | ||
| 223 | - | ||
| 224 | - private fun sendTrackPublishedEvent(publication: RemoteTrackPublication) { | ||
| 225 | - when (publication) { | ||
| 226 | - is RemoteAudioTrackPublication -> listener?.onPublish(publication, this) | ||
| 227 | - is RemoteVideoTrackPublication -> listener?.onPublish(publication, this) | ||
| 228 | - is RemoteDataTrackPublication -> listener?.onPublish(publication, this) | ||
| 229 | - else -> throw TrackException.InvalidTrackTypeException() | 168 | + listener?.onUnpublish(publication, this) |
| 230 | } | 169 | } |
| 231 | } | 170 | } |
| 232 | 171 | ||
| @@ -244,68 +183,36 @@ class RemoteParticipant( | @@ -244,68 +183,36 @@ class RemoteParticipant( | ||
| 244 | } | 183 | } |
| 245 | 184 | ||
| 246 | interface Listener: Participant.Listener { | 185 | interface Listener: Participant.Listener { |
| 247 | - fun onPublish(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant) {} | ||
| 248 | - fun onUnpublish(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant) {} | ||
| 249 | - fun onPublish(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant) {} | ||
| 250 | - fun onUnpublish(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant) {} | ||
| 251 | - fun onPublish(dataTrack: RemoteDataTrackPublication, participant: RemoteParticipant) {} | ||
| 252 | - fun onUnpublish(dataTrack: RemoteDataTrackPublication, participant: RemoteParticipant) {} | ||
| 253 | - | ||
| 254 | - fun onEnable(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant) {} | ||
| 255 | - fun onDisable(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant) {} | ||
| 256 | - fun onEnable(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant) {} | ||
| 257 | - fun onDisable(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant) {} | ||
| 258 | - | ||
| 259 | - fun onSubscribe(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant) {} | ||
| 260 | - fun onFailToSubscribe( | ||
| 261 | - audioTrack: RemoteAudioTrack, | ||
| 262 | - exception: Exception, | ||
| 263 | - participant: RemoteParticipant | ||
| 264 | - ) { | ||
| 265 | - } | 186 | + fun onPublish(publication: TrackPublication, participant: RemoteParticipant) {} |
| 187 | + fun onUnpublish(publication: TrackPublication, participant: RemoteParticipant) {} | ||
| 266 | 188 | ||
| 267 | - fun onUnsubscribe( | ||
| 268 | - audioTrack: RemoteAudioTrackPublication, | ||
| 269 | - participant: RemoteParticipant | ||
| 270 | - ) { | ||
| 271 | - } | 189 | + fun onEnable(publication: TrackPublication, participant: RemoteParticipant) {} |
| 190 | + fun onDisable(publication: TrackPublication, participant: RemoteParticipant) {} | ||
| 272 | 191 | ||
| 273 | - fun onSubscribe(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant) {} | 192 | + fun onSubscribe(track: Track, publication: TrackPublication, participant: RemoteParticipant) {} |
| 274 | fun onFailToSubscribe( | 193 | fun onFailToSubscribe( |
| 275 | - videoTrack: RemoteVideoTrack, | 194 | + sid: String, |
| 276 | exception: Exception, | 195 | exception: Exception, |
| 277 | participant: RemoteParticipant | 196 | participant: RemoteParticipant |
| 278 | ) { | 197 | ) { |
| 279 | } | 198 | } |
| 280 | 199 | ||
| 281 | fun onUnsubscribe( | 200 | fun onUnsubscribe( |
| 282 | - videoTrack: RemoteVideoTrackPublication, | ||
| 283 | - participant: RemoteParticipant | ||
| 284 | - ) { | ||
| 285 | - } | ||
| 286 | - | ||
| 287 | - fun onSubscribe(dataTrack: RemoteDataTrackPublication, participant: RemoteParticipant) {} | ||
| 288 | - fun onFailToSubscribe( | ||
| 289 | - dataTrack: RemoteDataTrackPublication, | ||
| 290 | - exception: Exception, | 201 | + track: Track, |
| 202 | + publications: TrackPublication, | ||
| 291 | participant: RemoteParticipant | 203 | participant: RemoteParticipant |
| 292 | ) { | 204 | ) { |
| 293 | } | 205 | } |
| 294 | 206 | ||
| 295 | - fun onUnsubscribe(dataTrack: RemoteDataTrackPublication, participant: RemoteParticipant) {} | ||
| 296 | fun onReceive( | 207 | fun onReceive( |
| 297 | data: ByteBuffer, | 208 | data: ByteBuffer, |
| 298 | - dataTrack: RemoteDataTrackPublication, | 209 | + dataTrack: DataTrack, |
| 299 | participant: RemoteParticipant | 210 | participant: RemoteParticipant |
| 300 | ) { | 211 | ) { |
| 301 | } | 212 | } |
| 302 | 213 | ||
| 303 | - //fun networkQualityDidChange(networkQualityLevel: NetworkQualityLevel, participant: remoteParticipant) | ||
| 304 | fun switchedOffVideo(track: RemoteVideoTrack, participant: RemoteParticipant) {} | 214 | fun switchedOffVideo(track: RemoteVideoTrack, participant: RemoteParticipant) {} |
| 305 | fun switchedOnVideo(track: RemoteVideoTrack, participant: RemoteParticipant) {} | 215 | fun switchedOnVideo(track: RemoteVideoTrack, participant: RemoteParticipant) {} |
| 306 | -// fun onChangePublishPriority(videoTrack: RemoteVideoTrackPublication, priority: PublishPriority, participant: RemoteParticipant) | ||
| 307 | -// fun onChangePublishPriority(audioTrack: RemoteAudioTrackPublication, priority: PublishPriority, participant: RemoteParticipant) | ||
| 308 | -// fun onChangePublishPriority(dataTrack: RemoteDataTrackPublication, priority: PublishPriority, participant: RemoteParticipant) | ||
| 309 | } | 216 | } |
| 310 | 217 | ||
| 311 | } | 218 | } |
| 1 | package io.livekit.android.room.track | 1 | package io.livekit.android.room.track |
| 2 | 2 | ||
| 3 | +import livekit.LivekitModels | ||
| 3 | import org.webrtc.AudioTrack | 4 | import org.webrtc.AudioTrack |
| 4 | -import org.webrtc.MediaStreamTrack | ||
| 5 | 5 | ||
| 6 | -open class AudioTrack(name: String, val rtcTrack: AudioTrack) : | ||
| 7 | - Track(name, stateFromRTCMediaTrackState(rtcTrack.state())), | ||
| 8 | - MediaTrack { | 6 | +open class AudioTrack(name: String, override val rtcTrack: AudioTrack) : |
| 7 | + MediaTrack(name, LivekitModels.TrackType.AUDIO, rtcTrack) { | ||
| 9 | 8 | ||
| 10 | - override val mediaTrack: MediaStreamTrack | ||
| 11 | - get() = rtcTrack | ||
| 12 | } | 9 | } |
| 1 | package io.livekit.android.room.track | 1 | package io.livekit.android.room.track |
| 2 | 2 | ||
| 3 | +import livekit.LivekitModels | ||
| 3 | import org.webrtc.DataChannel | 4 | import org.webrtc.DataChannel |
| 4 | 5 | ||
| 5 | open class DataTrack( | 6 | open class DataTrack( |
| 6 | name: String, | 7 | name: String, |
| 7 | - var rtcTrack: DataChannel? = null | ||
| 8 | -) : Track( | ||
| 9 | - name, | ||
| 10 | - run { | ||
| 11 | - if (rtcTrack != null) { | ||
| 12 | - stateFromRTCDataChannelState(rtcTrack.state()) | ||
| 13 | - } else { | ||
| 14 | - State.NONE | ||
| 15 | - } | ||
| 16 | - }) { | ||
| 17 | - | 8 | + var dataChannel: DataChannel? = null |
| 9 | +) : Track(name, LivekitModels.TrackType.DATA) { | ||
| 18 | var ordered: Boolean = TODO() | 10 | var ordered: Boolean = TODO() |
| 19 | private set | 11 | private set |
| 20 | var maxRetransmitTimeMs: Int = TODO() | 12 | var maxRetransmitTimeMs: Int = TODO() |
| @@ -27,4 +19,8 @@ open class DataTrack( | @@ -27,4 +19,8 @@ open class DataTrack( | ||
| 27 | maxRetransmitTimeMs = config.maxRetransmitTimeMs | 19 | maxRetransmitTimeMs = config.maxRetransmitTimeMs |
| 28 | maxRetransmits = config.maxRetransmits | 20 | maxRetransmits = config.maxRetransmits |
| 29 | } | 21 | } |
| 30 | -} | ||
| 22 | + | ||
| 23 | + override fun stop() { | ||
| 24 | + dataChannel?.unregisterObserver() | ||
| 25 | + } | ||
| 26 | +} |
| @@ -7,16 +7,14 @@ import java.util.* | @@ -7,16 +7,14 @@ import java.util.* | ||
| 7 | class LocalAudioTrack( | 7 | class LocalAudioTrack( |
| 8 | name: String, | 8 | name: String, |
| 9 | audioOptions: AudioOptions? = null, | 9 | audioOptions: AudioOptions? = null, |
| 10 | - rtcTrack: org.webrtc.AudioTrack | ||
| 11 | -) : AudioTrack(name, rtcTrack) { | 10 | + mediaTrack: org.webrtc.AudioTrack |
| 11 | +) : AudioTrack(name, mediaTrack) { | ||
| 12 | var enabled: Boolean | 12 | var enabled: Boolean |
| 13 | get() = rtcTrack.enabled() | 13 | get() = rtcTrack.enabled() |
| 14 | set(value) { | 14 | set(value) { |
| 15 | rtcTrack.setEnabled(value) | 15 | rtcTrack.setEnabled(value) |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | - var sid: Sid? = null | ||
| 19 | - internal set | ||
| 20 | var audioOptions = audioOptions | 18 | var audioOptions = audioOptions |
| 21 | private set | 19 | private set |
| 22 | 20 | ||
| @@ -31,7 +29,7 @@ class LocalAudioTrack( | @@ -31,7 +29,7 @@ class LocalAudioTrack( | ||
| 31 | val rtcAudioTrack = | 29 | val rtcAudioTrack = |
| 32 | factory.createAudioTrack(UUID.randomUUID().toString(), audioSource) | 30 | factory.createAudioTrack(UUID.randomUUID().toString(), audioSource) |
| 33 | 31 | ||
| 34 | - return LocalAudioTrack(name = name, rtcTrack = rtcAudioTrack) | 32 | + return LocalAudioTrack(name = name, mediaTrack = rtcAudioTrack) |
| 35 | } | 33 | } |
| 36 | } | 34 | } |
| 37 | -} | ||
| 35 | +} |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/LocalAudioTrackPublication.kt
已删除
100644 → 0
| 1 | -package io.livekit.android.room.track | ||
| 2 | - | ||
| 3 | -import livekit.LivekitModels | ||
| 4 | - | ||
| 5 | -class LocalAudioTrackPublication(info: LivekitModels.TrackInfo, track: Track? = null) : | ||
| 6 | - LocalTrackPublication(info, track), AudioTrackPublication { | ||
| 7 | - override val audioTrack: AudioTrack? | ||
| 8 | - get() = track as? AudioTrack | ||
| 9 | -} |
| @@ -5,21 +5,20 @@ import java.nio.ByteBuffer | @@ -5,21 +5,20 @@ import java.nio.ByteBuffer | ||
| 5 | import java.util.* | 5 | import java.util.* |
| 6 | 6 | ||
| 7 | class LocalDataTrack( | 7 | class LocalDataTrack( |
| 8 | - val options: DataTrackOptions, | ||
| 9 | - rtcTrack: DataChannel | ||
| 10 | -) : DataTrack(options.name, rtcTrack) { | ||
| 11 | - var sid: Sid? = null | 8 | + val options: DataTrackOptions |
| 9 | +) : DataTrack(options.name) { | ||
| 10 | + var sid: String? = null | ||
| 12 | internal set | 11 | internal set |
| 13 | - var cid: Cid = Cid(UUID.randomUUID().toString()) | 12 | + var cid: String = UUID.randomUUID().toString() |
| 14 | 13 | ||
| 15 | fun sendString(message: String) { | 14 | fun sendString(message: String) { |
| 16 | val byteBuffer = ByteBuffer.wrap(message.toByteArray()) | 15 | val byteBuffer = ByteBuffer.wrap(message.toByteArray()) |
| 17 | val buffer = DataChannel.Buffer(byteBuffer, false) | 16 | val buffer = DataChannel.Buffer(byteBuffer, false) |
| 18 | - rtcTrack?.send(buffer) | 17 | + dataChannel?.send(buffer) |
| 19 | } | 18 | } |
| 20 | 19 | ||
| 21 | fun sendBytes(byteBuffer: ByteBuffer) { | 20 | fun sendBytes(byteBuffer: ByteBuffer) { |
| 22 | val buffer = DataChannel.Buffer(byteBuffer, true) | 21 | val buffer = DataChannel.Buffer(byteBuffer, true) |
| 23 | - rtcTrack?.send(buffer) | 22 | + dataChannel?.send(buffer) |
| 24 | } | 23 | } |
| 25 | -} | ||
| 24 | +} |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/LocalDataTrackPublication.kt
已删除
100644 → 0
| 1 | -package io.livekit.android.room.track | ||
| 2 | - | ||
| 3 | -import livekit.LivekitModels | ||
| 4 | - | ||
| 5 | -class LocalDataTrackPublication(info: LivekitModels.TrackInfo, track: Track? = null) : | ||
| 6 | - LocalTrackPublication(info, track), DataTrackPublication { | ||
| 7 | - override val dataTrack: DataTrack? | ||
| 8 | - get() = track as? DataTrack | ||
| 9 | -} |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/LocalTrackPublication.kt
已删除
100644 → 0
| 1 | -package io.livekit.android.room.track | ||
| 2 | - | ||
| 3 | -import livekit.LivekitModels | ||
| 4 | - | ||
| 5 | -open class LocalTrackPublication(info: LivekitModels.TrackInfo, track: Track? = null) : | ||
| 6 | - TrackPublication(info, track) { | ||
| 7 | - val localTrack | ||
| 8 | - get() = track | ||
| 9 | - var priority = Track.Priority.STANDARD | ||
| 10 | - private set | ||
| 11 | -} |
| @@ -16,8 +16,6 @@ class LocalVideoTrack( | @@ -16,8 +16,6 @@ class LocalVideoTrack( | ||
| 16 | capturer.startCapture(400, 400, 30) | 16 | capturer.startCapture(400, 400, 30) |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | - var sid: Sid? = null | ||
| 20 | - | ||
| 21 | companion object { | 19 | companion object { |
| 22 | internal fun createTrack( | 20 | internal fun createTrack( |
| 23 | peerConnectionFactory: PeerConnectionFactory, | 21 | peerConnectionFactory: PeerConnectionFactory, |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/LocalVideoTrackPublication.kt
已删除
100644 → 0
| 1 | -package io.livekit.android.room.track | ||
| 2 | - | ||
| 3 | -import livekit.LivekitModels | ||
| 4 | - | ||
| 5 | -class LocalVideoTrackPublication(info: LivekitModels.TrackInfo, track: Track? = null) : | ||
| 6 | - LocalTrackPublication(info, track), VideoTrackPublication { | ||
| 7 | - override val videoTrack: VideoTrack? | ||
| 8 | - get() = track as? VideoTrack | ||
| 9 | -} |
| 1 | package io.livekit.android.room.track | 1 | package io.livekit.android.room.track |
| 2 | 2 | ||
| 3 | +import livekit.LivekitModels | ||
| 3 | import org.webrtc.MediaStreamTrack | 4 | import org.webrtc.MediaStreamTrack |
| 4 | 5 | ||
| 5 | -interface MediaTrack { | ||
| 6 | - val mediaTrack: MediaStreamTrack | ||
| 7 | -} | ||
| 6 | + | ||
| 7 | +open class MediaTrack(name: String, kind: LivekitModels.TrackType, open val rtcTrack: MediaStreamTrack) : | ||
| 8 | + Track(name, kind) { | ||
| 9 | + | ||
| 10 | + override fun stop() { | ||
| 11 | + rtcTrack.setEnabled(false) | ||
| 12 | + rtcTrack.dispose() | ||
| 13 | + } | ||
| 14 | +} |
| 1 | package io.livekit.android.room.track | 1 | package io.livekit.android.room.track |
| 2 | 2 | ||
| 3 | class RemoteAudioTrack( | 3 | class RemoteAudioTrack( |
| 4 | - sid: Sid, | 4 | + sid: String, |
| 5 | playbackEnabled: Boolean = true, | 5 | playbackEnabled: Boolean = true, |
| 6 | name: String, | 6 | name: String, |
| 7 | - rtcTrack: org.webrtc.AudioTrack | ||
| 8 | -) : AudioTrack(name, rtcTrack), RemoteTrack { | 7 | + mediaTrack: org.webrtc.AudioTrack |
| 8 | +) : AudioTrack(name, mediaTrack), RemoteTrack { | ||
| 9 | 9 | ||
| 10 | - | ||
| 11 | - override var sid: Sid = sid | 10 | + override var sid: String = sid |
| 12 | var playbackEnabled = playbackEnabled | 11 | var playbackEnabled = playbackEnabled |
| 13 | internal set | 12 | internal set |
| 14 | 13 | ||
| 15 | - | ||
| 16 | } | 14 | } |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/RemoteAudioTrackPublication.kt
已删除
100644 → 0
| 1 | -package io.livekit.android.room.track | ||
| 2 | - | ||
| 3 | -import livekit.LivekitModels | ||
| 4 | - | ||
| 5 | -class RemoteAudioTrackPublication( | ||
| 6 | - info: LivekitModels.TrackInfo, | ||
| 7 | - track: Track? = null | ||
| 8 | -) : RemoteTrackPublication(info, track), AudioTrackPublication { | ||
| 9 | - override val audioTrack: AudioTrack? | ||
| 10 | - get() = track as? AudioTrack | ||
| 11 | -} |
| @@ -3,7 +3,7 @@ package io.livekit.android.room.track | @@ -3,7 +3,7 @@ package io.livekit.android.room.track | ||
| 3 | import org.webrtc.DataChannel | 3 | import org.webrtc.DataChannel |
| 4 | 4 | ||
| 5 | class RemoteDataTrack( | 5 | class RemoteDataTrack( |
| 6 | - override var sid: Sid, | 6 | + override var sid: String, |
| 7 | name: String, | 7 | name: String, |
| 8 | rtcTrack: DataChannel | 8 | rtcTrack: DataChannel |
| 9 | ) : | 9 | ) : |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/RemoteDataTrackPublication.kt
已删除
100644 → 0
| 1 | -package io.livekit.android.room.track | ||
| 2 | - | ||
| 3 | -import livekit.LivekitModels | ||
| 4 | - | ||
| 5 | -class RemoteDataTrackPublication( | ||
| 6 | - info: LivekitModels.TrackInfo, | ||
| 7 | - track: Track? = null | ||
| 8 | -) : RemoteTrackPublication(info, track), DataTrackPublication { | ||
| 9 | - override val dataTrack: DataTrack? | ||
| 10 | - get() = track as? DataTrack | ||
| 11 | -} |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/RemoteTrackPublication.kt
已删除
100644 → 0
| 1 | -package io.livekit.android.room.track | ||
| 2 | - | ||
| 3 | -import livekit.LivekitModels | ||
| 4 | - | ||
| 5 | -open class RemoteTrackPublication(info: LivekitModels.TrackInfo, track: Track? = null) : | ||
| 6 | - TrackPublication(info, track) { | ||
| 7 | - | ||
| 8 | - val remoteTrack: Track? | ||
| 9 | - get() = track | ||
| 10 | - | ||
| 11 | - val trackSubscribed: Boolean | ||
| 12 | - get() = track != null | ||
| 13 | - | ||
| 14 | - val publishPriority = Track.Priority.STANDARD | ||
| 15 | -} |
| 1 | package io.livekit.android.room.track | 1 | package io.livekit.android.room.track |
| 2 | 2 | ||
| 3 | class RemoteVideoTrack( | 3 | class RemoteVideoTrack( |
| 4 | - override var sid: Sid, | 4 | + override var sid: String, |
| 5 | var switchedOff: Boolean = false, | 5 | var switchedOff: Boolean = false, |
| 6 | - var priority: Priority? = null, | ||
| 7 | name: String, | 6 | name: String, |
| 8 | - rtcTrack: org.webrtc.VideoTrack | ||
| 9 | -) : VideoTrack(name, rtcTrack), RemoteTrack | ||
| 7 | + mediaTrack: org.webrtc.VideoTrack | ||
| 8 | +) : VideoTrack(name, mediaTrack), RemoteTrack |
livekit-android-sdk/src/main/java/io/livekit/android/room/track/RemoteVideoTrackPublication.kt
已删除
100644 → 0
| 1 | -package io.livekit.android.room.track | ||
| 2 | - | ||
| 3 | -import livekit.LivekitModels | ||
| 4 | - | ||
| 5 | -class RemoteVideoTrackPublication(info: LivekitModels.TrackInfo, track: Track? = null) : | ||
| 6 | - RemoteTrackPublication(info, track), | ||
| 7 | - VideoTrackPublication { | ||
| 8 | - | ||
| 9 | - override val videoTrack: VideoTrack? | ||
| 10 | - get() = track as? VideoTrack | ||
| 11 | -} |
| 1 | package io.livekit.android.room.track | 1 | package io.livekit.android.room.track |
| 2 | 2 | ||
| 3 | +import livekit.LivekitModels | ||
| 3 | import org.webrtc.DataChannel | 4 | import org.webrtc.DataChannel |
| 4 | import org.webrtc.MediaStreamTrack | 5 | import org.webrtc.MediaStreamTrack |
| 5 | 6 | ||
| 6 | -open class Track(name: String, state: State) { | ||
| 7 | - | 7 | +open class Track(name: String, kind: LivekitModels.TrackType) { |
| 8 | var name = name | 8 | var name = name |
| 9 | internal set | 9 | internal set |
| 10 | - var state = state | 10 | + var kind = kind |
| 11 | internal set | 11 | internal set |
| 12 | - | ||
| 13 | - inline class Sid(val sid: String) | ||
| 14 | - inline class Cid(val cid: String) | ||
| 15 | - | ||
| 16 | - enum class Priority { | ||
| 17 | - STANDARD, HIGH, LOW; | ||
| 18 | - } | 12 | + var state: State = State.NONE |
| 19 | 13 | ||
| 20 | enum class State { | 14 | enum class State { |
| 21 | ENDED, LIVE, NONE; | 15 | ENDED, LIVE, NONE; |
| 22 | } | 16 | } |
| 23 | 17 | ||
| 18 | + open fun stop() { | ||
| 19 | + // subclasses override to provide stop behavior | ||
| 20 | + } | ||
| 21 | + | ||
| 24 | companion object { | 22 | companion object { |
| 25 | fun stateFromRTCMediaTrackState(trackState: MediaStreamTrack.State): State { | 23 | fun stateFromRTCMediaTrackState(trackState: MediaStreamTrack.State): State { |
| 26 | return when (trackState) { | 24 | return when (trackState) { |
| @@ -42,6 +40,7 @@ open class Track(name: String, state: State) { | @@ -42,6 +40,7 @@ open class Track(name: String, state: State) { | ||
| 42 | } | 40 | } |
| 43 | } | 41 | } |
| 44 | } | 42 | } |
| 43 | + | ||
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | sealed class TrackException(message: String? = null, cause: Throwable? = null) : | 46 | sealed class TrackException(message: String? = null, cause: Throwable? = null) : |
| @@ -5,18 +5,28 @@ import livekit.LivekitModels | @@ -5,18 +5,28 @@ import livekit.LivekitModels | ||
| 5 | open class TrackPublication(info: LivekitModels.TrackInfo, track: Track? = null) { | 5 | open class TrackPublication(info: LivekitModels.TrackInfo, track: Track? = null) { |
| 6 | var track: Track? = track | 6 | var track: Track? = track |
| 7 | internal set | 7 | internal set |
| 8 | - var trackName: String | 8 | + var name: String |
| 9 | internal set | 9 | internal set |
| 10 | - var trackSid: Track.Sid | 10 | + var sid: String |
| 11 | + private set | ||
| 12 | + var kind: LivekitModels.TrackType | ||
| 13 | + private set | ||
| 14 | + var muted: Boolean | ||
| 11 | private set | 15 | private set |
| 12 | 16 | ||
| 13 | init { | 17 | init { |
| 14 | - trackSid = Track.Sid(info.sid) | ||
| 15 | - trackName = info.name | 18 | + sid = info.sid |
| 19 | + name = info.name | ||
| 20 | + kind = info.type | ||
| 21 | + muted = info.muted | ||
| 16 | } | 22 | } |
| 17 | 23 | ||
| 18 | fun updateFromInfo(info: LivekitModels.TrackInfo) { | 24 | fun updateFromInfo(info: LivekitModels.TrackInfo) { |
| 19 | - trackSid = Track.Sid(info.sid) | ||
| 20 | - trackName = info.name | 25 | + sid = info.sid |
| 26 | + name = info.name | ||
| 27 | + kind = info.type | ||
| 28 | + | ||
| 29 | + // TODO: forward mute status to listener | ||
| 30 | + muted = info.muted | ||
| 21 | } | 31 | } |
| 22 | -} | ||
| 32 | +} |
| 1 | package io.livekit.android.room.track | 1 | package io.livekit.android.room.track |
| 2 | 2 | ||
| 3 | -import org.webrtc.MediaStreamTrack | 3 | +import livekit.LivekitModels |
| 4 | import org.webrtc.VideoSink | 4 | import org.webrtc.VideoSink |
| 5 | import org.webrtc.VideoTrack | 5 | import org.webrtc.VideoTrack |
| 6 | 6 | ||
| 7 | -open class VideoTrack(name: String, val rtcTrack: VideoTrack) : | ||
| 8 | - Track(name, stateFromRTCMediaTrackState(rtcTrack.state())), | ||
| 9 | - MediaTrack { | ||
| 10 | - | ||
| 11 | - override val mediaTrack: MediaStreamTrack | ||
| 12 | - get() = rtcTrack | 7 | +open class VideoTrack(name: String, override val rtcTrack: VideoTrack) : |
| 8 | + MediaTrack(name, LivekitModels.TrackType.VIDEO, rtcTrack){ | ||
| 13 | 9 | ||
| 14 | var enabled: Boolean | 10 | var enabled: Boolean |
| 15 | get() = rtcTrack.enabled() | 11 | get() = rtcTrack.enabled() |
| @@ -20,4 +16,4 @@ open class VideoTrack(name: String, val rtcTrack: VideoTrack) : | @@ -20,4 +16,4 @@ open class VideoTrack(name: String, val rtcTrack: VideoTrack) : | ||
| 20 | fun addRenderer(renderer: VideoSink) = rtcTrack.addSink(renderer) | 16 | fun addRenderer(renderer: VideoSink) = rtcTrack.addSink(renderer) |
| 21 | 17 | ||
| 22 | fun removeRenderer(renderer: VideoSink) = rtcTrack.addSink(renderer) | 18 | fun removeRenderer(renderer: VideoSink) = rtcTrack.addSink(renderer) |
| 23 | -} | ||
| 19 | +} |
| @@ -4,19 +4,19 @@ import io.livekit.android.room.participant.Participant | @@ -4,19 +4,19 @@ import io.livekit.android.room.participant.Participant | ||
| 4 | import io.livekit.android.room.track.Track | 4 | import io.livekit.android.room.track.Track |
| 5 | import org.webrtc.DataChannel | 5 | import org.webrtc.DataChannel |
| 6 | 6 | ||
| 7 | -fun DataChannel.unpackedTrackLabel(): Triple<Participant.Sid, Track.Sid, String> { | 7 | +fun DataChannel.unpackedTrackLabel(): Triple<String, String, String> { |
| 8 | val parts = label().split("|") | 8 | val parts = label().split("|") |
| 9 | - val participantSid: Participant.Sid | ||
| 10 | - val trackSid: Track.Sid | 9 | + val participantSid: String |
| 10 | + val trackSid: String | ||
| 11 | val name: String | 11 | val name: String |
| 12 | 12 | ||
| 13 | if (parts.count() == 3) { | 13 | if (parts.count() == 3) { |
| 14 | - participantSid = Participant.Sid(parts[0]) | ||
| 15 | - trackSid = Track.Sid(parts[1]) | 14 | + participantSid = parts[0] |
| 15 | + trackSid = parts[1] | ||
| 16 | name = parts[2] | 16 | name = parts[2] |
| 17 | } else { | 17 | } else { |
| 18 | - participantSid = Participant.Sid("") | ||
| 19 | - trackSid = Track.Sid("") | 18 | + participantSid = "" |
| 19 | + trackSid = "" | ||
| 20 | name = "" | 20 | name = "" |
| 21 | } | 21 | } |
| 22 | 22 |
| @@ -51,7 +51,7 @@ class CallActivity : AppCompatActivity() { | @@ -51,7 +51,7 @@ class CallActivity : AppCompatActivity() { | ||
| 51 | 51 | ||
| 52 | tabLayoutMediator = | 52 | tabLayoutMediator = |
| 53 | TabLayoutMediator(binding.tabs, binding.viewPager) { tab, position -> | 53 | TabLayoutMediator(binding.tabs, binding.viewPager) { tab, position -> |
| 54 | - tab.text = participants[position].name | 54 | + tab.text = participants[position].identity |
| 55 | } | 55 | } |
| 56 | tabLayoutMediator?.attach() | 56 | tabLayoutMediator?.attach() |
| 57 | } | 57 | } |
| @@ -84,7 +84,7 @@ class CallViewModel( | @@ -84,7 +84,7 @@ class CallViewModel( | ||
| 84 | mutableRemoteParticipants.postValue( | 84 | mutableRemoteParticipants.postValue( |
| 85 | room.remoteParticipants | 85 | room.remoteParticipants |
| 86 | .keys | 86 | .keys |
| 87 | - .sortedBy { it.sid } | 87 | + .sortedBy { it } |
| 88 | .mapNotNull { room.remoteParticipants[it] } | 88 | .mapNotNull { room.remoteParticipants[it] } |
| 89 | ) | 89 | ) |
| 90 | } | 90 | } |
| 1 | package io.livekit.android.sample | 1 | package io.livekit.android.sample |
| 2 | 2 | ||
| 3 | +import android.provider.MediaStore | ||
| 3 | import android.view.View | 4 | import android.view.View |
| 4 | import com.github.ajalt.timberkt.Timber | 5 | import com.github.ajalt.timberkt.Timber |
| 5 | import com.xwray.groupie.viewbinding.BindableItem | 6 | import com.xwray.groupie.viewbinding.BindableItem |
| 6 | import com.xwray.groupie.viewbinding.GroupieViewHolder | 7 | import com.xwray.groupie.viewbinding.GroupieViewHolder |
| 7 | import io.livekit.android.room.Room | 8 | import io.livekit.android.room.Room |
| 8 | import io.livekit.android.room.participant.RemoteParticipant | 9 | import io.livekit.android.room.participant.RemoteParticipant |
| 9 | -import io.livekit.android.room.track.RemoteVideoTrackPublication | ||
| 10 | -import io.livekit.android.room.track.VideoTrack | ||
| 11 | -import io.livekit.android.room.track.VideoTrackPublication | 10 | +import io.livekit.android.room.track.* |
| 12 | import io.livekit.android.sample.databinding.ParticipantItemBinding | 11 | import io.livekit.android.sample.databinding.ParticipantItemBinding |
| 13 | 12 | ||
| 14 | class ParticipantItem( | 13 | class ParticipantItem( |
| @@ -30,11 +29,11 @@ class ParticipantItem( | @@ -30,11 +29,11 @@ class ParticipantItem( | ||
| 30 | 29 | ||
| 31 | remoteParticipant.listener = object : RemoteParticipant.Listener { | 30 | remoteParticipant.listener = object : RemoteParticipant.Listener { |
| 32 | override fun onSubscribe( | 31 | override fun onSubscribe( |
| 33 | - videoTrack: RemoteVideoTrackPublication, | 32 | + track: Track, |
| 33 | + publication: TrackPublication, | ||
| 34 | participant: RemoteParticipant | 34 | participant: RemoteParticipant |
| 35 | ) { | 35 | ) { |
| 36 | - val track = videoTrack.videoTrack | ||
| 37 | - if (track != null) { | 36 | + if (track is VideoTrack) { |
| 38 | setupVideoIfNeeded(track, viewBinding) | 37 | setupVideoIfNeeded(track, viewBinding) |
| 39 | } | 38 | } |
| 40 | } | 39 | } |
| @@ -48,10 +47,8 @@ class ParticipantItem( | @@ -48,10 +47,8 @@ class ParticipantItem( | ||
| 48 | 47 | ||
| 49 | private fun getVideoTrack(): VideoTrack? { | 48 | private fun getVideoTrack(): VideoTrack? { |
| 50 | return remoteParticipant | 49 | return remoteParticipant |
| 51 | - .remoteVideoTracks | ||
| 52 | - .firstOrNull() | ||
| 53 | - .let { it as? VideoTrackPublication } | ||
| 54 | - ?.videoTrack | 50 | + .videoTracks.values |
| 51 | + .firstOrNull()?.track as? VideoTrack | ||
| 55 | } | 52 | } |
| 56 | 53 | ||
| 57 | private fun setupVideoIfNeeded(videoTrack: VideoTrack, viewBinding: ParticipantItemBinding) { | 54 | private fun setupVideoIfNeeded(videoTrack: VideoTrack, viewBinding: ParticipantItemBinding) { |
-
请 注册 或 登录 后发表评论