mirror of
https://github.com/vector-im/element-call.git
synced 2026-02-23 05:07:03 +00:00
review
This commit is contained in:
@@ -37,7 +37,7 @@ import {
|
||||
import { type Logger } from "matrix-js-sdk/lib/logger";
|
||||
import { deepCompare } from "matrix-js-sdk/lib/utils";
|
||||
|
||||
import { constant, type Behavior } from "../../Behavior.ts";
|
||||
import { type Behavior } from "../../Behavior.ts";
|
||||
import { type IConnectionManager } from "../remoteMembers/ConnectionManager.ts";
|
||||
import { type ObservableScope } from "../../ObservableScope.ts";
|
||||
import { type Publisher } from "./Publisher.ts";
|
||||
@@ -68,6 +68,8 @@ export enum TransportState {
|
||||
|
||||
export enum PublishState {
|
||||
WaitingForUser = "publish_waiting_for_user",
|
||||
// XXX: This state is removed for now since we do not have full control over
|
||||
// track publication anymore with the publisher abstraction, might come back in the future?
|
||||
// /** Implies lk connection is connected */
|
||||
// Starting = "publish_start_publishing",
|
||||
/** Implies lk connection is connected */
|
||||
@@ -79,6 +81,8 @@ export enum PublishState {
|
||||
export enum TrackState {
|
||||
/** The track is waiting for user input to create tracks (waiting to call `startTracks()`) */
|
||||
WaitingForUser = "tracks_waiting_for_user",
|
||||
// XXX: This state is removed for now since we do not have full control over
|
||||
// track creation anymore with the publisher abstraction, might come back in the future?
|
||||
// /** Implies lk connection is connected */
|
||||
// Creating = "tracks_creating",
|
||||
/** Implies lk connection is connected */
|
||||
@@ -154,9 +158,10 @@ export const createLocalMembership$ = ({
|
||||
matrixRTCSession,
|
||||
}: Props): {
|
||||
/**
|
||||
* This starts audio and video tracks. They will be reused when calling `requestPublish`.
|
||||
* This request to start audio and video tracks.
|
||||
* Can be called early to pre-emptively get media permissions and start devices.
|
||||
*/
|
||||
startTracks: () => Behavior<void>;
|
||||
startTracks: () => void;
|
||||
/**
|
||||
* This sets a inner state (shouldPublish) to true and instructs the js-sdk and livekit to keep the user
|
||||
* connected to matrix and livekit.
|
||||
@@ -265,19 +270,10 @@ export const createLocalMembership$ = ({
|
||||
* The publisher is stored in here an abstracts creating and publishing tracks.
|
||||
*/
|
||||
const publisher$ = new BehaviorSubject<Publisher | null>(null);
|
||||
/**
|
||||
* Extract the tracks from the published. Also reacts to changing publishers.
|
||||
*/
|
||||
// const tracks$ = scope.behavior(
|
||||
// publisher$.pipe(switchMap((p) => (p?.tracks$ ? p.tracks$ : constant([])))),
|
||||
// );
|
||||
// const publishing$ = scope.behavior(
|
||||
// publisher$.pipe(switchMap((p) => p?.publishing$ ?? constant(false))),
|
||||
// );
|
||||
|
||||
const startTracks = (): Behavior<void> => {
|
||||
const startTracks = (): void => {
|
||||
trackStartRequested.resolve();
|
||||
return constant(undefined);
|
||||
// This used to return the tracks, but now they are only accessible via the publisher.
|
||||
};
|
||||
|
||||
const requestJoinAndPublish = (): void => {
|
||||
@@ -348,14 +344,6 @@ export const createLocalMembership$ = ({
|
||||
setPublishError(new UnknownCallError(error as Error));
|
||||
}
|
||||
}
|
||||
// XXX Why is that?
|
||||
// else {
|
||||
// try {
|
||||
// await publisher?.stopPublishing();
|
||||
// } catch (error) {
|
||||
// setLivekitError(new UnknownCallError(error as Error));
|
||||
// }
|
||||
// }
|
||||
},
|
||||
);
|
||||
|
||||
@@ -401,16 +389,10 @@ export const createLocalMembership$ = ({
|
||||
([
|
||||
localConnectionState,
|
||||
localTransport,
|
||||
// tracks,
|
||||
// publishing,
|
||||
shouldPublish,
|
||||
shouldStartTracks,
|
||||
]) => {
|
||||
if (!localTransport) return null;
|
||||
// const hasTracks = tracks.length > 0;
|
||||
// let trackState: TrackState = TrackState.WaitingForUser;
|
||||
// if (hasTracks && shouldStartTracks) trackState = TrackState.Ready;
|
||||
// if (!hasTracks && shouldStartTracks) trackState = TrackState.Creating;
|
||||
const trackState: TrackState = shouldStartTracks
|
||||
? TrackState.Ready
|
||||
: TrackState.WaitingForUser;
|
||||
|
||||
@@ -34,7 +34,7 @@ beforeEach(() => {
|
||||
scope = new ObservableScope();
|
||||
});
|
||||
|
||||
// afterEach(() => scope.end());
|
||||
afterEach(() => scope.end());
|
||||
|
||||
function createMockLocalTrack(source: Track.Source): LocalTrack {
|
||||
const track = {
|
||||
|
||||
@@ -97,7 +97,7 @@ export class Publisher {
|
||||
// it would also prevent the user from seeing their own video/audio preview.
|
||||
// So for that we use pauseUpStream(): Stops sending media to the server by replacing
|
||||
// the sender track with null, but keeps the local MediaStreamTrack active.
|
||||
// The user can still see/hear themselves locally, but remote participants see nothing
|
||||
// The user can still see/hear themselves locally, but remote participants see nothing.
|
||||
private onLocalTrackPublished(
|
||||
localTrackPublication: LocalTrackPublication,
|
||||
): void {
|
||||
@@ -128,6 +128,15 @@ export class Publisher {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create and setup local audio and video tracks based on the current mute states.
|
||||
* It creates the tracks only if audio and/or video is enabled, to avoid unnecessary
|
||||
* permission prompts.
|
||||
*
|
||||
* It also observes mute state changes to update LiveKit microphone/camera states accordingly.
|
||||
* If a track is not created initially because disabled, it will be created when unmuting.
|
||||
*
|
||||
* This call is not blocking anymore, instead callers can listen to the
|
||||
* `RoomEvent.MediaDevicesError` event in the LiveKit room to be notified of any errors.
|
||||
*
|
||||
*/
|
||||
public async createAndSetupTracks(): Promise<void> {
|
||||
@@ -141,25 +150,21 @@ export class Publisher {
|
||||
const audio = this.muteStates.audio.enabled$.value;
|
||||
const video = this.muteStates.video.enabled$.value;
|
||||
|
||||
const enableTracks = async (): Promise<void> => {
|
||||
if (audio && video) {
|
||||
// Enable both at once in order to have a single permission prompt!
|
||||
await lkRoom.localParticipant.enableCameraAndMicrophone();
|
||||
} else if (audio) {
|
||||
await lkRoom.localParticipant.setMicrophoneEnabled(true);
|
||||
} else if (video) {
|
||||
await lkRoom.localParticipant.setCameraEnabled(true);
|
||||
}
|
||||
return;
|
||||
};
|
||||
// We don't await enableTracks, because livekit could block until the tracks
|
||||
// We don't await the creation, because livekit could block until the tracks
|
||||
// are fully published, and not only that they are created.
|
||||
// We don't have control on that, localParticipant creates and publishes the tracks
|
||||
// asap.
|
||||
// We are using the `ParticipantEvent.LocalTrackPublished` to be notified
|
||||
// when tracks are actually published, and at that point
|
||||
// we can pause upstream if needed (depending on if startPublishing has been called).
|
||||
void enableTracks();
|
||||
if (audio && video) {
|
||||
// Enable both at once in order to have a single permission prompt!
|
||||
void lkRoom.localParticipant.enableCameraAndMicrophone();
|
||||
} else if (audio) {
|
||||
void lkRoom.localParticipant.setMicrophoneEnabled(true);
|
||||
} else if (video) {
|
||||
void lkRoom.localParticipant.setCameraEnabled(true);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -233,6 +238,8 @@ export class Publisher {
|
||||
public async stopPublishing(): Promise<void> {
|
||||
this.logger.debug("stopPublishing called");
|
||||
this.shouldPublish = false;
|
||||
// Pause upstream will stop sending media to the server, while keeping
|
||||
// the local MediaStreamTrack active, so the user can still see themselves.
|
||||
await this.pauseUpstreams(this.connection.livekitRoom, [
|
||||
Track.Source.Microphone,
|
||||
Track.Source.Camera,
|
||||
|
||||
Reference in New Issue
Block a user