changes summary valere timo
This commit is contained in:
@@ -19,10 +19,21 @@ import {
|
|||||||
SyncState,
|
SyncState,
|
||||||
type Room as MatrixRoom,
|
type Room as MatrixRoom,
|
||||||
} from "matrix-js-sdk";
|
} from "matrix-js-sdk";
|
||||||
import { fromEvent, map, type Observable, scan, startWith } from "rxjs";
|
import {
|
||||||
|
BehaviorSubject,
|
||||||
|
combineLatest,
|
||||||
|
from,
|
||||||
|
fromEvent,
|
||||||
|
map,
|
||||||
|
type Observable,
|
||||||
|
of,
|
||||||
|
scan,
|
||||||
|
startWith,
|
||||||
|
switchMap,
|
||||||
|
} from "rxjs";
|
||||||
import { multiSfu } from "../../settings/settings";
|
import { multiSfu } from "../../settings/settings";
|
||||||
import { type Behavior } from "../Behavior";
|
import { type Behavior } from "../Behavior";
|
||||||
import { type ConnectionManager } from "../remoteMembers/ConnectionManager";
|
import { ConnectionManager } from "../remoteMembers/ConnectionManager";
|
||||||
import { makeTransport } from "../../rtcSessionHelpers";
|
import { makeTransport } from "../../rtcSessionHelpers";
|
||||||
import { type ObservableScope } from "../ObservableScope";
|
import { type ObservableScope } from "../ObservableScope";
|
||||||
import { async$, unwrapAsync } from "../Async";
|
import { async$, unwrapAsync } from "../Async";
|
||||||
@@ -31,7 +42,19 @@ import { type MuteStates } from "../MuteStates";
|
|||||||
import { type ProcessorState } from "../../livekit/TrackProcessorContext";
|
import { type ProcessorState } from "../../livekit/TrackProcessorContext";
|
||||||
import { type MediaDevices } from "../../state/MediaDevices";
|
import { type MediaDevices } from "../../state/MediaDevices";
|
||||||
import { and$ } from "../../utils/observable";
|
import { and$ } from "../../utils/observable";
|
||||||
|
import { areLivekitTransportsEqual } from "../remoteMembers/matrixLivekitMerger";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* - get well known
|
||||||
|
* - get oldest membership
|
||||||
|
* - get transport to use
|
||||||
|
* - get openId + jwt token
|
||||||
|
* - wait for createTrack() call
|
||||||
|
* - create tracks
|
||||||
|
* - wait for join() call
|
||||||
|
* - Publisher.publishTracks()
|
||||||
|
* - send join state/sticky event
|
||||||
|
*/
|
||||||
interface Props {
|
interface Props {
|
||||||
scope: ObservableScope;
|
scope: ObservableScope;
|
||||||
mediaDevices: MediaDevices;
|
mediaDevices: MediaDevices;
|
||||||
@@ -71,10 +94,18 @@ export const ownMembership$ = ({
|
|||||||
roomId,
|
roomId,
|
||||||
trackerProcessorState$,
|
trackerProcessorState$,
|
||||||
}: Props): {
|
}: Props): {
|
||||||
connected$: Behavior<boolean>;
|
// publisher: Publisher
|
||||||
transport$: Behavior<LivekitTransport | null>;
|
requestJoin(): Observable<JoinedStateWithErrors>;
|
||||||
publisher: Publisher;
|
startTracks(): Track[];
|
||||||
} => {
|
} => {
|
||||||
|
// This should be used in a combineLatest with publisher$ to connect.
|
||||||
|
const shouldStartTracks$ = BehaviorSubject(false);
|
||||||
|
|
||||||
|
// to make it possible to call startTracks before the preferredTransport$ has resolved.
|
||||||
|
const startTracks = () => {
|
||||||
|
shouldStartTracks$.next(true);
|
||||||
|
};
|
||||||
|
|
||||||
const userId = client.getUserId()!;
|
const userId = client.getUserId()!;
|
||||||
const deviceId = client.getDeviceId()!;
|
const deviceId = client.getDeviceId()!;
|
||||||
const multiSfu$ = multiSfu.value$;
|
const multiSfu$ = multiSfu.value$;
|
||||||
@@ -82,22 +113,23 @@ export const ownMembership$ = ({
|
|||||||
* The transport that we would personally prefer to publish on (if not for the
|
* The transport that we would personally prefer to publish on (if not for the
|
||||||
* transport preferences of others, perhaps).
|
* transport preferences of others, perhaps).
|
||||||
*/
|
*/
|
||||||
const preferredTransport$ = scope.behavior(
|
const preferredTransport$: Behavior<LivekitTransport> = scope.behavior(
|
||||||
async$(makeTransport(client, roomId)).pipe(
|
from(makeTransport(client, roomId)),
|
||||||
map(unwrapAsync<LivekitTransport | null>(null)),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const connection = connectionManager.registerTransports(
|
connectionManager.registerTransports(
|
||||||
scope.behavior(preferredTransport$.pipe(map((t) => (t ? [t] : [])))),
|
scope.behavior(preferredTransport$.pipe(map((t) => (t ? [t] : [])))),
|
||||||
)[0];
|
);
|
||||||
if (!connection) {
|
|
||||||
logger.warn(
|
|
||||||
"No connection found when passing transport to connectionManager. transport:",
|
|
||||||
preferredTransport$.value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const connection$ = scope.behavior(
|
||||||
|
combineLatest([connectionManager.connections$, preferredTransport$]).pipe(
|
||||||
|
map(([connections, transport]) =>
|
||||||
|
connections.find((connection) =>
|
||||||
|
areLivekitTransportsEqual(connection.transport, transport),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
/**
|
/**
|
||||||
* Whether we are connected to the MatrixRTC session.
|
* Whether we are connected to the MatrixRTC session.
|
||||||
*/
|
*/
|
||||||
@@ -129,6 +161,7 @@ export const ownMembership$ = ({
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether we are "fully" connected to the call. Accounts for both the
|
* Whether we are "fully" connected to the call. Accounts for both the
|
||||||
* connection to the MatrixRTC session and the LiveKit publish connection.
|
* connection to the MatrixRTC session and the LiveKit publish connection.
|
||||||
@@ -136,19 +169,31 @@ export const ownMembership$ = ({
|
|||||||
const connected$ = scope.behavior(
|
const connected$ = scope.behavior(
|
||||||
and$(
|
and$(
|
||||||
matrixConnected$,
|
matrixConnected$,
|
||||||
connection.state$.pipe(
|
connection$.pipe(
|
||||||
map((state) => state.state === "ConnectedToLkRoom"),
|
switchMap((c) =>
|
||||||
|
c
|
||||||
|
? c.state$.pipe(map((state) => state.state === "ConnectedToLkRoom"))
|
||||||
|
: of(false),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const publisher = new Publisher(
|
const publisher = scope.behavior(
|
||||||
scope,
|
connection$.pipe(
|
||||||
connection,
|
map((c) =>
|
||||||
mediaDevices,
|
c
|
||||||
muteStates,
|
? new Publisher(
|
||||||
e2eeLivekitOptions,
|
scope,
|
||||||
trackerProcessorState$,
|
c,
|
||||||
|
mediaDevices,
|
||||||
|
muteStates,
|
||||||
|
e2eeLivekitOptions,
|
||||||
|
trackerProcessorState$,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// HOW IT WAS PREVIEOUSLY CREATED
|
// HOW IT WAS PREVIEOUSLY CREATED
|
||||||
@@ -171,11 +216,11 @@ export const ownMembership$ = ({
|
|||||||
* null when not joined.
|
* null when not joined.
|
||||||
*/
|
*/
|
||||||
// DISCUSSION ownMembershipManager
|
// DISCUSSION ownMembershipManager
|
||||||
const localTransport$: Behavior<Async<LivekitTransport> | null> =
|
const localTransport$: Behavior<LivekitTransport | null> =
|
||||||
this.scope.behavior(
|
this.scope.behavior(
|
||||||
this.transports$.pipe(
|
this.transports$.pipe(
|
||||||
map((transports) => transports?.local ?? null),
|
map((transports) => transports?.local ?? null),
|
||||||
distinctUntilChanged<Async<LivekitTransport> | null>(deepCompare),
|
distinctUntilChanged<LivekitTransport | null>(deepCompare),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export class ConnectionManager {
|
|||||||
/**
|
/**
|
||||||
* Connections for each transport in use by one or more session members.
|
* Connections for each transport in use by one or more session members.
|
||||||
*/
|
*/
|
||||||
private readonly connections$ = this.scope.behavior(
|
public readonly connections$ = this.scope.behavior(
|
||||||
generateKeyed$<LivekitTransport[], Connection, Connection[]>(
|
generateKeyed$<LivekitTransport[], Connection, Connection[]>(
|
||||||
this.transports$,
|
this.transports$,
|
||||||
(transports, createOrGet) => {
|
(transports, createOrGet) => {
|
||||||
@@ -144,22 +144,20 @@ export class ConnectionManager {
|
|||||||
* the same `transports$` behavior reference.
|
* the same `transports$` behavior reference.
|
||||||
* @param transports$ The Behavior containing a list of transports to subscribe to.
|
* @param transports$ The Behavior containing a list of transports to subscribe to.
|
||||||
*/
|
*/
|
||||||
public registerTransports(
|
public registerTransports(transports$: Behavior<LivekitTransport[]>): void {
|
||||||
transports$: Behavior<LivekitTransport[]>,
|
|
||||||
): Connection[] {
|
|
||||||
if (!this.transportsSubscriptions$.value.some((t$) => t$ === transports$)) {
|
if (!this.transportsSubscriptions$.value.some((t$) => t$ === transports$)) {
|
||||||
this.transportsSubscriptions$.next(
|
this.transportsSubscriptions$.next(
|
||||||
this.transportsSubscriptions$.value.concat(transports$),
|
this.transportsSubscriptions$.value.concat(transports$),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// After updating the subscriptions our connection list is also updated.
|
// // After updating the subscriptions our connection list is also updated.
|
||||||
return transports$.value
|
// return transports$.value
|
||||||
.map((transport) => {
|
// .map((transport) => {
|
||||||
const isConnectionForTransport = (connection: Connection): boolean =>
|
// const isConnectionForTransport = (connection: Connection): boolean =>
|
||||||
areLivekitTransportsEqual(connection.transport, transport);
|
// areLivekitTransportsEqual(connection.transport, transport);
|
||||||
return this.connections$.value.find(isConnectionForTransport);
|
// return this.connections$.value.find(isConnectionForTransport);
|
||||||
})
|
// })
|
||||||
.filter((c) => c !== undefined);
|
// .filter((c) => c !== undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,7 +216,7 @@ export class ConnectionManager {
|
|||||||
* Each participant that is found on all connections managed by the manager will be listed.
|
* Each participant that is found on all connections managed by the manager will be listed.
|
||||||
*
|
*
|
||||||
* They are stored an a map keyed by `participant.identity`
|
* They are stored an a map keyed by `participant.identity`
|
||||||
* (which is equivalent to the `member.id` field in the `m.rtc.member` event)
|
* TODO (which is equivalent to the `member.id` field in the `m.rtc.member` event) right now its userId:deviceId
|
||||||
*/
|
*/
|
||||||
public allParticipantsByMemberId$ = this.scope.behavior(
|
public allParticipantsByMemberId$ = this.scope.behavior(
|
||||||
this.allParticipantsWithConnection$.pipe(
|
this.allParticipantsWithConnection$.pipe(
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ export class MatrixLivekitMerger {
|
|||||||
const items: MatrixLivekitItem[] = memberships.map(
|
const items: MatrixLivekitItem[] = memberships.map(
|
||||||
({ membership, transport }) => {
|
({ membership, transport }) => {
|
||||||
const participantsWithConnection = participantsByMemberId.get(
|
const participantsWithConnection = participantsByMemberId.get(
|
||||||
membership.membershipID,
|
// membership.membershipID, Currently its hardcoded by the jwt service to
|
||||||
|
`${membership.userId}:${membership.deviceId}`,
|
||||||
);
|
);
|
||||||
const participant =
|
const participant =
|
||||||
transport &&
|
transport &&
|
||||||
|
|||||||
Reference in New Issue
Block a user