Skip to content
This repository was archived by the owner on Jun 28, 2024. It is now read-only.

Event emitters #73

Merged
merged 7 commits into from
May 15, 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
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nodejs 18.14.2
nodejs v20.13.1
27 changes: 14 additions & 13 deletions examples/minimal-react/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions examples/minimal-react/src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import VideoPlayer from "./VideoPlayer";
import { JellyfishClient, SCREEN_SHARING_MEDIA_CONSTRAINTS } from "@jellyfish-dev/react-client-sdk";
import { SCREEN_SHARING_MEDIA_CONSTRAINTS, Client } from "@jellyfish-dev/react-client-sdk";
import { useState } from "react";
import { useConnect, useDisconnect, useApi, useStatus, useTracks, useSelector } from "./client";
import { useConnect, useDisconnect, useClient, useStatus, useTracks } from "./client";

// Example metadata types for peer and track
// You can define your own metadata types just make sure they are serializable
Expand All @@ -18,14 +18,14 @@ export const App = () => {

const connect = useConnect();
const disconnect = useDisconnect();
const api = useApi();
const client = useClient();
const status = useStatus();
const tracks = useTracks();

{
// for e2e test
const client = useSelector((s) => s.connectivity.client);
(window as unknown as { client: JellyfishClient<PeerMetadata, TrackMetadata> }).client = client!;
const client = useClient();
(window as unknown as { client: Client<PeerMetadata, TrackMetadata> }).client = client!;
}

return (
Expand Down Expand Up @@ -58,7 +58,7 @@ export const App = () => {
// Get screen sharing MediaStream
navigator.mediaDevices.getDisplayMedia(SCREEN_SHARING_MEDIA_CONSTRAINTS).then((screenStream) => {
// Add local MediaStream to webrtc
screenStream.getTracks().forEach((track) => api.addTrack(track, screenStream, { type: "screen" }));
screenStream.getTracks().forEach((track) => client.addTrack(track, screenStream, { type: "screen" }));
});
}}
>
Expand Down
2 changes: 1 addition & 1 deletion examples/minimal-react/src/components/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import { PeerMetadata, TrackMetadata } from "./App";

// Create a Membrane client instance
// remember to use JellyfishContextProvider
export const { useApi, useTracks, useStatus, useConnect, useDisconnect, useSelector, JellyfishContextProvider } =
export const { useClient, useTracks, useStatus, useConnect, useDisconnect, useSelector, JellyfishContextProvider } =
create<PeerMetadata, TrackMetadata>();
27 changes: 14 additions & 13 deletions examples/use-camera-and-microphone-example/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export const AdditionalControls = () => {
<h3>Local:</h3>
<div className="max-w-[500px]">
{camera?.track?.kind === "video" && <VideoPlayer stream={camera?.stream} />}
{microphone?.track?.kind === "audio" && <AudioVisualizer stream={microphone?.stream} />}
{microphone?.track?.kind === "audio" && (
<AudioVisualizer stream={microphone?.stream} trackId={microphone?.track.id} />
)}
</div>
</div>
</div>
Expand Down
15 changes: 11 additions & 4 deletions examples/use-camera-and-microphone-example/src/AudioVisualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { useEffect, useRef, useState } from "react";

type Props = {
stream: MediaStream | null | undefined;
trackId: string | null;
};

export const AudioVisualizer = ({ stream }: Props) => {
export const AudioVisualizer = ({ stream, trackId }: Props) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const canvasParentRef = useRef<HTMLDivElement>(null);
const idRef = useRef<number | null>(null);
const [canvasWidth, setCanvasWidth] = useState<number>(400);

useEffect(() => {
Expand Down Expand Up @@ -34,9 +36,10 @@ export const AudioVisualizer = ({ stream }: Props) => {
const dataArray = new Uint8Array(bufferLength);

function renderFrame() {
const id = requestAnimationFrame(renderFrame);
idRef.current = requestAnimationFrame(renderFrame);

if (!canvasRef.current) {
cancelAnimationFrame(id);
cancelAnimationFrame(idRef.current);
return;
}

Expand All @@ -58,7 +61,11 @@ export const AudioVisualizer = ({ stream }: Props) => {
}

renderFrame();
}, [stream]);

return () => {
idRef.current && cancelAnimationFrame(idRef.current);
};
}, [stream, trackId]);

return (
<div ref={canvasParentRef} className="flex flex-row flex-nowrap justify-center border-4">
Expand Down
30 changes: 17 additions & 13 deletions examples/use-camera-and-microphone-example/src/DeviceControls.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { PeerStatus, UseScreenshareResult } from "@jellyfish-dev/react-client-sdk";
import { UseMicrophoneResult, UseCameraResult } from "@jellyfish-dev/react-client-sdk";
import {
PeerStatus,
UseMicrophoneResult,
UseCameraResult,
UseScreenShareResult,
} from "@jellyfish-dev/react-client-sdk";
import { TrackMetadata } from "./jellyfishSetup";

type DeviceControlsProps = {
Expand All @@ -15,7 +19,7 @@ type DeviceControlsProps = {
type: "video";
}
| {
device: UseScreenshareResult<TrackMetadata>;
device: UseScreenShareResult<TrackMetadata>;
type: "screenshare";
}
);
Expand All @@ -25,36 +29,36 @@ export const DeviceControls = ({ device, type, status, metadata }: DeviceControl
<div className="flex flex-col gap-2">
<button
className="btn btn-success btn-sm"
disabled={!!device.stream}
disabled={!!device?.stream}
onClick={() => {
device.start();
device?.start();
}}
>
Start {type} device
</button>
<button
className="btn btn-error btn-sm"
disabled={!device.stream}
disabled={!device?.stream}
onClick={() => {
device.stop();
device?.stop();
}}
>
Stop {type} device
</button>
<button
className="btn btn-success btn-sm"
disabled={!device.stream || device.enabled}
disabled={!device?.stream || device?.enabled}
onClick={() => {
device.setEnable(true);
device?.setEnable(true);
}}
>
Enable {type} track
</button>
<button
className="btn btn-error btn-sm"
disabled={!device.enabled}
disabled={!device?.enabled}
onClick={() => {
device.setEnable(false);
device?.setEnable(false);
}}
>
Disable {type} track
Expand All @@ -63,7 +67,7 @@ export const DeviceControls = ({ device, type, status, metadata }: DeviceControl
className="btn btn-success btn-sm"
disabled={status !== "joined" || !device?.stream || !!device?.broadcast?.trackId}
onClick={() => {
device.addTrack(metadata);
device?.addTrack(metadata);
}}
>
Stream {type} track
Expand All @@ -72,7 +76,7 @@ export const DeviceControls = ({ device, type, status, metadata }: DeviceControl
className="btn btn-error btn-sm"
disabled={status !== "joined" || !device?.stream || !device?.broadcast?.trackId}
onClick={() => {
device.removeTrack();
device?.removeTrack();
}}
>
Stop {type} track stream
Expand Down
47 changes: 26 additions & 21 deletions examples/use-camera-and-microphone-example/src/DeviceSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,41 @@ type Props = {
defaultOptionText: string;
devices: MediaDeviceInfo[] | null;
setInput: (value: string | null) => void;
// inputValue: string | null;
activeDevice: string | null;
};

export const DeviceSelector = ({ name, devices, setInput, defaultOptionText }: Props) => {
export const DeviceSelector = ({ name, devices, setInput, defaultOptionText, activeDevice }: Props) => {
const [selectedDevice, setSelectedDevice] = useState<string | null>(null);

const onOptionChangeHandler = (event: ChangeEvent<HTMLSelectElement>) => {
setSelectedDevice(event?.target?.value);
};

return (
<div className="flex flex-row items-center gap-2">
<span>{name}</span>
<select className="select w-full max-w-xs" onChange={onOptionChangeHandler} defaultValue={defaultOptionText}>
<option disabled>{defaultOptionText}</option>
{(devices || []).map(({ deviceId, label }) => (
<option key={deviceId} value={deviceId}>
{label}
</option>
))}
</select>
<button
className="btn btn-error btn-sm"
disabled={!selectedDevice}
onClick={() => {
setInput(selectedDevice);
}}
>
Change device!
</button>
<div className="flex flex-col gap-2">
<div className="flex flex-row">
<span>Selected: {activeDevice}</span>
</div>
<div className="flex flex-row items-center gap-2">
<span>{name}</span>
<select className="select w-full max-w-xs" onChange={onOptionChangeHandler} defaultValue={defaultOptionText}>
<option disabled>{defaultOptionText}</option>
{(devices || []).map(({ deviceId, label }) => (
<option key={deviceId} value={deviceId}>
{label}
</option>
))}
</select>
<button
className="btn btn-error btn-sm"
disabled={!selectedDevice}
onClick={() => {
setInput(selectedDevice);
}}
>
Change device!
</button>
</div>
</div>
);
};
Loading
Loading