[SDK] split the clint object into -> slot and participation

This commit is contained in:
Timo K.
2026-10-08 13:53:57 +02:00
parent 9cc9eb0889
commit dc983e5493
17 changed files with 653 additions and 415 deletions
@@ -23,11 +23,12 @@ import {
switchMap,
} from "rxjs";
import { type ResolvedTransport, type RTCMembership } from "../../api";
import { type ResolvedTransport, type RTCMember } from "../../api";
import { type MediaQuality } from "../../config";
import { MatrixRTCError } from "../../errors";
import { type Behavior } from "../../reactive/Behavior";
import { type MemberMedia } from "../../media-api";
import {
type Epoch,
type ObservableScope,
@@ -37,7 +38,6 @@ import {
type BackendConnection,
type MediaBackend,
type MediaBackendContext,
type MemberMediaFields,
type TransportCapabilities,
} from "../api";
import { type Connection } from "./Connection";
@@ -147,14 +147,14 @@ export function createLivekitBackend(
);
};
const mediaFor$ = (
const mediaFor = (
memberScope: ObservableScope,
membership$: Behavior<RTCMembership>,
): MemberMediaFields => {
const identity = membership$.value.rtcBackendIdentity;
member: RTCMember,
): MemberMedia => {
const identity = member.rtcBackendIdentity;
const transport$ = memberScope.behavior(
membership$.pipe(
map((membership) => membership.getTransport()),
member.transport$.pipe(
map((transport) => transport?.raw),
map((transport) =>
isLivekitTransport(transport) ? transport : undefined,
),
@@ -224,7 +224,7 @@ export function createLivekitBackend(
prepareLocalTransport,
delegateDelayedLeave,
local: localMedia_,
mediaFor$,
mediaFor,
connections$,
setAudioOutputDeviceId: localMedia_.setAudioOutputDeviceId,
sendData,
@@ -23,8 +23,12 @@ import { generateItems } from "../../reactive/observable";
import { E2eeType, type EncryptionSystem } from "../../encryption";
import { type Behavior } from "../../reactive/Behavior";
import { mapScoped } from "../../utils/mapScoped";
import { type EncryptionError, type MediaSource } from "../../media-api";
import { type LocalMemberMediaFields, type MemberMediaFields } from "../api";
import {
type EncryptionError,
type LocalMemberMedia,
type MediaSource,
type MemberMedia,
} from "../../media-api";
import {
createLivekitMediaTrack,
createLocalLivekitMediaTrack,
@@ -45,7 +49,7 @@ export function createLivekitMemberMedia(
scope: ObservableScope,
source$: Behavior<ParticipantSource>,
encryptionSystem: EncryptionSystem,
): MemberMediaFields {
): MemberMedia {
return {
tracks$: memberTracks$(
scope,
@@ -62,7 +66,7 @@ export function createLocalLivekitMemberMedia(
source$: Behavior<ParticipantSource<LocalParticipant>>,
encryptionSystem: EncryptionSystem,
setEnabled: (source: MediaSource, enabled: boolean) => Promise<boolean>,
): LocalMemberMediaFields {
): LocalMemberMedia {
return {
tracks$: memberTracks$(
scope,
+19 -8
View File
@@ -191,14 +191,11 @@ export function createLivekitLocalMedia({
}
};
const unpublish = async (id: string): Promise<void> => {
const track = tracks$.value?.find((t) => t.id === id);
if (track === undefined) return;
// The screen share audio goes with its video
const source =
track.source === "screenShareAudio" ? "screenShare" : track.source;
desired.delete(source);
await publisher$.value?.unpublish(source);
const unpublish = async (source: MediaSource): Promise<void> => {
const published = publishedSource(source);
if (published === undefined) return;
desired.delete(published);
await publisher$.value?.unpublish(published);
};
const setAudioOutputDeviceId = async (deviceId: string): Promise<void> => {
@@ -268,3 +265,17 @@ function trackWithId$(
filter((track) => track !== undefined),
);
}
/** The publication a source belongs to: the screen share audio goes with its video. */
function publishedSource(
source: MediaSource,
): PublishRequest["source"] | undefined {
switch (source) {
case "screenShareAudio":
return "screenShare";
case "unknown":
return undefined;
default:
return source;
}
}