Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shared video local participant #15086

Merged
merged 2 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ function MeetingParticipantItem({
</>
}

{!overflowDrawer && (_localVideoOwner || _participant?.fakeParticipant) && (
{!overflowDrawer && (_localVideoOwner && _participant?.fakeParticipant) && (
<ParticipantActionEllipsis
accessibilityLabel = { participantActionEllipsisLabel }
onClick = { onContextMenu } />
Expand Down
15 changes: 9 additions & 6 deletions react/features/shared-video/actions.any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from './actionTypes';
import { ShareVideoConfirmDialog, SharedVideoDialog } from './components';
import { PLAYBACK_START, PLAYBACK_STATUSES } from './constants';
import { isSharedVideoEnabled } from './functions';
import { isSharedVideoEnabled, sendShareVideoCommand } from './functions';


/**
Expand Down Expand Up @@ -120,12 +120,15 @@ export function playSharedVideo(videoUrl: string) {
if (conference) {
const localParticipant = getLocalParticipant(getState());

dispatch(setSharedVideoStatus({
videoUrl,
// we will send the command and will create local video fake participant
// and start playing once we receive ourselves the command
sendShareVideoCommand({
conference,
id: videoUrl,
localParticipantId: localParticipant?.id,
status: PLAYBACK_START,
time: 0,
ownerId: localParticipant?.id
}));
time: 0
});
}
};
}
Expand Down
28 changes: 28 additions & 0 deletions react/features/shared-video/functions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { IStateful } from '../base/app/types';
import { IJitsiConference } from '../base/conference/reducer';
import { getFakeParticipants } from '../base/participants/functions';
import { toState } from '../base/redux/functions';

import {
ALLOW_ALL_URL_DOMAINS,
PLAYBACK_START,
PLAYBACK_STATUSES,
SHARED_VIDEO,
VIDEO_PLAYER_PARTICIPANT_NAME,
YOUTUBE_PLAYER_PARTICIPANT_NAME,
YOUTUBE_URL_DOMAIN
Expand Down Expand Up @@ -146,3 +148,29 @@ export function isURLAllowedForSharedVideo(url: string,

return false;
}

/**
* Sends SHARED_VIDEO command.
*
* @param {string} id - The id of the video.
* @param {string} status - The status of the shared video.
* @param {JitsiConference} conference - The current conference.
* @param {string} localParticipantId - The id of the local participant.
* @param {string} time - The seek position of the video.
* @returns {void}
*/
export function sendShareVideoCommand({ id, status, conference, localParticipantId = '', time, muted, volume }: {
conference?: IJitsiConference; id: string; localParticipantId?: string; muted?: boolean;
status: string; time: number; volume?: number;
}) {
conference?.sendCommandOnce(SHARED_VIDEO, {
value: id,
attributes: {
from: localParticipantId,
muted,
state: status,
time,
volume
}
});
}
54 changes: 23 additions & 31 deletions react/features/shared-video/middleware.any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
SHARED_VIDEO,
VIDEO_PLAYER_PARTICIPANT_NAME
} from './constants';
import { isSharedVideoEnabled, isSharingStatus, isURLAllowedForSharedVideo } from './functions';
import { isSharedVideoEnabled, isSharingStatus, isURLAllowedForSharedVideo, sendShareVideoCommand } from './functions';
import logger from './logger';


Expand Down Expand Up @@ -155,6 +155,14 @@ MiddlewareRegistry.register(store => next => action => {
APP.API.notifyAudioOrVideoSharingToggled(MEDIA_TYPE.VIDEO, status, ownerId);
}

// when setting status we need to send the command for that, but not do it for the start command
// as we are sending the command in playSharedVideo and setting the start status once
// we receive the response, this way we will start the video at the same time when remote participants
// start it, on receiving the command
if (status === 'start') {
break;
}

if (localParticipantId === ownerId) {
sendShareVideoCommand({
conference,
Expand Down Expand Up @@ -224,12 +232,15 @@ function handleSharingVideoStatus(store: IStore, videoUrl: string,

if (oldVideoUrl && oldVideoUrl !== videoUrl) {
logger.warn(
`User with id: ${localParticipantId} sent videoUrl: ${videoUrl} while we are playing: ${oldVideoUrl}`);
`User with id: ${from} sent videoUrl: ${videoUrl} while we are playing: ${oldVideoUrl}`);

return;
}

if (state === PLAYBACK_START && !isSharingStatus(oldStatus)) {
// If the video was not started (no participant) we want to create the participant
// this can be triggered by start, but also by paused or playing
// commands (joining late) and getting the current state
if (state === PLAYBACK_START || !isSharingStatus(oldStatus)) {
const youtubeId = videoUrl.match(/http/) ? false : videoUrl;
const avatarURL = youtubeId ? `https://img.youtube.com/vi/${youtubeId}/0.jpg` : '';

Expand All @@ -242,6 +253,15 @@ function handleSharingVideoStatus(store: IStore, videoUrl: string,
}));

dispatch(pinParticipant(videoUrl));

if (localParticipantId === from) {
dispatch(setSharedVideoStatus({
videoUrl,
status: state,
time: Number(time),
ownerId: localParticipantId
}));
}
}

if (localParticipantId !== from) {
Expand All @@ -254,31 +274,3 @@ function handleSharingVideoStatus(store: IStore, videoUrl: string,
}));
}
}

/* eslint-disable max-params */

/**
* Sends SHARED_VIDEO command.
*
* @param {string} id - The id of the video.
* @param {string} status - The status of the shared video.
* @param {JitsiConference} conference - The current conference.
* @param {string} localParticipantId - The id of the local participant.
* @param {string} time - The seek position of the video.
* @returns {void}
*/
function sendShareVideoCommand({ id, status, conference, localParticipantId = '', time, muted, volume }: {
conference?: IJitsiConference; id: string; localParticipantId?: string; muted: boolean;
status: string; time: number; volume: number;
}) {
conference?.sendCommandOnce(SHARED_VIDEO, {
value: id,
attributes: {
from: localParticipantId,
muted,
state: status,
time,
volume
}
});
}