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

fix(web): obtain media device label #10

Merged
merged 10 commits into from
Nov 5, 2024
3 changes: 2 additions & 1 deletion .github/CLA.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ Example:
-->

- Metal A-wing, @a-wing, 2024/10/23
- Hongcha Zhang, @hongcha98, 2024/10/24
- Hongcha Zhang, @hongcha98, 2024/10/24
- Winter Zhang, @WinterJack002, 2024/10/26
79 changes: 68 additions & 11 deletions webapp/components/device.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,40 @@ import SvgAudio from './svg/audio'
import SvgVideo from './svg/video'
import { SvgPresentCancel, SvgPresentToAll } from './svg/present'

// 1. Converts each device's deviceId and label into a displayable format. If label is empty, uses the device type and deviceId as the display name.
function deviceInfoToOption(info: MediaDeviceInfo) {
const value = info.deviceId;
let text = info.label;
if (text.length <= 0) {
text = `${info.kind} (${info.deviceId})`;
}
return { value, text };
}

// 2. Removes duplicate items based on their value.
function uniqByValue<T extends { value: unknown }>(items: T[]) {
const map = new Map<unknown, T>();
for (const item of items) {
if (!map.has(item.value)) {
map.set(item.value, item);
}
}
return Array.from(map.values());
}

// 3. Converts items to Device format
const convertToDevice = (items: { value: string; text: string }[], kind: MediaDeviceKind): MediaDeviceInfo[] => {
return items.map(item => ({
deviceId: item.value, // use value as the device ID
kind,
label: item.text, // use text as the label
groupId: '',

})as MediaDeviceInfo);
}

export default function DeviceBar(props: { streamId: string }) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This blank line is unused

const [permissionAudio, setPermissionAudio] = useState("")
const [permissionVideo, setPermissionVideo] = useState("")

Expand Down Expand Up @@ -48,31 +81,55 @@ export default function DeviceBar(props: { streamId: string }) {
// NOTE:
// Chrome: audio_capture, video_capture
// Safari: microphone, camera
if (status.name === "audio_capture" || "microphone") {
if (status.name === "audio_capture" || status.name === "microphone") {
setPermissionAudio(status.state)
}
if (status.name === "video_capture" || "camera") {
if (status.name === "video_capture" || status.name === "camera") {
setPermissionVideo(status.state)
}
})

const updateDeviceList = async () => {
const devices = (await navigator.mediaDevices.enumerateDevices()).filter(i => !!i.deviceId)
const audios: Device[] = devices.filter(i => i.kind === 'audioinput')
const videos: Device[] = devices.filter(i => i.kind === 'videoinput')
const audios = devices.filter(i => i.kind === 'audioinput').map(deviceInfoToOption)
const videos = devices.filter(i => i.kind === 'videoinput').map(deviceInfoToOption);

const uniqueAudios = uniqByValue(audios);
const uniqueVideos = uniqByValue(videos);

if (currentDeviceAudio === deviceNone.deviceId) {
let device = audios[0]
if (device) await setCurrentDeviceAudio(device.deviceId)
let device = uniqueAudios[0]
if (device)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (device) {

try {
await setCurrentDeviceAudio(device.value)
console.log('Audio device set successfully')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this log

} catch (error) {
console.error('Failed to set audio device:', error)
}
}

}

if (currentDeviceVideo === deviceNone.deviceId) {
let device = videos[0]
if (device) await setCurrentDeviceVideo(device.deviceId)
let device = uniqueVideos[0]
if (device) {
try {
await setCurrentDeviceVideo(device.value)
console.log('Video device set successfully')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

        try {
          await setCurrentDeviceVideo(device.value)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this successfully log

} catch (error) {
console.error('Failed to set video device:', error)
}
} else {
console.log('no video devices:')
await setCurrentDeviceVideo(deviceNone.deviceId)

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block indent style error

}

setDeviceAudio([...audios])
setDeviceVideo([...videos, deviceScreen])
setDeviceAudio(convertToDevice(uniqueAudios,'audioinput'))
setDeviceVideo(convertToDevice(uniqueVideos,'videoinput'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

convertToDevice(uniqueVideos, 'videoinput')

, after add a


}

const init = async () => {
Expand Down Expand Up @@ -181,7 +238,7 @@ export default function DeviceBar(props: { streamId: string }) {
onChange={e => onChangedDeviceVideo(e.target.value)}
>
{deviceVideo.map(device =>
<option key={device.deviceId} value={device.deviceId}>{device.label}</option>
<option key={device.label} value={device.label}>{device.label}</option>
)}
</select>
</section>
Expand Down