Skip to content

Commit

Permalink
Add channel source
Browse files Browse the repository at this point in the history
  • Loading branch information
ioppermann committed Nov 29, 2024
1 parent abc1f4a commit aa168db
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 5 deletions.
12 changes: 12 additions & 0 deletions src/utils/restreamer.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,9 @@ class Restreamer {
virtualvideo: [],
videoloop: [],
audioloop: [],
channel: [],
noaudio: [],
sdp: [],
},
sinks: {},
};
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 0 additions & 4 deletions src/views/Edit/Profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
125 changes: 125 additions & 0 deletions src/views/Edit/Sources/Channel.js
Original file line number Diff line number Diff line change
@@ -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 };
2 changes: 1 addition & 1 deletion src/views/Edit/Sources/X11grab.js
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
2 changes: 2 additions & 0 deletions src/views/Edit/Sources/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -54,5 +55,6 @@ registry.Register(VideoLoop);
registry.Register(AudioLoop);
registry.Register(SDP);
registry.Register(X11grab);
registry.Register(Channel);

export default registry;
2 changes: 2 additions & 0 deletions src/views/Edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
};

Expand Down

0 comments on commit aa168db

Please sign in to comment.