Skip to content

Commit

Permalink
デバイス初期化
Browse files Browse the repository at this point in the history
  • Loading branch information
voluntas committed Jan 3, 2025
1 parent 1ea46ec commit c8b38c0
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 0 deletions.
55 changes: 55 additions & 0 deletions devtools/src/components/AudioInputDevice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type React from 'react'
import { useEffect, useState } from 'react'
import { useSettingsStore } from '../store/useSettingsStore'

const AudioInputDevice: React.FC = () => {
const [devices, setDevices] = useState<MediaDeviceInfo[]>([])
const setAudioInputDeviceId = useSettingsStore((state) => state.setAudioInputDeviceId)
const audioInputDeviceId = useSettingsStore((state) => state.settings.audio.inputDeviceId)

useEffect(() => {
const getDevices = async () => {
const permissionStatus = await navigator.permissions.query({
name: 'microphone' as PermissionName,
})

const handlePermissionChange = async () => {
if (permissionStatus.state === 'granted') {
const devices = await navigator.mediaDevices.enumerateDevices()
const audioInputDevices = devices.filter((device) => device.kind === 'audioinput')
setDevices(audioInputDevices)
} else {
setDevices([])
}
}

// 初期状態の処理
handlePermissionChange()

// 権限変更の監視
permissionStatus.onchange = handlePermissionChange

return () => {
// ククリーンアップ
permissionStatus.onchange = null
}
}
getDevices()
}, [])

const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setAudioInputDeviceId(e.target.value)
}

return (
<select onChange={handleChange} value={audioInputDeviceId}>
{devices.map((device) => (
<option key={device.deviceId} value={device.deviceId}>
{device.label || `Microphone ${device.deviceId}`}
</option>
))}
</select>
)
}

export default AudioInputDevice
55 changes: 55 additions & 0 deletions devtools/src/components/AudioOutputDevice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type React from 'react'
import { useEffect, useState } from 'react'
import { useSettingsStore } from '../store/useSettingsStore'

const AudioOutputDevice: React.FC = () => {
const [devices, setDevices] = useState<MediaDeviceInfo[]>([])
const setAudioOutputDeviceId = useSettingsStore((state) => state.setAudioOutputDeviceId)
const audioOutputDeviceId = useSettingsStore((state) => state.settings.audio.outputDeviceId)

useEffect(() => {
const getDevices = async () => {
const permissionStatus = await navigator.permissions.query({
name: 'microphone' as PermissionName,
})

const handlePermissionChange = async () => {
if (permissionStatus.state === 'granted') {
const devices = await navigator.mediaDevices.enumerateDevices()
const audioOutputDevices = devices.filter((device) => device.kind === 'audiooutput')
setDevices(audioOutputDevices)
} else {
setDevices([])
}
}

// 初期状態の処理
handlePermissionChange()

// 権限変更の監視
permissionStatus.onchange = handlePermissionChange

return () => {
// ククリーンアップ
permissionStatus.onchange = null
}
}
getDevices()
}, [])

const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setAudioOutputDeviceId(e.target.value)
}

return (
<select onChange={handleChange} value={audioOutputDeviceId}>
{devices.map((device) => (
<option key={device.deviceId} value={device.deviceId}>
{device.label || `Speaker ${device.deviceId}`}
</option>
))}
</select>
)
}

export default AudioOutputDevice
12 changes: 12 additions & 0 deletions devtools/src/components/MediaSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import type React from 'react'
import { useSettingsStore } from '../store/useSettingsStore'
import AudioCodecMimeType from './AudioCodecMimeType'
import AudioInputDevice from './AudioInputDevice'
import AudioOutputDevice from './AudioOutputDevice'
import AudioToggle from './AudioToggle'
import CameraPermissionState from './CameraPermissionState'
import MicrophonePermissionState from './MicrophonePermissionState'
import RequestMediaPermissionButton from './RequestMediaPermissionButton'
import TransceiverDirection from './TransceiverDirection'
import VideoCodecMimeType from './VideoCodecMimeType'
import VideoInputDevice from './VideoInputDevice'
import VideoToggle from './VideoToggle'

