Simple monitor for displaying MIDI status for digital pianos.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

84 рядки
2.8 KiB

  1. import Keyboard, {
  2. StyledNaturalKey,
  3. StyledAccidentalKey
  4. } from '@theoryofnekomata/react-musical-keyboard'
  5. import * as React from 'react'
  6. import { PedalBoard } from '../components/PedalBoard'
  7. import { Activity } from '../components/Activity'
  8. import { useMidi, useMidiActivity } from '../hooks/midi'
  9. import { RANGES } from '../../../common/config'
  10. import { useForm } from '../hooks/form'
  11. interface IndexPageProps {
  12. params: URLSearchParams
  13. }
  14. const IndexPage: React.FC<IndexPageProps> = ({ params: search }) => {
  15. const { handleAction } = useForm()
  16. const { midiAccess, lastStateChangeTimestamp: devicesLoadedTimestamp } = useMidi()
  17. const inputDevices = Array.from(midiAccess?.inputs.entries() ?? [])
  18. const queryDeviceKey = search.get('queryDeviceKey') || inputDevices?.[0]?.[0] || ''
  19. const currentDevice =
  20. typeof midiAccess?.inputs !== 'undefined' ? midiAccess.inputs.get(queryDeviceKey) : undefined
  21. const { keyChannels, unaCorda, isChannelActive, sustain, sostenuto } =
  22. useMidiActivity(currentDevice)
  23. const range = search.get('range') || RANGES['A0-C8']
  24. const [startKeyRaw, endKeyRaw] = range.split('|')
  25. const startKey = Number(startKeyRaw)
  26. const endKey = Number(endKeyRaw)
  27. return (
  28. <div
  29. className="flex flex-col items-center h-full w-full group relative select-none"
  30. key={devicesLoadedTimestamp}
  31. >
  32. <div className="absolute bottom-1 left-1">
  33. <Activity device={currentDevice} currentDeviceActive={isChannelActive} />
  34. </div>
  35. <div className="flex-auto relative w-full">
  36. <div
  37. className="absolute w-full h-full"
  38. style={{
  39. paddingRight: 'calc(var(--size-scale-factor) * 1px)'
  40. }}
  41. >
  42. <Keyboard
  43. key={range}
  44. height="100%"
  45. startKey={startKey}
  46. endKey={endKey}
  47. keyChannels={keyChannels}
  48. keyComponents={{
  49. natural: StyledNaturalKey,
  50. accidental: StyledAccidentalKey
  51. }}
  52. />
  53. </div>
  54. </div>
  55. <div className="flex sm:gap-16 w-full justify-between sm:justify-center items-center px-4 gap-4">
  56. <div className="w=0 flex-auto hidden sm:block" />
  57. <div className="flex-shrink-0 pt-2 pb-8">
  58. <PedalBoard unaCorda={unaCorda} sostenuto={sostenuto} sustain={sustain} />
  59. </div>
  60. <div className="w-0 flex-auto flex items-center justify-end opacity-0 group-hover:opacity-100 transition-opacity">
  61. <form className="contents" onSubmit={handleAction}>
  62. <button
  63. type="submit"
  64. name="action"
  65. value="showSettings"
  66. className="h-10 border rounded overflow-hidden px-4"
  67. >
  68. Settings
  69. </button>
  70. </form>
  71. </div>
  72. </div>
  73. </div>
  74. )
  75. }
  76. export default IndexPage