Code Monkey home page Code Monkey logo

midicast's Introduction

Midicast

a web extension that streams songs from a web page to a MIDI instrument

How does it work?

Midicast scans the page you're on for MIDI links. Whatever it finds will show up in a list in the extension. Click one of the songs in the extension to start playing it. Midicast should work with any instrument that accepts MIDI input, such as a Yamaha Disklavier® player piano.

Installation

Midicast is available on the Chrome Web Store.

Troubleshooting

Your MIDI instrument must be connected to your computer. If you are using a Mac and your instrument supports Bluetooth®, open the Audio MIDI Setup app and click Bluetooth:

In the dialog that opens, click Connect next to your instrument:

Architecture

Midicast uses Cycle.js to model dataflow. Each "cycle" receives a collection of input streams and transforms them into output streams, which are captured by "drivers" to draw UI or play notes.

Most of the logic lives in Background.ts. That cycle receives a stream of messages from the UI and outputs a stream of notes to send to the instrument.

Popup.tsx draws the UI when the user clicks the toolbar icon. It displays playback controls, along with a tabbed pane where the user may select a song, or change which instruments are being played. Every time the popup opens, it requests the current state (such as which song is currently playing) from the background page.

SongScanner.tsx is a tab in the popup. It uses the hostPageDriver to search the currently-active tab for links that end in .mid, displaying them in a list. When the user clicks one of the list items, it sends this message to the background page:

{
  type: MessageType.PLAY_SONG,
  payload: {
    label: 'A Song Title',
    url: 'https://example.com/song.mid',
  },
}

The background page fetches the requested MIDI file. MIDI files contain "tracks," each representing the notes for a single instrument. Every 100ms, the background page dispatches the next pulse of notes. If the user has used the Instruments tab to filter tracks, only notes from those tracks will be included. Sending the notes one-pulse-at-a-time allows the user to filter tracks while the song is playing.

cycle-midi listens for notes and forwards them to the instrument with Web MIDI.

cycle-extensions connects the cycles to the web extensions APIs, which pass messages between the cycles, or between a cycle and the host page.

snab-style is a conceptual port of jsxstyle. It provides JSX elements like <Row>, <Column>, and <MaterialIcon> that expose their style attributes as props, making nodes easier to style.

License

Apache 2.0

Note: This is not an official Google product.

midicast's People

Contributors

appsforartists avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

midicast's Issues

Clean up code

Most of the code was written as a prototype. Check it for readability and refactor where helpful.

Return input stream from cycle-midi driver

This has been something I've wanted to do from the beginning, so I'm surprised I don't see an issue for it.

cycle-midi right now will send any notes it receives to the first instrument. It should also listen to notes from that instrument, and return a stream of them. This will allow a Cycle application to both write notes to an instrument and read notes from them.

Fix PLAY SONG button

The PLAY SONG button in the ENTER URL tab doesn't work if you paste into the field.

Support pedal usage in MIDI tracks

MIDI commands:

0xB0 0x07 0x00-7F: volume
0xB0 0x40 0x00-7F: sustain pedal
0xB0 0x43 0x00-7F: soft pedal
0xB0 0x42 0x00-7F: sostenuto pedal
0xB0 0x7B 0x00: all notes off
0xB0 0x78 0x00: all sounds off

Move cycle-extensions to own repo

Hi,

I'm working on an extension and would like to use/contribute to the cycle-extensions package, but it seems like it would make more sense if it had a repo to itself.

Any chance of that happening?

Upgrade Pundle

There are improvements that have been made to pundle since this was started (like automatically setting the debug flag). Upgrade and make the appropriate changes.

Production-quality manifest.json

manifest.json has some security settings disabled to make HMR work. We need a production-quality version.

What are the minimum necessary permissions? Can we defer asking for permission to
fetch until after a user does something?

Use declarativeContent + SetIcon to highlight the icon when a MIDI is found

midicast should be a browser_action rather than a page_action, to ensure the controls can be opened even when there are no MIDIs on the current page. Still, it would be a nice user experience for the icon to change when there are MIDIs available.

chrome.declarativeContent.SetIcon ought to be able to handle this, but it doesn't work with browser actions right now. Poke Devlin about this, and see when it's fixed. Then, use it.

Use separate entries for separate pages

If background.js and popup.js were individual bundles, we could do

"background": {
    "scripts": [
      "./dist/background.js"
    ]
}

instead of using the index.html background page. However, since Pundle only works on one entry (which is served from localhost), this would be hard to do without breaking the dev workflow.

(This was also advice from Devlin.)

Check timing

The timing sounds like it might be a bit off. Maybe the pulse is throwing it off?

Consolidate HTML pages

Both background.html and popup.html are just empty containers for Cycle to render to. Can we consolidate them?

Right now, Cycle determines which components to render based on location.href. We'd need a different sigil to determine which to render.

Channel setup screen

Right now, midicast defaults to channel 1. We should detect which channel a user's instrument uses.

A flow for detecting an instrument's channel:

  • Play a different note on each channel.
  • User repeats note, app deduces channel
  • App plays a different note on only that channel.
  • User repeats note to confirm correct channel.

Make pianoDriver into midiDriver (cycle-midi)

midiDriver could accept a stream of notes to send to an instrument and return a stream of notes from the instrument. This would make it useful independent of this particular extension.

Build a demo page

It ought to be fairly simple to build a demo page that shows off the extension without users having to install it. You'd basically just need to link the message buses to one another and seed hostPage$ with links.

Cache favorited songs

The user ought to be able to bookmark songs into a library. Perhaps that library could persist across devices.

Better types

Can we use the enums to be more specific with our types?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.