Skip to content

Commit

Permalink
CSDK-2569: Updating to daily-android 0.26.0
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-daily committed Nov 11, 2024
1 parent 9f5789f commit b65edde
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 8 deletions.
2 changes: 1 addition & 1 deletion DailyDemo/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ android {
dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'

implementation 'co.daily:client:0.25.0'
implementation 'co.daily:client:0.26.0'

implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.android.flexbox:flexbox:3.0.0'
Expand Down
Binary file added DailyDemo/app/src/main/assets/vb-library.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 11 additions & 2 deletions DailyDemo/app/src/main/java/co/daily/core/dailydemo/DemoState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import co.daily.model.CallState
import co.daily.model.MediaStreamTrack
import co.daily.model.Participant
import co.daily.model.ParticipantId
import co.daily.settings.VideoProcessor

// As an optimization for larger calls, it would be possible to modify this to
// represent state updates rather than entire state snapshots. The MainActivity
Expand All @@ -23,6 +24,8 @@ data class DemoState(
val availableDevices: AvailableDevices,
val activeAudioDevice: String?,
val screenShareActive: Boolean,
val videoProcessor: VideoProcessor?,
val customAudioTrackFreqHz: Int?
) {
data class StreamsState(
val cameraEnabled: Boolean,
Expand All @@ -41,6 +44,8 @@ data class DemoState(
newAvailableDevices: AvailableDevices = availableDevices,
newActiveAudioDevice: String? = activeAudioDevice,
newScreenShareActive: Boolean = screenShareActive,
newVideoProcessor: VideoProcessor? = videoProcessor,
newCustomAudioTrackFreqHz: Int? = customAudioTrackFreqHz,
) = DemoState(
newStatus,
newInputs,
Expand All @@ -51,7 +56,9 @@ data class DemoState(
newAllParticipants,
newAvailableDevices,
newActiveAudioDevice,
newScreenShareActive
newScreenShareActive,
newVideoProcessor,
newCustomAudioTrackFreqHz
)

companion object {
Expand All @@ -70,7 +77,9 @@ data class DemoState(
audio = emptyList()
),
activeAudioDevice = null,
screenShareActive = false
screenShareActive = false,
videoProcessor = null,
customAudioTrackFreqHz = null
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import co.daily.model.CallState
import co.daily.model.MediaDeviceInfo
import co.daily.model.MeetingToken
import co.daily.model.RequestListener
import co.daily.settings.VideoProcessor
import co.daily.view.VideoView
import com.google.android.material.dialog.MaterialAlertDialogBuilder

Expand Down Expand Up @@ -350,6 +351,10 @@ class MainActivity : AppCompatActivity(), DemoStateListener {

menu.setOnMenuItemClickListener {
when (it.itemId) {
R.id.call_option_change_video_processor -> {
showMenuChangeVideoProcessor()
}

R.id.call_option_change_remote_participant -> {
showMenuChangeRemoteVideo()
}
Expand All @@ -370,6 +375,10 @@ class MainActivity : AppCompatActivity(), DemoStateListener {
startActivity(Intent(this@MainActivity, ChatActivity::class.java))
}

R.id.custom_audio_track -> {
showMenuCustomAudioTrack()
}

else -> {
throw RuntimeException("Unhandled menu item: ${it.itemId}")
}
Expand Down Expand Up @@ -408,6 +417,36 @@ class MainActivity : AppCompatActivity(), DemoStateListener {
initEventListeners()
}

private fun showMenuChangeVideoProcessor() {

data class VideoProcessorMenuChoice(val name: String, val choice: VideoProcessor)

val choices = listOf(
VideoProcessorMenuChoice(name = "Off", choice = VideoProcessor.None),
VideoProcessorMenuChoice(name = "Blur (low)", choice = VideoProcessor.BackgroundBlur(0.6)),
VideoProcessorMenuChoice(name = "Blur (high)", choice = VideoProcessor.BackgroundBlur(1.0)),
VideoProcessorMenuChoice(name = "Image: Library", choice = VideoProcessor.BackgroundImage("vb-library.jpg"))
)

val checkedItem = choices.indexOfFirst { it.choice == demoState?.videoProcessor }
.coerceAtLeast(0)

MaterialAlertDialogBuilder(this)
.setTitle(R.string.call_option_change_video_processor_title)
.setSingleChoiceItems(
choices.map { it.name }.toTypedArray(),
checkedItem
) { _, which ->
val item = choices[which]
Log.i(TAG, "Selected video processor: ${item.name}")
callService?.setVideoProcessor(item.choice)
}
.setNegativeButton("Close") { dialog, _ ->
dialog.dismiss()
}
.show()
}

private fun showMenuChangeRemoteVideo() {

data class RemoteVideoMenuChoice(val name: String, val choice: RemoteVideoChooser)
Expand Down Expand Up @@ -489,6 +528,30 @@ class MainActivity : AppCompatActivity(), DemoStateListener {
.show()
}

private fun showMenuCustomAudioTrack() {

// To demonstrate custom audio tracks, we generate a sine wave.
val choices = listOf(null, 250, 500, 1000, 2000)

val checkedItem = choices.indexOfFirst { it == demoState?.customAudioTrackFreqHz }
.coerceAtLeast(0)

MaterialAlertDialogBuilder(this)
.setTitle(R.string.custom_audio_track)
.setSingleChoiceItems(
choices.map { it?.let { "$it Hz sine" } ?: "None" }.toTypedArray(),
checkedItem
) { _, which ->
val item = choices[which]
Log.i(TAG, "Selected custom audio track: $item")
callService?.setCustomAudioTrack(item)
}
.setNegativeButton("Close") { dialog, _ ->
dialog.dismiss()
}
.show()
}

private fun showMessage(message: String) {
val layout = layoutInflater.inflate(R.layout.custom_toast, findViewById(R.id.custom_toast_id))
val toastMessage: TextView = layout.findViewById(R.id.custom_toast_message)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package co.daily.core.dailydemo.customtracks

import android.os.SystemClock
import android.util.Log
import co.daily.model.customtrack.AudioFrameFormat
import co.daily.model.customtrack.CustomAudioFrameConsumer
import co.daily.model.customtrack.CustomAudioSource
import java.util.concurrent.atomic.AtomicReference
import kotlin.concurrent.thread
import kotlin.math.roundToInt
import kotlin.math.sin

class DemoSineWaveAudioSource(private val sineFreqHz: Int) : CustomAudioSource() {

companion object {
private const val TAG = "DemoSineWaveAudioSource"
}

private val activeConsumer = AtomicReference<CustomAudioFrameConsumer?>(null)

override fun attachFrameConsumer(consumer: CustomAudioFrameConsumer) {

Log.i(TAG, "Frame consumer attached")

activeConsumer.set(consumer)

thread(priority = Thread.MAX_PRIORITY) {
val format = AudioFrameFormat(
bitsPerSample = 16,
sampleRateHz = 48000,
channelCount = 1
)

val periodMs = 50

val data = ShortArray((format.sampleRateHz * periodMs) / 1000)
var samplesRendered = 0

var targetTime = SystemClock.uptimeMillis() + periodMs

while (true) {

while (true) {

val now = SystemClock.uptimeMillis()

if (targetTime <= now) {
break
}

Thread.sleep(targetTime - now)
}

targetTime += periodMs

for (i in data.indices) {
val sampleNum = samplesRendered + i

val timeElapsedSecs = sampleNum.toDouble() / format.sampleRateHz.toDouble()

data[i] = (sin(timeElapsedSecs * 2.0 * Math.PI * sineFreqHz) * Short.MAX_VALUE.toDouble()).roundToInt()
.toShort()
}

samplesRendered += data.size

if (activeConsumer.get() != consumer) {
Log.i(TAG, "Shutting down sample audio renderer")
return@thread
}

consumer.sendFrame(format, data)
}
}
}

override fun detachFrameConsumer() {
Log.i(TAG, "Frame consumer detached")
activeConsumer.set(null)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import co.daily.core.dailydemo.DemoStateListener
import co.daily.core.dailydemo.DeveloperOptionsDialog
import co.daily.core.dailydemo.VideoTrackType
import co.daily.core.dailydemo.chat.ChatProtocol
import co.daily.core.dailydemo.customtracks.DemoSineWaveAudioSource
import co.daily.core.dailydemo.remotevideochooser.RemoteVideoChooser
import co.daily.core.dailydemo.remotevideochooser.RemoteVideoChooserAuto
import co.daily.model.AvailableDevices
Expand All @@ -27,6 +28,8 @@ import co.daily.model.ParticipantId
import co.daily.model.ParticipantLeftReason
import co.daily.model.Recipient
import co.daily.model.RequestListener
import co.daily.model.RequestResult
import co.daily.model.customtrack.CustomTrackName
import co.daily.model.livestream.LiveStreamStatus
import co.daily.model.recording.RecordingStatus
import co.daily.model.streaming.StreamId
Expand All @@ -36,6 +39,7 @@ import co.daily.settings.BitRate
import co.daily.settings.CameraInputSettingsUpdate
import co.daily.settings.CameraPublishingSettingsUpdate
import co.daily.settings.ClientSettingsUpdate
import co.daily.settings.CustomAudioTrackPublishingSettingsUpdate
import co.daily.settings.Enable
import co.daily.settings.FacingModeUpdate
import co.daily.settings.FrameRate
Expand All @@ -48,7 +52,9 @@ import co.daily.settings.VideoEncodingSettingsUpdate
import co.daily.settings.VideoEncodingsSettingsUpdate
import co.daily.settings.VideoMaxQualityUpdate
import co.daily.settings.VideoMediaTrackSettingsUpdate
import co.daily.settings.VideoProcessor
import co.daily.settings.VideoSendSettingsUpdate
import co.daily.settings.subscription.AudioSubscriptionSettingsUpdate
import co.daily.settings.subscription.MediaSubscriptionSettingsUpdate
import co.daily.settings.subscription.Subscribed
import co.daily.settings.subscription.SubscriptionProfile
Expand All @@ -68,6 +74,8 @@ private const val TAG = "CallService"

private const val ACTION_LEAVE = "action_leave"

private val CUSTOM_AUDIO_TRACK = CustomTrackName("demoCustomAudioTrack")

class DemoCallService : Service(), ChatProtocol.ChatProtocolListener {

private val profileActiveCamera = SubscriptionProfile("activeCamera")
Expand Down Expand Up @@ -187,6 +195,18 @@ class DemoCallService : Service(), ChatProtocol.ChatProtocolListener {
updateRemoteVideoChoice()
}

fun setVideoProcessor(videoProcessor: VideoProcessor) {
callClient?.updateInputs(
InputSettingsUpdate(
camera = CameraInputSettingsUpdate(
settings = VideoMediaTrackSettingsUpdate(
processor = videoProcessor
)
)
)
)
}

fun setAudioDevice(device: MediaDeviceInfo) {
if (Build.VERSION.SDK_INT >= 23) {
Log.i(TAG, "Setting audio device to $device")
Expand Down Expand Up @@ -225,6 +245,46 @@ class DemoCallService : Service(), ChatProtocol.ChatProtocolListener {
callClient?.stopScreenShare()
updateServiceState { it.with(newScreenShareActive = false) }
}

fun setCustomAudioTrack(freqHz: Int?) {

val call = callClient ?: return

if (freqHz == null) {
if (state.customAudioTrackFreqHz != null) {
call.removeCustomAudioTrack(CUSTOM_AUDIO_TRACK, ::notifyIfError)
}
} else {

val source = DemoSineWaveAudioSource(sineFreqHz = freqHz)

if (state.customAudioTrackFreqHz != null) {
call.updateCustomAudioTrack(CUSTOM_AUDIO_TRACK, source, ::notifyIfError)
} else {
call.addCustomAudioTrack(CUSTOM_AUDIO_TRACK, source, ::notifyIfError)
}

call.updatePublishing(
publishSettings = PublishingSettingsUpdate(
customAudio = mapOf(
CUSTOM_AUDIO_TRACK to CustomAudioTrackPublishingSettingsUpdate(
isPublishing = Enable()
)
)
)
)
}

updateServiceState { it.with(newCustomAudioTrackFreqHz = freqHz) }
}
}

private fun notifyIfError(result: RequestResult) {
result.error?.msg?.let(::notifyError)
}

private fun notifyError(msg: String) {
listeners.forEach { it.onError(msg) }
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Expand Down Expand Up @@ -302,8 +362,9 @@ class DemoCallService : Service(), ChatProtocol.ChatProtocolListener {
newInputs = DemoState.StreamsState(
cameraEnabled = inputSettings.camera.isEnabled,
micEnabled = inputSettings.microphone.isEnabled,
screenVideoEnabled = inputSettings.screenVideo.isEnabled
)
screenVideoEnabled = inputSettings.screenVideo.isEnabled,
),
newVideoProcessor = inputSettings.camera.settings.processor
)
}
}
Expand Down Expand Up @@ -460,6 +521,8 @@ class DemoCallService : Service(), ChatProtocol.ChatProtocolListener {
private fun setupParticipantSubscriptionProfiles(
callClient: CallClient
) {
val customAudio = mapOf(CUSTOM_AUDIO_TRACK to AudioSubscriptionSettingsUpdate(subscriptionState = Subscribed()))

callClient.updateSubscriptionProfiles(
mapOf(
profileActiveCamera to
Expand All @@ -472,7 +535,8 @@ class DemoCallService : Service(), ChatProtocol.ChatProtocolListener {
),
screenVideo = VideoSubscriptionSettingsUpdate(
subscriptionState = Unsubscribed()
)
),
customAudio = customAudio
),
profileActiveScreenShare to
SubscriptionProfileSettingsUpdate(
Expand All @@ -484,7 +548,8 @@ class DemoCallService : Service(), ChatProtocol.ChatProtocolListener {
receiveSettings = VideoReceiveSettingsUpdate(
maxQuality = VideoMaxQualityUpdate.high
)
)
),
customAudio = customAudio
),
SubscriptionProfile.base to
SubscriptionProfileSettingsUpdate(
Expand All @@ -493,7 +558,8 @@ class DemoCallService : Service(), ChatProtocol.ChatProtocolListener {
),
screenVideo = VideoSubscriptionSettingsUpdate(
subscriptionState = Unsubscribed()
)
),
customAudio = customAudio
)
)
)
Expand Down
Loading

0 comments on commit b65edde

Please sign in to comment.