const MediaSettings: React.FC = () => {
Expand All @@ -28,6 +31,12 @@ const MediaSettings: React.FC = () => {
Microphone permission state:
<MicrophonePermissionState />
<br />
Audio input device:
<AudioInputDevice />
<br />
Audio output device:
<AudioOutputDevice />
<br />
Direction:
<TransceiverDirection value={audioDirection} onChange={setAudioDirection} />
<br />
Expand All @@ -41,6 +50,9 @@ const MediaSettings: React.FC = () => {
Camera permission state:
<CameraPermissionState />
<br />
Video input device:
<VideoInputDevice />
<br />
Direction:
<TransceiverDirection value={videoDirection} onChange={setVideoDirection} />
<br />
Expand Down
55 changes: 55 additions & 0 deletions devtools/src/components/VideoInputDevice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type React from 'react'
import { useEffect, useState } from 'react'
import { useSettingsStore } from '../store/useSettingsStore'

const VideoInputDevice: React.FC = () => {
const [devices, setDevices] = useState<MediaDeviceInfo[]>([])
const setVideoInputDeviceId = useSettingsStore((state) => state.setVideoInputDeviceId)
const videoInputDeviceId = useSettingsStore((state) => state.settings.video.inputDeviceId)

useEffect(() => {
const getDevices = async () => {
const permissionStatus = await navigator.permissions.query({
name: 'camera' as PermissionName,
})

const handlePermissionChange = async () => {
if (permissionStatus.state === 'granted') {
const devices = await navigator.mediaDevices.enumerateDevices()
const videoInputDevices = devices.filter((device) => device.kind === 'videoinput')
setDevices(videoInputDevices)
} else {
setDevices([])
}
}

// 初期状態の処理
handlePermissionChange()

// 権限変更の監視
permissionStatus.onchange = handlePermissionChange

return () => {
// ククリーンアップ
permissionStatus.onchange = null
}
}
getDevices()
}, [])

const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setVideoInputDeviceId(e.target.value)
}

return (
<select onChange={handleChange} value={videoInputDeviceId}>
{devices.map((device) => (
<option key={device.deviceId} value={device.deviceId}>
{device.label || `Camera ${device.deviceId}`}
</option>
))}
</select>
)
}

export default VideoInputDevice
44 changes: 44 additions & 0 deletions devtools/src/store/useSettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import { create } from 'zustand'
type Settings = {
audio: {
isEnable: boolean
inputDeviceId: string
outputDeviceId: string
direction: Direction
codecMimeType: string
}
video: {
isEnable: boolean
inputDeviceId: string
direction: Direction
codecMimeType: string
}

permissionState: {
microphone: 'granted' | 'denied' | 'prompt' | 'undefined'
camera: 'granted' | 'denied' | 'prompt' | 'undefined'
Expand All @@ -30,10 +34,13 @@ type SettingsStore = {
settings: Settings

toggleAudio: (enabled: boolean) => void
setAudioInputDeviceId: (deviceId: string) => void
setAudioOutputDeviceId: (deviceId: string) => void
setAudioDirection: (direction: Direction) => void
setAudioCodecMimeType: (mimeType: string) => void

toggleVideo: (enabled: boolean) => void
setVideoInputDeviceId: (deviceId: string) => void
setVideoDirection: (direction: Direction) => void
setVideoCodecMimeType: (mimeType: string) => void

Expand Down Expand Up @@ -63,11 +70,14 @@ export const useSettingsStore = create<SettingsStore>()((set, get) => ({
},
audio: {
isEnable: true,
inputDeviceId: 'default',
outputDeviceId: 'default',
direction: 'sendrecv',
codecMimeType: 'undefined',
},
video: {
isEnable: true,
inputDeviceId: 'default',
direction: 'sendrecv',
codecMimeType: 'undefined',
},
Expand Down Expand Up @@ -145,6 +155,28 @@ export const useSettingsStore = create<SettingsStore>()((set, get) => ({
},
})),

setAudioInputDeviceId: (deviceId: string) =>
set((state) => ({
settings: {
...state.settings,
audio: {
...state.settings.audio,
inputDeviceId: deviceId,
},
},
})),

setAudioOutputDeviceId: (deviceId: string) =>
set((state) => ({
settings: {
...state.settings,
audio: {
...state.settings.audio,
outputDeviceId: deviceId,
},
},
})),

setAudioDirection: (direction: Direction) =>
set((state) => ({
settings: {
Expand Down Expand Up @@ -178,6 +210,18 @@ export const useSettingsStore = create<SettingsStore>()((set, get) => ({
},
})),

setVideoInputDeviceId: (deviceId: string) => {
set((state) => ({
settings: {
...state.settings,
video: {
...state.settings.video,
inputDeviceId: deviceId,
},
},
}))
},

setVideoDirection: (direction: Direction) =>
set((state) => ({
settings: {
Expand Down

0 comments on commit c8b38c0

Please sign in to comment.