diff --git a/src/misc/modals/Hint.js b/src/misc/modals/Hint.js
new file mode 100644
index 0000000..4f790e3
--- /dev/null
+++ b/src/misc/modals/Hint.js
@@ -0,0 +1,200 @@
+import React from 'react';
+
+import { useLingui } from '@lingui/react';
+import { Trans, t } from '@lingui/macro';
+import Button from '@mui/material/Button';
+import Grid from '@mui/material/Grid';
+import Stack from '@mui/material/Stack';
+import MenuItem from '@mui/material/MenuItem';
+import Typography from '@mui/material/Typography';
+
+import Dialog from './Dialog';
+import Select from '../Select';
+import Video from '../coders/settings/Video';
+import Audio from '../coders/settings/Audio';
+
+const Stream = function (props) {
+ const { i18n } = useLingui();
+
+ const handleChange = (what) => (event) => {
+ const value = event.target.value;
+
+ let stream = {
+ ...props.stream,
+ };
+
+ if (what === 'type') {
+ if (value === 'audio') {
+ stream.codec = 'aac';
+ if (stream.sampling_hz === 0) {
+ stream.sampling_hz = 44100;
+ }
+ if (stream.layout === '') {
+ stream.layout = 'stereo';
+ stream.channels = 2;
+ }
+ } else {
+ stream.codec = 'h264';
+ if (stream.width === 0) {
+ stream.width = 1920;
+ stream.height = 1080;
+ }
+ }
+ stream.type = value;
+ } else if (what === 'size') {
+ const [width, height] = value.split('x');
+
+ stream.width = width;
+ stream.height = height;
+ } else {
+ stream[what] = value;
+ }
+
+ props.onChange(stream);
+ };
+
+ return (
+
+
+
+
+ {props.stream.type === 'audio' ? (
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+
+
+
+
+
+
+
+
+ )}
+
+ );
+};
+
+Stream.defaultProps = {
+ stream: {},
+ locked: false,
+ onChange: () => {},
+};
+
+const Streams = function (props) {
+ const handleChange = (index) => (stream) => {
+ const streams = props.streams.slice();
+
+ streams[index] = stream;
+
+ props.onChange(streams);
+ };
+
+ const handleAddStream = () => {
+ const streams = props.streams.slice();
+
+ streams.push({
+ index: props.type === 'video' ? 0 : 1,
+ stream: streams.length,
+ type: 'audio',
+ codec: 'aac',
+ width: 0,
+ height: 0,
+ sampling_hz: 44100,
+ layout: 'stereo',
+ channels: 2,
+ });
+
+ props.onChange(streams);
+ };
+
+ const handleRemoveStream = (index) => () => {
+ const streams = props.streams.toSpliced(index, 1);
+
+ props.onChange(streams);
+ };
+
+ return (
+
+ {props.streams.map((stream, index) => (
+
+
+ Stream {stream.stream}
+
+ {index > 0 && (
+
+ )}
+
+
+ ))}
+
+
+
+
+ );
+};
+
+Streams.defaultProps = {
+ streams: [],
+ type: '',
+ onChange: () => {},
+};
+
+const Component = function (props) {
+ return (
+
+ );
+};
+
+export default Component;
+
+Component.defaultProps = {
+ open: false,
+ title: '',
+ streams: [],
+ type: '',
+ onClose: null,
+ onDone: () => {},
+ onHelp: null,
+};
diff --git a/src/views/Edit/Profile.js b/src/views/Edit/Profile.js
index 13c45fc..aae5f92 100644
--- a/src/views/Edit/Profile.js
+++ b/src/views/Edit/Profile.js
@@ -15,6 +15,7 @@ import BoxText from '../../misc/BoxText';
import EncodingSelect from '../../misc/EncodingSelect';
import PaperFooter from '../../misc/PaperFooter';
import ProbeModal from '../../misc/modals/Probe';
+import HintModal from '../../misc/modals/Hint';
import SourceSelect from './SourceSelect';
import StreamSelect from './StreamSelect';
@@ -39,10 +40,15 @@ export default function Profile(props) {
status: 'none',
});
const [$skillsRefresh, setSkillsRefresh] = React.useState(false);
- const [$modal, setModal] = React.useState({
+ const [$probeModal, setProbeModal] = React.useState({
open: false,
data: '',
});
+ const [$hintModal, setHintModal] = React.useState({
+ open: false,
+ type: '',
+ streams: [],
+ });
const [$activeStep, setActiveStep] = React.useState(props.startWith === 'audio' ? 1 : 0);
const [$ready, setReady] = React.useState(false);
@@ -106,6 +112,12 @@ export default function Profile(props) {
const res = await props.onProbe(inputs);
+ const status = handleProbeStreams(type, device, settings, inputs, res);
+
+ return status === 'success';
+ };
+
+ const handleProbeStreams = (type, device, settings, inputs, res) => {
let status = M.analyzeStreams(type, res.streams);
if (type === 'video') {
@@ -194,8 +206,6 @@ export default function Profile(props) {
},
});
}
-
- return status === 'success';
};
const handleRefresh = async () => {
@@ -242,24 +252,24 @@ export default function Profile(props) {
props.onAbort();
};
- const handleModal = (type) => (event) => {
+ const handleProbeLogModal = (type) => (event) => {
event.preventDefault();
if (type === 'video') {
- setModal({
- ...$modal,
+ setProbeModal({
+ ...$probeModal,
open: true,
data: $videoProbe.log.join('\n'),
});
} else if (type === 'audio') {
- setModal({
- ...$modal,
+ setProbeModal({
+ ...$probeModal,
open: true,
data: $audioProbe.log.join('\n'),
});
} else {
- setModal({
- ...$modal,
+ setProbeModal({
+ ...$probeModal,
open: false,
data: '',
});
@@ -348,6 +358,104 @@ export default function Profile(props) {
});
};
+ const handleHintModal = (type, streams) => (event) => {
+ if (event) {
+ event.preventDefault();
+ }
+
+ if (!streams) {
+ streams = [];
+ }
+
+ if (streams.length > 0) {
+ return streams;
+ }
+
+ if (type === 'video') {
+ streams = [
+ {
+ index: 0,
+ stream: 0,
+ type: 'video',
+ codec: 'h264',
+ width: 1920,
+ height: 1080,
+ sampling_hz: 0,
+ layout: '',
+ channels: 0,
+ },
+ ];
+ } else if (type === 'audio') {
+ streams = [
+ {
+ index: 1,
+ stream: 0,
+ type: 'audio',
+ codec: 'aac',
+ width: 0,
+ height: 0,
+ sampling_hz: 44100,
+ layout: 'stereo',
+ channels: 2,
+ },
+ ];
+ }
+
+ if (type === 'video') {
+ setHintModal({
+ ...$hintModal,
+ open: true,
+ type: type,
+ streams: streams,
+ });
+ } else if (type === 'audio') {
+ setHintModal({
+ ...$hintModal,
+ open: true,
+ type: type,
+ streams: streams,
+ });
+ } else {
+ setHintModal({
+ ...$hintModal,
+ open: false,
+ type: '',
+ streams: [],
+ });
+ }
+ };
+
+ const handleHintChange = (streams) => {
+ setHintModal({
+ ...$hintModal,
+ streams: streams,
+ });
+ };
+
+ const handleHintCancel = () => {
+ setHintModal({
+ streams: [],
+ });
+
+ handleHintModal('none')(null);
+ };
+
+ const handleHintDone = () => {
+ const type = $hintModal.type;
+
+ const device = $sources[type].type;
+ const settings = $sources[type].settings;
+ const inputs = $sources[type].inputs;
+ const probe = {
+ streams: $hintModal.streams,
+ log: ['Stream hints'],
+ };
+
+ handleProbeStreams(type, device, settings, inputs, probe);
+
+ handleHintModal('none')(null);
+ };
+
if ($ready === false) {
return null;
}
@@ -383,12 +491,21 @@ export default function Profile(props) {
Failed to probe the source. Please check the{' '}
-
+
probe details
.
+
+
+ In order to proceed anyways, you can provide{' '}
+
+ hints
+ {' '}
+ about the available streams.
+
+
)}
@@ -399,7 +516,7 @@ export default function Profile(props) {
The source doesn't provide any video streams. Please check the{' '}
-
+
probe details
.
@@ -421,7 +538,7 @@ export default function Profile(props) {
-
+
Show probe details
@@ -533,7 +650,7 @@ export default function Profile(props) {
Failed to probe the source. Please check the{' '}
-
+
probe details
.
@@ -549,7 +666,7 @@ export default function Profile(props) {
The source doesn't provide any audio streams. Please check the{' '}
-
+
probe details
.
@@ -571,7 +688,7 @@ export default function Profile(props) {
-
+
Show probe details
@@ -629,7 +746,16 @@ export default function Profile(props) {
-
+
+
);
}