Merge pull request #42 from asivery/master

Fetch changes from asivery's fork
This commit is contained in:
Stefano Brilli 2021-06-20 10:43:49 +02:00 committed by GitHub
commit a98c3b8bcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 5 deletions

View File

@ -4,6 +4,7 @@ import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import StopIcon from '@material-ui/icons/Stop'; import StopIcon from '@material-ui/icons/Stop';
import SkipNextIcon from '@material-ui/icons/SkipNext'; import SkipNextIcon from '@material-ui/icons/SkipNext';
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious'; import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
import PauseIcon from '@material-ui/icons/Pause'
import IconButton from '@material-ui/core/IconButton'; import IconButton from '@material-ui/core/IconButton';
import Box from '@material-ui/core/Box'; import Box from '@material-ui/core/Box';
@ -28,6 +29,11 @@ const useStyles = makeStyles(theme => ({
}, },
to: {}, to: {},
}, },
'@keyframes blink': {
'50%': {
visibility: 'hidden',
},
},
container: { container: {
display: 'flex', display: 'flex',
flex: '1 1 auto', flex: '1 1 auto',
@ -88,6 +94,12 @@ const useStyles = makeStyles(theme => ({
top: 15, top: 15,
left: 1, left: 1,
}, },
lcdBlink:{
animationName: '$blink',
animationTimingFunction: 'step-end',
animationDuration: '1s',
animationIterationCount: 'infinite'
},
button: { button: {
// padding: 8, // padding: 8,
}, },
@ -112,11 +124,15 @@ export const Controls = () => {
const handleNext = useCallback(() => { const handleNext = useCallback(() => {
dispatch(control('next')); dispatch(control('next'));
}, [dispatch]); }, [dispatch]);
const handlePause = useCallback(() => {
dispatch(control('pause'));
}, [dispatch]);
let message = ``; let message = ``;
let trackIndex = deviceStatus?.track ?? null; let trackIndex = deviceStatus?.track ?? null;
let deviceState = deviceStatus?.state ?? null; let deviceState = deviceStatus?.state ?? null;
let discPresent = deviceStatus?.discPresent ?? false; let discPresent = deviceStatus?.discPresent ?? false;
let paused = deviceStatus?.state === "paused";
const tracks = getSortedTracks(disc); const tracks = getSortedTracks(disc);
if (!discPresent) { if (!discPresent) {
message = ``; message = ``;
@ -125,7 +141,7 @@ export const Controls = () => {
} else if (tracks.length === 0) { } else if (tracks.length === 0) {
message = `BLANKDISC`; message = `BLANKDISC`;
} else if (deviceStatus && deviceStatus.track !== null && tracks[deviceStatus.track]) { } else if (deviceStatus && deviceStatus.track !== null && tracks[deviceStatus.track]) {
message = `${deviceStatus.track + 1} - ` + tracks[deviceStatus.track].title; message = (deviceStatus.track + 1).toString().padStart(3, '0') + (tracks[deviceStatus.track].title ? ' - ' + tracks[deviceStatus.track].title : '');
} }
const [lcdScroll, setLcdScroll] = useState(0); const [lcdScroll, setLcdScroll] = useState(0);
@ -187,6 +203,7 @@ export const Controls = () => {
handlePrev, handlePrev,
handlePlay, handlePlay,
handleStop, handleStop,
handlePause,
handleNext, handleNext,
message, message,
@ -208,6 +225,9 @@ export const Controls = () => {
<IconButton aria-label="play" onClick={handlePlay} className={classes.button}> <IconButton aria-label="play" onClick={handlePlay} className={classes.button}>
<PlayArrowIcon /> <PlayArrowIcon />
</IconButton> </IconButton>
<IconButton aria-label="pause" onClick={handlePause} className={classes.button}>
<PauseIcon />
</IconButton>
<IconButton aria-label="stop" onClick={handleStop} className={classes.button}> <IconButton aria-label="stop" onClick={handleStop} className={classes.button}>
<StopIcon /> <StopIcon />
</IconButton> </IconButton>
@ -228,7 +248,7 @@ export const Controls = () => {
{message} {message}
</span> </span>
</div> </div>
<div className={classes.lcdDisc}>{discPresent && <DiscFrame className={classes.lcdDiscIcon} />}</div> <div className={classes.lcdDisc}>{discPresent && <DiscFrame className={classes.lcdDiscIcon + (paused ? ' ' + classes.lcdBlink : '')} />}</div>
</div> </div>
</Box> </Box>
); );

View File

@ -8,6 +8,7 @@ import { actions as convertDialogActions } from '../redux/convert-dialog-feature
import { actions as dumpDialogActions } from '../redux/dump-dialog-feature'; import { actions as dumpDialogActions } from '../redux/dump-dialog-feature';
import { formatTimeFromFrames, getTracks } from 'netmd-js'; import { formatTimeFromFrames, getTracks } from 'netmd-js';
import { control } from '../redux/actions';
import { belowDesktop, forAnyDesktop, getSortedTracks, useShallowEqualSelector } from '../utils'; import { belowDesktop, forAnyDesktop, getSortedTracks, useShallowEqualSelector } from '../utils';
@ -19,6 +20,8 @@ import AddIcon from '@material-ui/icons/Add';
import DeleteIcon from '@material-ui/icons/Delete'; import DeleteIcon from '@material-ui/icons/Delete';
import EditIcon from '@material-ui/icons/Edit'; import EditIcon from '@material-ui/icons/Edit';
import Backdrop from '@material-ui/core/Backdrop'; import Backdrop from '@material-ui/core/Backdrop';
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import PauseIcon from '@material-ui/icons/Pause'
import Table from '@material-ui/core/Table'; import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody'; import TableBody from '@material-ui/core/TableBody';
@ -133,12 +136,53 @@ const useStyles = makeStyles(theme => ({
textDecoration: 'underline', textDecoration: 'underline',
textDecorationStyle: 'dotted', textDecorationStyle: 'dotted',
}, },
controlButtonInTrackCommon: {
width: '.5em',
verticalAlign: 'middle',
},
playButtonInTrackListPlaying: {
color: theme.palette.primary.main,
display: 'none',
},
pauseButtonInTrackListPlaying: {
color: theme.palette.primary.main,
display: 'none',
},
currentControlButton: {
display: 'inline-block',
},
playButtonInTrackListNotPlaying: {
visibility: 'hidden',
},
trackRow: {
'&:hover': {
/* For the tracks that aren't currently playing */
"& $playButtonInTrackListNotPlaying":{
visibility: 'visible',
},
"& $trackIndex":{
display: 'none',
},
/* For the current track */
"& svg:not($currentControlButton)": {
display: 'inline-block',
},
"& $currentControlButton": {
display: 'none',
}
},
},
trackIndex:{
display: 'inline-block',
}
})); }));
export const Main = (props: {}) => { export const Main = (props: {}) => {
let dispatch = useDispatch(); let dispatch = useDispatch();
let disc = useShallowEqualSelector(state => state.main.disc); let disc = useShallowEqualSelector(state => state.main.disc);
let deviceName = useShallowEqualSelector(state => state.main.deviceName); let deviceName = useShallowEqualSelector(state => state.main.deviceName);
const deviceStatus = useShallowEqualSelector(state => state.main.deviceStatus);
const { vintageMode } = useShallowEqualSelector(state => state.appState); const { vintageMode } = useShallowEqualSelector(state => state.appState);
const [selected, setSelected] = React.useState<number[]>([]); const [selected, setSelected] = React.useState<number[]>([]);
@ -229,6 +273,20 @@ export const Main = (props: {}) => {
dispatch(deleteTracks(selected)); dispatch(deleteTracks(selected));
}; };
const handlePlayTrack = async (event: React.MouseEvent, track: number) => {
if(deviceStatus?.track !== track)
dispatch(control('goto', track));
if(deviceStatus?.state !== 'playing')
dispatch(control('play'));
};
const handleCurrentClick = async (event: React.MouseEvent) => {
if(deviceStatus?.state === 'playing')
dispatch(control('pause'));
else
dispatch(control('play'));
}
if (vintageMode) { if (vintageMode) {
const p = { const p = {
disc, disc,
@ -390,8 +448,26 @@ export const Main = (props: {}) => {
key={track.index} key={track.index}
onDoubleClick={event => handleRenameDoubleClick(event, track.index)} onDoubleClick={event => handleRenameDoubleClick(event, track.index)}
onClick={event => handleSelectClick(event, track.index)} onClick={event => handleSelectClick(event, track.index)}
className={classes.trackRow}
> >
<TableCell className={classes.indexCell}>{track.index + 1}</TableCell> <TableCell className={classes.indexCell}>
{track.index === deviceStatus?.track && (["playing", "paused"].includes(deviceStatus?.state)) ?
<span>
<PlayArrowIcon
className={`${classes.controlButtonInTrackCommon} ${classes.playButtonInTrackListPlaying} ${deviceStatus?.state === 'playing' ? classes.currentControlButton : ''}`}
onClick={event => {handleCurrentClick(event); event.stopPropagation();}} />
<PauseIcon
className={`${classes.controlButtonInTrackCommon} ${classes.pauseButtonInTrackListPlaying} ${deviceStatus?.state === 'paused' ? classes.currentControlButton : ''}`}
onClick={event => {handleCurrentClick(event); event.stopPropagation()}} />
</span> :
<span>
<span className={classes.trackIndex}>{track.index + 1}</span>
<PlayArrowIcon
className={`${classes.controlButtonInTrackCommon} ${classes.playButtonInTrackListNotPlaying}`}
onClick={event => {handlePlayTrack(event, track.index); event.stopPropagation();}}
/>
</span>}
</TableCell>
<TableCell className={classes.titleCell} title={track.title}> <TableCell className={classes.titleCell} title={track.title}>
{track.title || `No Title`} {track.title || `No Title`}
</TableCell> </TableCell>

View File

@ -6,6 +6,7 @@ import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import StopIcon from '@material-ui/icons/Stop'; import StopIcon from '@material-ui/icons/Stop';
import SkipNextIcon from '@material-ui/icons/SkipNext'; import SkipNextIcon from '@material-ui/icons/SkipNext';
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious'; import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
import PauseIcon from '@material-ui/icons/Pause';
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles(theme => ({ const useStyles = makeStyles(theme => ({
@ -32,6 +33,7 @@ export const W95Controls = (props: {
handlePrev: () => void; handlePrev: () => void;
handlePlay: () => void; handlePlay: () => void;
handleStop: () => void; handleStop: () => void;
handlePause: () => void;
handleNext: () => void; handleNext: () => void;
message: string; message: string;
discPresent: boolean; discPresent: boolean;
@ -49,6 +51,9 @@ export const W95Controls = (props: {
<Button onClick={props.handlePlay}> <Button onClick={props.handlePlay}>
<PlayArrowIcon /> <PlayArrowIcon />
</Button> </Button>
<Button onClick={props.handlePause}>
<PauseIcon />
</Button>
<Button onClick={props.handleStop}> <Button onClick={props.handleStop}>
<StopIcon /> <StopIcon />
</Button> </Button>

View File

@ -14,7 +14,7 @@ import * as mm from 'music-metadata-browser';
import { TitleFormatType, UploadFormat } from './convert-dialog-feature'; import { TitleFormatType, UploadFormat } from './convert-dialog-feature';
import NotificationCompleteIconUrl from '../images/record-complete-notification-icon.png'; import NotificationCompleteIconUrl from '../images/record-complete-notification-icon.png';
export function control(action: 'play' | 'stop' | 'next' | 'prev' | 'goto', params?: unknown) { export function control(action: 'play' | 'stop' | 'next' | 'prev' | 'goto' | 'pause', params?: unknown) {
return async function(dispatch: AppDispatch, getState: () => RootState) { return async function(dispatch: AppDispatch, getState: () => RootState) {
switch (action) { switch (action) {
case 'play': case 'play':
@ -29,8 +29,11 @@ export function control(action: 'play' | 'stop' | 'next' | 'prev' | 'goto', para
case 'prev': case 'prev':
await serviceRegistry.netmdService!.prev(); await serviceRegistry.netmdService!.prev();
break; break;
case 'pause':
await serviceRegistry.netmdService!.pause();
break;
case 'goto': case 'goto':
if (params && typeof params === 'number' && params >= 0) { if (params !== null && params !== undefined && typeof params === 'number' && params >= 0) {
await serviceRegistry.netmdService!.gotoTrack(params); await serviceRegistry.netmdService!.gotoTrack(params);
} }
break; break;