# Architecture ## Library/Application This repository contains both an NPM module, and a demo page, found at . The NPM module's goal is to provide a widget which can be embedded in any website, where as the demo page depends upon the library, and provides the canonical usage. You can find more information about the library's API in the [usage](./usage.md) document. * The entry point for the demo page is [index.js](../js/index.js) * The entry point for the NPM modules is [webamp.js](../js/webamp.js) ## Redux Within the core library, state is managed by [Redux]. In fact, Redux's own docs mention Webamp in the [Apps and Examples](https://redux.js.org/introduction/learning-resources#apps-and-examples) section of their docs! Our reducers, and the states they control, can be found in the [reducers](../js/reducers/) directory. Async actions are handled using the [redux-thunk]. You can find all of the actionCreators in the [actionCreators.js](../js/actionCreators.js) file. This is the most complex portion of the app, as it contains all the coordination of our many async actions. Any non-trivial value derived from state is computed inside a [selector](../js/selectors.js). Care has been taken to ensure that the structure of the state allows for most common selectors to be a constant time operation. For selectors that are `O(n)`, we use [reselect] to ensure the calculation is only done when dependent values change. Coordination between the playing media (which is inherently stateful, and changes over time) and Redux is handed in the [mediaMiddleware](../js/mediaMiddleware.js). This basically listens for events, and triggers the correct methods on our `Media` instance. It also listens events emitted by the media instance, and dispatches the corresponding actions. ## React We use [react-redux] to bind Redux state into our [React components](../js/components/). Any component which is not reusable, and even some that are, are connected using [connect]. This works well for us, since most components are "one off", and connecting most components allows for state changes to result in a mininmal set of react components needing to re-render. This does, however, require that our selectors be performant. In some places we use [rc-slider](https://github.com/react-component/slider) instead of `` since it gives us more precise control over styling. This is particualarly true for the vertial sliders in the equalizer window. As far as I can tell, there is no way to style the handle of a vertical `` in a way that gives pixel-level accuracy. ## Media Media (audio files) is managed by our [Media](../js/media/index.js) class. It encapsulates the Web Audio API complexity. Audio manipulation (volume, balance, EQ) is handled in the main `Media` class, but the audio source is managed in [elementSource.js](../js/media/elementSource.js). This class tries to encapsulate some of the complexity required to get the playing of audio files working across all browsers seamlessly. We handle playing audio from a URL source (subject to CORs) and from a local file. Both of these are normalized to a URL before they are passed into our audio aparatus. For local files, we convert the `ArrayBuffer` we get, into a Blob url using `URL.createObjectURL()`. This transformation is handlded inside our Action Creators (see the Redux section above). The `Winamp` class instantiates a single `Media` instance and passes it's [AnalyserNode](https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode) down through the tree of React components to the visualizer. ## Skins Winamp skins (`.wsz`) are, under the hood, just `.zip` files which contain `.bmp` sprite sheets, and some config files. We use [JSZip] to unpack the zip archive, and then some clever canvas slicing to extract the individual sprites out of each `.bmp`. We get these sprite images as [data URIs] which are dispatched to Redux. We then have a [Skin](../js/components/Skin.js) component which renders a `