davidliu
Committed by GitHub

Add documentation for various undocumented methods (#427)

* KDocs for undocumented methods

* More KDocs

* spotless
正在显示 21 个修改的文件 包含 158 行增加38 行删除
... ... @@ -26,6 +26,11 @@ import io.livekit.android.util.LKLog
import io.livekit.android.util.LoggingLevel
import timber.log.Timber
/**
* The main entry point into using LiveKit.
*
* @see [LiveKit.create]
*/
object LiveKit {
/**
* [LoggingLevel] to use for Livekit logs. Set to [LoggingLevel.OFF] to turn off logs.
... ...
... ... @@ -17,7 +17,9 @@
package io.livekit.android
import android.media.AudioAttributes
import android.media.AudioFocusRequest
import android.media.AudioManager
import android.media.AudioTrack
import io.livekit.android.audio.AudioFocusHandler
import io.livekit.android.audio.AudioHandler
import io.livekit.android.audio.AudioProcessorOptions
... ... @@ -31,7 +33,6 @@ import livekit.org.webrtc.VideoEncoderFactory
import livekit.org.webrtc.audio.AudioDeviceModule
import livekit.org.webrtc.audio.JavaAudioDeviceModule
import okhttp3.OkHttpClient
/**
* Overrides to replace LiveKit internally used components with custom implementations.
*/
... ... @@ -138,8 +139,25 @@ class AudioOptions(
* Audio types for customizing the audio of LiveKit.
*/
sealed class AudioType(
/**
* The audio mode to use when playing audio through LiveKit.
*
* @see [AudioManager.setMode]
*/
val audioMode: Int,
/**
* The audio attributes to use when playing audio through LiveKit.
*
* @see [AudioTrack]
* @see [AudioFocusRequest]
*/
val audioAttributes: AudioAttributes,
/**
* The audio attributes to use when playing audio through LiveKit on pre-O devices.
*
* @see [AudioTrack]
* @see [AudioManager.requestAudioFocus]
*/
val audioStreamType: Int,
) {
/**
... ...
... ... @@ -16,6 +16,9 @@
package io.livekit.android.audio
/**
* Options for audio processing.
*/
data class AudioProcessorOptions(
/**
* Audio processor for captured audio.
... ...
... ... @@ -51,6 +51,9 @@ interface CommunicationWorkaround {
fun dispose()
}
/**
* @suppress
*/
class NoopCommunicationWorkaround
@Inject
constructor() : CommunicationWorkaround {
... ... @@ -77,7 +80,7 @@ constructor() : CommunicationWorkaround {
*/
@Singleton
@RequiresApi(Build.VERSION_CODES.R)
class CommunicationWorkaroundImpl
internal class CommunicationWorkaroundImpl
@Inject
constructor(
@Named(InjectionNames.DISPATCHER_MAIN)
... ...
/*
* Copyright 2023 LiveKit, Inc.
* Copyright 2023-2024 LiveKit, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
... ... @@ -22,6 +22,9 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
/**
* @suppress
*/
class BroadcastEventBus<T> : EventListenable<T> {
private val mutableEvents = MutableSharedFlow<T>(extraBufferCapacity = Int.MAX_VALUE)
override val events = mutableEvents.asSharedFlow()
... ...
... ... @@ -19,6 +19,10 @@ package io.livekit.android.events
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharedFlow
/**
* An interface declaring that this object emits events that can be collected.
* @see [EventListenable.collect]
*/
interface EventListenable<out T> {
val events: SharedFlow<T>
}
... ...
... ... @@ -27,6 +27,7 @@ open class SurfaceViewRenderer : SurfaceViewRenderer, ViewVisibility.Notifier {
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
override var viewVisibility: ViewVisibility? = null
override fun onVisibilityChanged(changedView: View, visibility: Int) {
super.onVisibilityChanged(changedView, visibility)
viewVisibility?.recalculate()
... ...
... ... @@ -77,6 +77,9 @@ constructor(
private val e2EEManagerFactory: E2EEManager.Factory,
private val communicationWorkaround: CommunicationWorkaround,
val audioProcessingController: AudioProcessingController,
/**
* A holder for objects that are used internally within LiveKit.
*/
val lkObjects: LKObjects,
networkCallbackManagerFactory: NetworkCallbackManagerFactory,
private val audioDeviceModule: AudioDeviceModule,
... ...
... ... @@ -46,6 +46,9 @@ internal class NetworkCallbackRegistryImpl(val connectivityManager: Connectivity
}
}
/**
* @suppress
*/
interface NetworkCallbackManager : Closeable {
fun registerCallback()
fun unregisterCallback()
... ...
... ... @@ -19,6 +19,7 @@ package io.livekit.android.room.participant
import android.Manifest
import android.content.Context
import android.content.Intent
import androidx.annotation.VisibleForTesting
import com.google.protobuf.ByteString
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
... ... @@ -183,15 +184,29 @@ internal constructor(
return super.getTrackPublicationByName(name) as? LocalTrackPublication
}
/**
* If set to enabled, creates and publishes a camera video track if not already done, and starts the camera.
*
* If set to disabled, mutes and stops the camera.
*/
suspend fun setCameraEnabled(enabled: Boolean) {
setTrackEnabled(Track.Source.CAMERA, enabled)
}
/**
* If set to enabled, creates and publishes a microphone audio track if not already done, and unmutes the mic.
*
* If set to disabled, mutes the mic.
*/
suspend fun setMicrophoneEnabled(enabled: Boolean) {
setTrackEnabled(Track.Source.MICROPHONE, enabled)
}
/**
* If set to enabled, creates and publishes a screenshare video track.
*
* If set to disabled, unpublishes the screenshare video track.
*
* @param mediaProjectionPermissionResultData The resultData returned from launching
* [MediaProjectionManager.createScreenCaptureIntent()](https://developer.android.com/reference/android/media/projection/MediaProjectionManager#createScreenCaptureIntent()).
* @throws IllegalArgumentException if attempting to enable screenshare without [mediaProjectionPermissionResultData]
... ... @@ -260,6 +275,9 @@ internal constructor(
}
}
/**
* Publishes an audio track.
*/
suspend fun publishAudioTrack(
track: LocalAudioTrack,
options: AudioTrackPublishOptions = AudioTrackPublishOptions(
... ... @@ -288,6 +306,9 @@ internal constructor(
)
}
/**
* Publishes an video track.
*/
suspend fun publishVideoTrack(
track: LocalVideoTrack,
options: VideoTrackPublishOptions = VideoTrackPublishOptions(null, videoTrackPublishDefaults),
... ... @@ -571,6 +592,11 @@ internal constructor(
engine.updateSubscriptionPermissions(allParticipantsAllowed, participantTrackPermissions)
}
/**
* Unpublish a track.
*
* @param stopOnUnpublish if true, stops the track after unpublishing the track. Defaults to true.
*/
fun unpublishTrack(track: Track, stopOnUnpublish: Boolean = true) {
val publication = localTrackPublications.firstOrNull { it.track == track }
if (publication === null) {
... ... @@ -633,6 +659,10 @@ internal constructor(
engine.sendData(dataPacket)
}
/**
* @suppress
*/
@VisibleForTesting
override fun updateFromInfo(info: LivekitModels.ParticipantInfo) {
super.updateFromInfo(info)
... ... @@ -773,7 +803,7 @@ internal constructor(
unpublishTrack(track)
}
fun prepareForFullReconnect() {
internal fun prepareForFullReconnect() {
val pubs = localTrackPublications.toList() // creates a copy, so is safe from the following removal.
// Only set the first time we start a full reconnect.
... ... @@ -789,7 +819,7 @@ internal constructor(
}
}
suspend fun republishTracks() {
internal suspend fun republishTracks() {
val publish = republishes?.toList() ?: emptyList()
republishes = null
... ... @@ -807,6 +837,9 @@ internal constructor(
}
}
/**
* @suppress
*/
fun cleanup() {
for (pub in trackPublications.values) {
val track = pub.track
... ... @@ -825,6 +858,9 @@ internal constructor(
}
}
/**
* @suppress
*/
override fun dispose() {
cleanup()
super.dispose()
... ... @@ -965,6 +1001,9 @@ data class BackupVideoCodec(
)
abstract class BaseAudioTrackPublishOptions {
/**
* The target audioBitrate to use.
*/
abstract val audioBitrate: Int?
/**
... ...
... ... @@ -28,8 +28,18 @@ import io.livekit.android.room.track.TrackPublication
import io.livekit.android.util.FlowObservable
import io.livekit.android.util.flow
import io.livekit.android.util.flowDelegate
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.isActive
import kotlinx.serialization.Serializable
import livekit.LivekitModels
import java.util.Date
... ... @@ -302,7 +312,6 @@ open class Participant(
/**
* @suppress
*/
@VisibleForTesting
open fun updateFromInfo(info: LivekitModels.ParticipantInfo) {
sid = Sid(info.sid)
identity = Identity(info.identity)
... ...
... ... @@ -37,10 +37,13 @@ import livekit.org.webrtc.MediaStreamTrack
import livekit.org.webrtc.RtpReceiver
import livekit.org.webrtc.VideoTrack
/**
* A representation of a remote participant.
*/
class RemoteParticipant(
sid: Sid,
identity: Identity? = null,
val signalClient: SignalClient,
internal val signalClient: SignalClient,
private val ioDispatcher: CoroutineDispatcher,
defaultDispatcher: CoroutineDispatcher,
) : Participant(sid, identity, defaultDispatcher) {
... ... @@ -68,6 +71,9 @@ class RemoteParticipant(
private val coroutineScope = CloseableCoroutineScope(defaultDispatcher + SupervisorJob())
/**
* Get a track publication with the corresponding sid.
*/
fun getTrackPublication(sid: String): RemoteTrackPublication? = trackPublications[sid] as? RemoteTrackPublication
/**
... ...
... ... @@ -113,6 +113,9 @@ constructor(
private val closeableManager = CloseableManager()
/**
* Starts the [capturer] with the capture params contained in [options].
*/
open fun startCapture() {
capturer.startCapture(
options.captureParams.width,
... ... @@ -121,6 +124,9 @@ constructor(
)
}
/**
* Stops the [capturer].
*/
open fun stopCapture() {
capturer.stopCapture()
}
... ... @@ -152,6 +158,10 @@ constructor(
}
}
/**
* If this is a camera track, switches to the new camera determined by [deviceId]
*/
@Deprecated("Use LocalVideoTrack.switchCamera instead.", ReplaceWith("switchCamera(deviceId = deviceId)"))
fun setDeviceId(deviceId: String) {
restartTrack(options.copy(deviceId = deviceId))
}
... ... @@ -346,7 +356,7 @@ constructor(
}
}
fun setPublishingCodecs(codecs: List<SubscribedCodec>): List<VideoCodec> {
internal fun setPublishingCodecs(codecs: List<SubscribedCodec>): List<VideoCodec> {
LKLog.v { "setting publishing codecs: $codecs" }
// only enable simulcast codec for preferred codec set
... ...
... ... @@ -21,6 +21,9 @@ import livekit.org.webrtc.AudioTrack
import livekit.org.webrtc.AudioTrackSink
import livekit.org.webrtc.RtpReceiver
/**
* A representation of a remote audio track.
*/
class RemoteAudioTrack(
name: String,
rtcTrack: AudioTrack,
... ...
... ... @@ -149,18 +149,27 @@ abstract class Track(
data class Dimensions(val width: Int, val height: Int)
/**
* Starts the track.
*/
open fun start() {
executeBlockingOnRTCThread {
rtcTrack.setEnabled(true)
}
}
/**
* Stops the track.
*/
open fun stop() {
executeBlockingOnRTCThread {
rtcTrack.setEnabled(false)
}
}
/**
* Disposes the track. LiveKit will generally take care of disposing tracks for you.
*/
open fun dispose() {
executeBlockingOnRTCThread {
rtcTrack.dispose()
... ...
... ... @@ -30,6 +30,9 @@ abstract class VideoTrack(name: String, override val rtcTrack: VideoTrack) :
rtcTrack.setEnabled(value)
}
/**
* Add a [VideoSink] that will receive frames.
*/
open fun addRenderer(renderer: VideoSink) {
executeBlockingOnRTCThread {
sinks.add(renderer)
... ... @@ -37,6 +40,9 @@ abstract class VideoTrack(name: String, override val rtcTrack: VideoTrack) :
}
}
/**
* Remove a previously added [VideoSink].
*/
open fun removeRenderer(renderer: VideoSink) {
executeBlockingOnRTCThread {
rtcTrack.removeSink(renderer)
... ...
... ... @@ -237,10 +237,20 @@ object CameraCapturerUtils {
return null
}
/**
* An interface declaring a provider of camera capturers.
*/
interface CameraProvider {
/**
* This acts as the priority of the CameraProvider when determining which provider to use (in order of highest to lowest).
*/
val cameraVersion: Int
fun provideEnumerator(context: Context): CameraEnumerator
fun provideCapturer(context: Context, options: LocalVideoTrackOptions, eventsHandler: CameraEventsDispatchHandler): VideoCapturer
/**
* If the return value of this method is false, this provider will be skipped when querying providers to use.
*/
fun isSupported(context: Context): Boolean
}
}
... ...
... ... @@ -20,6 +20,9 @@ import livekit.org.webrtc.CapturerObserver
import livekit.org.webrtc.VideoFrame
import livekit.org.webrtc.VideoSink
/**
* @suppress
*/
class CaptureDispatchObserver : CapturerObserver {
private val observers = linkedSetOf<CapturerObserver>()
private val sinks = linkedSetOf<VideoSink>()
... ...
... ... @@ -19,6 +19,9 @@ package io.livekit.android.room.track.video
import android.hardware.camera2.CameraManager
import livekit.org.webrtc.*
/**
* A [VideoCapturer] that declares that it can determine the actual size of the capture format it will use.
*/
interface VideoCapturerWithSize : VideoCapturer {
fun findCaptureFormat(width: Int, height: Int): Size
}
... ...
... ... @@ -77,6 +77,10 @@ class ViewVisibility(private val view: View) : VideoSinkVisibility() {
scheduleRecalculate()
}
/**
* Declares that this [View] will override [View.onVisibilityChanged] and call through to [recalculate],
* partaking in the [VideoSinkVisibility] system.
*/
interface Notifier {
var viewVisibility: ViewVisibility?
}
... ... @@ -103,6 +107,9 @@ class ViewVisibility(private val view: View) : VideoSinkVisibility() {
)
}
/**
* Recalculates whether this view's visibility has changed, and notifies observers if it has.
*/
fun recalculate() {
var shouldNotify = false
val newVisibility = isVisible()
... ...
/*
* Copyright 2024 LiveKit, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.livekit.android.util
import android.os.Handler
import android.os.Looper
fun Handler.runOrPost(r: Runnable) {
if (Looper.myLooper() == this.looper) {
r.run()
} else {
post(r)
}
}