Add channel source

This commit is contained in:
Ingo Oppermann 2024-11-29 13:00:50 +01:00
parent abc1f4a1f4
commit aa168db7d5
No known key found for this signature in database
GPG Key ID: 2AB32426E9DD229E
6 changed files with 142 additions and 5 deletions

View File

@ -514,6 +514,9 @@ class Restreamer {
virtualvideo: [],
videoloop: [],
audioloop: [],
channel: [],
noaudio: [],
sdp: [],
},
sinks: {},
};
@ -677,6 +680,15 @@ class Restreamer {
skills.sources['network'].push(...channels);
channels = this.ListChannels().map((channel) => {
return {
id: channel.channelid,
name: channel.name,
};
});
skills.sources['channel'].push(...channels);
this.skills = skills;
}

View File

@ -78,10 +78,6 @@ export default function Profile({
}, []);
const load = async () => {
// Add pseudo sources
skills.sources.noaudio = [];
skills.sources.sdp = [];
let audio = $sources.audio;
let hasAudio = false;

View File

@ -0,0 +1,125 @@
import React from 'react';
import { useLingui } from '@lingui/react';
import { Trans, t } from '@lingui/macro';
import VideocamIcon from '@mui/icons-material/Videocam';
import makeStyles from '@mui/styles/makeStyles';
import Button from '@mui/material/Button';
import Grid from '@mui/material/Grid';
import RefreshIcon from '@mui/icons-material/Refresh';
import Typography from '@mui/material/Typography';
import FormInlineButton from '../../../misc/FormInlineButton';
import SelectCustom from '../../../misc/SelectCustom';
const useStyles = makeStyles((theme) => ({
gridContainer: {
marginTop: '0.5em',
},
}));
const initSettings = (initialSettings) => {
if (!initialSettings) {
initialSettings = {};
}
const settings = {
channelid: 'none',
...initialSettings,
};
return settings;
};
const createInputs = (settings) => {
const address = `{fs:mem}/${settings.channelid}.m3u8`;
const input = {
address: address,
options: [],
};
return [input];
};
function Source({ knownDevices = [], settings = {}, onChange = function (settings) {}, onProbe = function (settings, inputs) {}, onRefresh = function () {} }) {
const classes = useStyles();
const { i18n } = useLingui();
settings = initSettings(settings);
const handleChange = (what) => (event) => {
let data = {};
if (['channelid'].includes(what)) {
data[what] = event.target.value;
}
onChange({
...settings,
...data,
});
};
const handleRefresh = () => {
onRefresh();
};
const handleProbe = () => {
onProbe(settings, createInputs(settings));
};
const options = knownDevices.map((device) => {
return {
value: device.id,
label: device.name + ' (' + device.id + ')',
};
});
options.unshift({
value: 'none',
label: i18n._(t`Choose an input channel ...`),
disabled: true,
});
return (
<Grid container alignItems="flex-start" spacing={2} className={classes.gridContainer}>
<Grid item xs={12}>
<Typography>
<Trans>Select a channel:</Trans>
</Typography>
</Grid>
<Grid item xs={12}>
<SelectCustom
options={options}
label={<Trans>Video device</Trans>}
value={settings.channelid}
onChange={handleChange('channelid')}
variant="outlined"
/>
<Button size="small" startIcon={<RefreshIcon />} onClick={handleRefresh} sx={{ float: 'right' }}>
<Trans>Refresh</Trans>
</Button>
</Grid>
<Grid item xs={12}>
<FormInlineButton onClick={handleProbe} disabled={settings.channelid === 'none'}>
<Trans>Probe</Trans>
</FormInlineButton>
</Grid>
</Grid>
);
}
function SourceIcon(props) {
return <VideocamIcon style={{ color: '#FFF' }} {...props} />;
}
const id = 'channel';
const name = <Trans>Channel</Trans>;
const capabilities = ['audio', 'video'];
const ffversion = '^4.1.0 || ^5.0.0 || ^6.1.0 || ^7.0.0';
const func = {
initSettings,
createInputs,
};
export { id, name, capabilities, ffversion, SourceIcon as icon, Source as component, func };

View File

@ -1,8 +1,8 @@
import React from 'react';
import { useLingui } from '@lingui/react';
import ScreenshotMonitorIcon from '@mui/icons-material/ScreenshotMonitor';
import { Trans, t } from '@lingui/macro';
import ScreenshotMonitorIcon from '@mui/icons-material/ScreenshotMonitor';
import makeStyles from '@mui/styles/makeStyles';
import Button from '@mui/material/Button';
import Grid from '@mui/material/Grid';

View File

@ -11,6 +11,7 @@ import * as VideoLoop from './VideoLoop';
import * as VirtualAudio from './VirtualAudio';
import * as VirtualVideo from './VirtualVideo';
import * as X11grab from './X11grab';
import * as Channel from './Channel';
class Registry {
constructor() {
@ -54,5 +55,6 @@ registry.Register(VideoLoop);
registry.Register(AudioLoop);
registry.Register(SDP);
registry.Register(X11grab);
registry.Register(Channel);
export default registry;

View File

@ -112,6 +112,7 @@ export default function Edit({ restreamer = null }) {
});
const skills = await restreamer.Skills();
skills.sources['channel'] = skills.sources['channel'].filter((channel) => channel.id !== _channelid);
setSkills(skills);
const config = await restreamer.ConfigActive();
@ -208,6 +209,7 @@ export default function Edit({ restreamer = null }) {
await restreamer.RefreshSkills();
const skills = await restreamer.Skills();
skills.sources['channel'] = skills.sources['channel'].filter((channel) => channel.id !== _channelid);
setSkills(skills);
};