Skip to content

Commit

Permalink
MIDI-Control: Launchpad X
Browse files Browse the repository at this point in the history
  • Loading branch information
YeonV committed Sep 12, 2024
1 parent 220cb46 commit d8e2bc4
Show file tree
Hide file tree
Showing 9 changed files with 762 additions and 119 deletions.
2 changes: 1 addition & 1 deletion src/components/Bars/BarBottom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import SpotifyFabFree from '../Integrations/Spotify/SpotifyFabFree'
import AddButton from '../AddButton/AddButton'
import YoutubeWidget from '../Integrations/Youtube/YoutubeWidget'
import SpotifyFabPro from '../Integrations/Spotify/SpotifyFabPro'
import MIDIListener from '../MidiListener'
import MIDIListener from '../Midi/MidiListener'
import { drawerWidth, ios } from '../../utils/helpers'
import EditSceneDialog from '../Dialogs/SceneDialogs/EditSceneDialog'
import BladeIcon from '../Icons/BladeIcon/BladeIcon'
Expand Down
156 changes: 133 additions & 23 deletions src/components/Gamepad/Assign.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
MenuItem,
Select,
Stack,
Typography,
useTheme
} from '@mui/material'
import {
Expand All @@ -23,12 +24,14 @@ import BladeIcon from '../Icons/BladeIcon/BladeIcon'
import OneShot from './OneShot'

const Assign = ({
type,
mapping,
setMapping,
pressed,
index,
padIndex,
disabled
disabled,
compact = true
}: any) => {
// console.log('mapping', mapping)
const theme = useTheme()
Expand All @@ -49,27 +52,84 @@ const Assign = ({
}

return (
<Stack key={index} direction="row" alignItems="center" spacing={1}>
<Fab
size="small"
color={pressed ? 'primary' : 'inherit'}
sx={{
background: pressed ? theme.palette.primary.main : '#333',
m: 1,
color: disabled ? '#999' : 'inherit',
width: 40,
height: 40,
flexShrink: 0,
pointerEvents: 'none'
}}
>
{index}
</Fab>
<FormControl fullWidth>
<Stack key={index} direction={compact ? "row" : "column"} alignItems={compact ? "center" : "stretch"} spacing={compact ? 1 : 0}>
{compact
&& <Fab
size="small"
color={pressed ? 'primary' : 'inherit'}
sx={{
background: pressed ? theme.palette.primary.main : '#333',
m: 1,
color: disabled ? '#999' : 'inherit',
width: 40,
height: 40,
flexShrink: 0,
pointerEvents: 'none'
}}
>
{index}
</Fab>}
{!compact
? <Stack direction="row" justifyContent={'space-between'} alignItems={'center'}>
<Typography>
Command
</Typography>
<FormControl>
<Select
disableUnderline
disabled={disabled || mapping[padIndex][index]?.command === 'scene'}
// IconComponent={() => null}
style={{
textAlign: 'right',
color:
mapping[padIndex]?.[index]?.command &&
mapping[padIndex]?.[index]?.command !== 'none'
? 'white'
: 'grey'
}}
sx={{
'& .MuiSelect-select': {
marginTop: '3px'
}
}}
labelId="command-select-label"
label="command"
// renderValue={(v) =>
// v === 'scene' ? <Wallpaper sx={{ pr: 0 }} /> : v
// }
value={mapping[padIndex]?.[index]?.command || 'none'}
onChange={(e) =>
setMapping({
...mapping,
[padIndex]: {
...mapping[padIndex],
[index]: { command: e.target.value }
}
})
}
>
<MenuItem value="none" key="none">
<Stack direction="row" spacing={1}>
<QuestionMark />
<span>{disabled ? 'used by LedFx' : 'choose command'}</span>
</Stack>
</MenuItem>
{Object.keys(commands).map((s) => (
<MenuItem key={s} value={s} disabled={type === 'midi' && s === 'scene'}>
<Stack direction="row" spacing={1}>
{commands[s as keyof typeof commands] || ''}
<span>{s || 'none'}</span>
</Stack>
</MenuItem>
))}
</Select>
</FormControl>
</Stack>
: <FormControl fullWidth>
<Select
fullWidth
disableUnderline
disabled={disabled}
disabled={disabled || (type === 'midi' && mapping[padIndex][index]?.command === 'scene')}
// IconComponent={() => null}
style={{
color:
Expand Down Expand Up @@ -106,21 +166,71 @@ const Assign = ({
</Stack>
</MenuItem>
{Object.keys(commands).map((s) => (
<MenuItem key={s} value={s}>
<MenuItem key={s} value={s} disabled={type === 'midi' && s === 'scene'}>
<Stack direction="row" spacing={1}>
{commands[s as keyof typeof commands] || ''}
<span>{s || 'none'}</span>
</Stack>
</MenuItem>
))}
</Select>
</FormControl>
</FormControl>}
{mapping[padIndex]?.[index]?.command === 'scene' && (
<FormControl sx={{ maxWidth: 150, minWidth:150 }} fullWidth>
!compact
? <Stack direction="row" justifyContent={'space-between'} alignItems={'center'} mt={0.5}>
<Typography>
Scene
</Typography><FormControl sx={{ maxWidth: 150, minWidth:150 }}>
<Select
disableUnderline
disabled={disabled || mapping[padIndex][index]?.command === 'scene'}
// IconComponent={() => null}
style={{
textAlign: 'right',
color:
mapping[padIndex]?.[index]?.payload &&
mapping[padIndex]?.[index]?.payload !== 'choose scene'
? 'white'
: 'grey'
}}
sx={{
'& .MuiSelect-select': {
// paddingRight: '0 !important',
marginTop: '3px'
}
}}
labelId="scene-select-label"
label="Scene"
value={mapping[padIndex]?.[index]?.payload?.scene || 'none'}
onChange={(e) =>
setMapping({
...mapping,
[padIndex]: {
...mapping[padIndex],
[index]: {
...mapping[padIndex]?.[index],
payload: { scene: e.target.value }
}
}
})
}
>
<MenuItem value="none" key="none">
{disabled ? 'used by LedFx' : 'choose scene'}
</MenuItem>
{Object.keys(scenes).map((s: string) => (
<MenuItem key={s} value={s}>
{scenes[s]?.name || s || 'none'}
</MenuItem>
))}
</Select>
</FormControl>
</Stack>
: <FormControl sx={{ maxWidth: 150, minWidth:150 }} fullWidth>
<Select
fullWidth
disableUnderline
disabled={disabled}
disabled={disabled || (type === 'midi' && mapping[padIndex][index]?.command === 'scene')}
// IconComponent={() => null}
style={{
color:
Expand Down
116 changes: 116 additions & 0 deletions src/components/Midi/LaunchpadButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import Button from '@mui/material/Button'
import DialogTitle from '@mui/material/DialogTitle'
import Dialog from '@mui/material/Dialog'
import { darken, DialogContent, Divider, Stack, Typography } from '@mui/material'
import { useState } from 'react'
import LpColorPicker from './LpColorPicker'
import Assign from '../Gamepad/Assign'
import useStore from '../../store/useStore'
import { getColorFromValue } from './lpColors'

const LaunchpadButton = ({
buttonNumber,
active,
borderless,
bgColor,
children,
...props
}: {
buttonNumber: number
children: React.ReactNode
active?: boolean
borderless?: boolean
bgColor?: string
}) => {
const [open, setOpen] = useState(false)

const midiMapping = useStore((state) => state.midiMapping)
const setMidiMapping = useStore((state) => state.setMidiMapping)
const midiSceneInactiveColor = useStore((state) => state.midiColors.sceneInactiveColor)
const midiSceneActiveColor = useStore((state) => state.midiColors.sceneActiveColor)
const midiCommandColor = useStore((state) => state.midiColors.commandColor)
const handleClickOpen = () => {
setOpen(true)
}

const handleClose = () => {
setOpen(false)
}

return (
<div>
<Button
variant="outlined"
onContextMenu={(e) => {
e.preventDefault()
handleClickOpen()
}}
sx={{
width: 70,
height: 70,
borderRadius: 1,
borderColor: active ? 'orange' : '#ccc',
borderStyle: 'solid',
borderWidth: borderless ? 0 : 1,
color: active ? 'orange' : '#ccc',
bgcolor: bgColor,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
'&:hover': {
backgroundColor: darken((bgColor || '#ffffff'), 0.2),
},
}}
{...props}
>
{children}
</Button>
<Dialog onClose={handleClose} open={open}>
<DialogTitle>Edit Launchpad Button {buttonNumber}</DialogTitle>
<DialogContent>
<Assign
type={'midi'}
compact={false}
padIndex={0}
mapping={midiMapping}
setMapping={setMidiMapping}
pressed={false}
index={`${buttonNumber}`}
key={`${buttonNumber}`}
/>
<Divider sx={{ mb: 2.5, mt: 1.5}} />
<Stack direction={'column'} spacing={1} mt={1}>
<Stack direction={'row'} spacing={2} justifyContent={'space-between'} alignItems={'center'}>
<Typography>Scene inactive</Typography>
<LpColorPicker defaultColor={getColorFromValue(`${midiMapping[0][buttonNumber]?.colorSceneInactive}` || midiSceneInactiveColor)} onColorSelect={(color: string) => {
setMidiMapping({...midiMapping, [0]: {...midiMapping[0], [buttonNumber]: {...midiMapping[0][buttonNumber], colorSceneInactive: color}}})
}} />
</Stack>
<Stack direction={'row'} spacing={2} justifyContent={'space-between'} alignItems={'center'}>
<Typography>Scene active</Typography>
<LpColorPicker defaultColor={getColorFromValue(`${midiMapping[0][buttonNumber]?.colorSceneActive}` || midiSceneActiveColor)} onColorSelect={(color: string) => {
setMidiMapping({...midiMapping, [0]: {...midiMapping[0], [buttonNumber]: {...midiMapping[0][buttonNumber], colorSceneActive: color}}})
}} />
</Stack>
<Stack direction={'row'} spacing={2} justifyContent={'space-between'} alignItems={'center'}>
<Typography>Command</Typography>
<LpColorPicker defaultColor={getColorFromValue(`${midiMapping[0][buttonNumber]?.colorCommand}` || midiCommandColor)} onColorSelect={(color: string) => {
setMidiMapping({...midiMapping, [0]: {...midiMapping[0], [buttonNumber]: {...midiMapping[0][buttonNumber], colorCommand: color}}})
}} />
</Stack>
</Stack>
<Stack direction={'row'} justifyContent={'flex-end'} spacing={1} mt={5}>
<Button onClick={() => handleClose()}>
Cancel
</Button>
<Button onClick={() => handleClose()}>
Save
</Button>
</Stack>
</DialogContent>
</Dialog>
</div>
)
}

export default LaunchpadButton
Loading

0 comments on commit d8e2bc4

Please sign in to comment.