File size: 4,412 Bytes
efc9173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"use client";

import { useEffect } from "react";
import { DailyMeetingState } from "@daily-co/daily-js";
import { useDaily, useDevices } from "@daily-co/daily-react";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { IconMicrophone, IconDeviceSpeaker } from "@tabler/icons-react";
import { AudioIndicatorBar } from "../AudioIndicator";

interface Props {}

export default function DevicePicker({}: Props) {
  const daily = useDaily();
  const {
    currentMic,
    hasMicError,
    micState,
    microphones,
    setMicrophone,
    currentSpeaker,
    speakers,
    setSpeaker,
  } = useDevices();

  const handleMicrophoneChange = (value: string) => {
    setMicrophone(value);
  };

  const handleSpeakerChange = (value: string) => {
    setSpeaker(value);
  };

  useEffect(() => {
    if (microphones.length > 0 || !daily || daily.isDestroyed()) return;
    const meetingState = daily.meetingState();
    const meetingStatesBeforeJoin: DailyMeetingState[] = [
      "new",
      "loading",
      "loaded",
    ];
    if (meetingStatesBeforeJoin.includes(meetingState)) {
      daily.startCamera({ startVideoOff: true, startAudioOff: false });
    }
  }, [daily, microphones]);

  return (
    <div className="flex flex-col gap-5">
      <section>
        <label className="uppercase text-sm tracking-wider text-gray-500">
          Microphone:
        </label>
        <div className="flex flex-row gap-4 items-center mt-2">
          <IconMicrophone size={24} />
          <div className="flex flex-col flex-1 gap-3">
            <Select onValueChange={handleMicrophoneChange}>
              <SelectTrigger className="">
                <SelectValue
                  placeholder={
                    hasMicError ? "error" : currentMic?.device?.label
                  }
                />
              </SelectTrigger>
              <SelectContent>
                {hasMicError && (
                  <option value="error" disabled>
                    No microphone access.
                  </option>
                )}

                {microphones.map((m) => (
                  <SelectItem key={m.device.deviceId} value={m.device.deviceId}>
                    {m.device.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <AudioIndicatorBar />
          </div>
        </div>
      </section>

      <section>
        <label className="uppercase text-sm tracking-wider text-gray-500">
          Speakers:
        </label>
        <div className="flex flex-row gap-4 items-center mt-2">
          <IconDeviceSpeaker size={24} />
          <Select onValueChange={handleSpeakerChange}>
            <SelectTrigger className="">
              <SelectValue placeholder={currentSpeaker?.device?.label} />
            </SelectTrigger>
            <SelectContent>
              {speakers.map((m) => (
                <SelectItem key={m.device.deviceId} value={m.device.deviceId}>
                  {m.device.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
      </section>
      {hasMicError && (
        <div className="error">
          {micState === "blocked" ? (
            <p className="text-red-500">
              Please check your browser and system permissions. Make sure that
              this app is allowed to access your microphone.
            </p>
          ) : micState === "in-use" ? (
            <p className="text-red-500">
              Your microphone is being used by another app. Please close any
              other apps using your microphone and restart this app.
            </p>
          ) : micState === "not-found" ? (
            <p className="text-red-500">
              No microphone seems to be connected. Please connect a microphone.
            </p>
          ) : micState === "not-supported" ? (
            <p className="text-red-500">
              This app is not supported on your device. Please update your
              software or use a different device.
            </p>
          ) : (
            <p className="text-red-500">
              There seems to be an issue accessing your microphone. Try
              restarting the app or consult a system administrator.
            </p>
          )}
        </div>
      )}
    </div>
  );
}