From 144e52df2b07284a56669b6bcdf71b7f6e11c585 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= <tm@tlater.net>
Date: Wed, 7 Apr 2021 23:23:21 +0100
Subject: [PATCH] Fix indentation

---
 src/index.ts                        | 192 ++++++++--------
 src/music/MusicPlayer.tsx           | 102 ++++-----
 src/music/components/controls.tsx   |  54 ++---
 src/music/components/indicator.tsx  |  66 +++---
 src/music/components/visualizer.tsx | 344 ++++++++++++++--------------
 src/music/index.tsx                 |  20 +-
 src/music/store/index.ts            |  10 +-
 src/music/store/music/reducers.ts   |  60 ++---
 src/music/store/music/types.ts      |  30 +--
 9 files changed, 439 insertions(+), 439 deletions(-)

diff --git a/src/index.ts b/src/index.ts
index 5d868f1..f7e1d7b 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -6,114 +6,114 @@ import jQuery from "jquery";
  * "Types" out a DOM element, emulating the way a human might.
  */
 class Typer {
-  private element: JQuery;
-  private text: string;
-  private cursor: boolean;
-  private typed: number;
-  private min: number;
-  private max: number;
-  private blink_tick: number;
-  private blink_timeout: number;
-  private end?: number;
+    private element: JQuery;
+    private text: string;
+    private cursor: boolean;
+    private typed: number;
+    private min: number;
+    private max: number;
+    private blink_tick: number;
+    private blink_timeout: number;
+    private end?: number;
 
-  /**
-   * Create the typer.
-   * @param {HTMLElement} element - The element to type.
-   * @param {number} blink - The time between cursor blinks.
-   * @param {number} blink_timeout - How long the cursor should keep
-   *                                 blinking for after the text
-   *                                 finishes typing.
-   */
-  constructor(element: HTMLElement, blink: number, blink_timeout: number) {
-    // Retrieve the current content and wipe it. We also make the
-    // element visible if it was hidden.
-    this.element = $(element);
-    this.text = this.element.html();
-    this.element.html("");
-    this.element.css("visibility", "visible");
+    /**
+     * Create the typer.
+     * @param {HTMLElement} element - The element to type.
+     * @param {number} blink - The time between cursor blinks.
+     * @param {number} blink_timeout - How long the cursor should keep
+     *                                 blinking for after the text
+     *                                 finishes typing.
+     */
+    constructor(element: HTMLElement, blink: number, blink_timeout: number) {
+        // Retrieve the current content and wipe it. We also make the
+        // element visible if it was hidden.
+        this.element = $(element);
+        this.text = this.element.html();
+        this.element.html("");
+        this.element.css("visibility", "visible");
 
-    this.cursor = false;
-    this.typed = 0;
+        this.cursor = false;
+        this.typed = 0;
 
-    this.min = 20;
-    this.max = 70;
-    this.blink_tick = blink;
-    this.blink_timeout = blink_timeout;
+        this.min = 20;
+        this.max = 70;
+        this.blink_tick = blink;
+        this.blink_timeout = blink_timeout;
 
-    this.end = null;
-  }
-
-  /**
-   * Start typing.
-   */
-  type() {
-    this._type();
-    this._blink();
-  }
-
-  /**
-   * Draw the current text line, i.e., anything that has been typed
-   * so far, and a cursor if it is currently supposed to be on.
-   * @private
-   */
-  _draw() {
-    let text = this.text.slice(0, this.typed);
-
-    if (this.cursor) {
-      text += "\u2588";
+        this.end = null;
     }
 
-    window.requestAnimationFrame(() => this.element.html(text));
-  }
-
-  /**
-   * Type the next character, and prepare to draw the next one. If
-   * no new characters are to be drawn, set the end timestamp.
-   * @private
-   */
-  _type() {
-    this.typed += 1;
-    this._draw();
-
-    if (this.typed != this.text.length)
-      setTimeout(this._type.bind(this), this._type_tick());
-    else {
-      this.end = Date.now();
+    /**
+     * Start typing.
+     */
+    type() {
+        this._type();
+        this._blink();
     }
-  }
 
-  /**
-   * Make the cursor change blink status, and prepare for the next
-   * blink.
-   * @private
-   */
-  _blink() {
-    this.cursor = !this.cursor;
-    this._draw();
+    /**
+     * Draw the current text line, i.e., anything that has been typed
+     * so far, and a cursor if it is currently supposed to be on.
+     * @private
+     */
+    _draw() {
+        let text = this.text.slice(0, this.typed);
 
-    // As long as we are typing, keep blinking
-    if (this.typed != this.text.length)
-      setTimeout(this._blink.bind(this), this.blink_tick);
-    // Once typing ends, keep going for a little bit
-    else if (Date.now() - this.end < this.blink_timeout)
-      setTimeout(this._blink.bind(this), this.blink_tick);
-    // Make sure we get rid of the cursor in the end
-    else {
-      this.cursor = true;
-      setTimeout(this._blink.bind(this), this.blink_tick);
+        if (this.cursor) {
+            text += "\u2588";
+        }
+
+        window.requestAnimationFrame(() => this.element.html(text));
     }
-  }
 
-  /**
-   * Calculate a "human" time for the next character to type.
-   * @private
-   */
-  _type_tick() {
-    return Math.round(Math.random() * this.max) + this.min;
-  }
+    /**
+     * Type the next character, and prepare to draw the next one. If
+     * no new characters are to be drawn, set the end timestamp.
+     * @private
+     */
+    _type() {
+        this.typed += 1;
+        this._draw();
+
+        if (this.typed != this.text.length)
+            setTimeout(this._type.bind(this), this._type_tick());
+        else {
+            this.end = Date.now();
+        }
+    }
+
+    /**
+     * Make the cursor change blink status, and prepare for the next
+     * blink.
+     * @private
+     */
+    _blink() {
+        this.cursor = !this.cursor;
+        this._draw();
+
+        // As long as we are typing, keep blinking
+        if (this.typed != this.text.length)
+            setTimeout(this._blink.bind(this), this.blink_tick);
+        // Once typing ends, keep going for a little bit
+        else if (Date.now() - this.end < this.blink_timeout)
+            setTimeout(this._blink.bind(this), this.blink_tick);
+        // Make sure we get rid of the cursor in the end
+        else {
+            this.cursor = true;
+            setTimeout(this._blink.bind(this), this.blink_tick);
+        }
+    }
+
+    /**
+     * Calculate a "human" time for the next character to type.
+     * @private
+     */
+    _type_tick() {
+        return Math.round(Math.random() * this.max) + this.min;
+    }
 }
 
 jQuery(($) => {
-  const typer = new Typer($(".head-line .typed").get(0), 500, 3000);
-  typer.type();
+    const typer = new Typer($(".head-line .typed").get(0), 500, 3000);
+    typer.type();
 });
diff --git a/src/music/MusicPlayer.tsx b/src/music/MusicPlayer.tsx
index a3c5f31..3960bf7 100644
--- a/src/music/MusicPlayer.tsx
+++ b/src/music/MusicPlayer.tsx
@@ -22,73 +22,73 @@ class MusicPlayer extends React.Component<MusicPlayerProps, State> {
   private audioState: AudioState;
 
   constructor(props: MusicPlayerProps) {
-    super(props);
+      super(props);
 
-    const context = new AudioContext();
-    const source = new Audio();
-    const sourceNode = context.createMediaElementSource(source);
-    const volume = context.createGain();
+      const context = new AudioContext();
+      const source = new Audio();
+      const sourceNode = context.createMediaElementSource(source);
+      const volume = context.createGain();
 
-    sourceNode.connect(volume);
-    volume.connect(context.destination);
+      sourceNode.connect(volume);
+      volume.connect(context.destination);
 
-    this.audioState = {
-      audioContext: context,
-      audioSourceNode: sourceNode,
-      audioSource: source,
-      audioVolume: volume,
-    };
+      this.audioState = {
+          audioContext: context,
+          audioSourceNode: sourceNode,
+          audioSource: source,
+          audioVolume: volume,
+      };
   }
 
   render() {
-    return (
-      <div id="player" style={{ height: "100%", width: "100%" }}>
-        <Visualizer
-          audioContext={this.audioState.audioContext}
-          audioSource={this.audioState.audioSourceNode}
-        />
-        <Controls />
-      </div>
-    );
+      return (
+          <div id="player" style={{ height: "100%", width: "100%" }}>
+              <Visualizer
+                  audioContext={this.audioState.audioContext}
+                  audioSource={this.audioState.audioSourceNode}
+              />
+              <Controls />
+          </div>
+      );
   }
 
   componentDidUpdate() {
-    const context = this.audioState.audioContext;
-    const source = this.audioState.audioSource;
-    const volume = this.audioState.audioVolume;
+      const context = this.audioState.audioContext;
+      const source = this.audioState.audioSource;
+      const volume = this.audioState.audioVolume;
 
-    // First, set the audio source (if it changed)
-    if (this.props.source && source.src != this.props.source) {
-      source.src = this.props.source;
-    }
+      // First, set the audio source (if it changed)
+      if (this.props.source && source.src != this.props.source) {
+          source.src = this.props.source;
+      }
 
-    if (this.props.playing) {
-      source
-        .play()
-        .then(() => {
-          console.info("Started playing audio");
-        })
-        .catch((error) => {
-          console.error(`Could not play audio: ${error}`);
-        });
-    } else {
-      source.pause();
-    }
+      if (this.props.playing) {
+          source
+              .play()
+              .then(() => {
+                  console.info("Started playing audio");
+              })
+              .catch((error) => {
+                  console.error(`Could not play audio: ${error}`);
+              });
+      } else {
+          source.pause();
+      }
 
-    if (!this.props.muted) {
-      volume.gain.setValueAtTime(1, context.currentTime);
-    } else {
-      volume.gain.setValueAtTime(0, context.currentTime);
-    }
+      if (!this.props.muted) {
+          volume.gain.setValueAtTime(1, context.currentTime);
+      } else {
+          volume.gain.setValueAtTime(0, context.currentTime);
+      }
   }
 }
 
 function mapStateToProps(state: State): MusicPlayerProps {
-  return {
-    playing: state.musicState.playing,
-    muted: state.musicState.muted,
-    source: state.musicState.source,
-  };
+    return {
+        playing: state.musicState.playing,
+        muted: state.musicState.muted,
+        source: state.musicState.source,
+    };
 }
 
 export default connect(mapStateToProps)(MusicPlayer);
diff --git a/src/music/components/controls.tsx b/src/music/components/controls.tsx
index 851cce1..c812d0e 100644
--- a/src/music/components/controls.tsx
+++ b/src/music/components/controls.tsx
@@ -6,44 +6,44 @@ import { Title } from "../store/music/types";
 import Indicator from "./indicator";
 
 type ControlProps = {
-  title: Title;
+    title: Title;
 };
 
 class Controls extends React.Component<ControlProps, State> {
-  render() {
-    return (
-      <div id="playerControls" className="container-fluid fixed-bottom">
-        <div className="align-items-center row p-2">
-          <Indicator></Indicator>
-          <div
-            id="playerText"
-            className="text-justify text-truncate col-6 playerControlsContent"
-          >
-            {this.props.title.name} - {this.props.title.album}
-          </div>
+    render() {
+        return (
+            <div id="playerControls" className="container-fluid fixed-bottom">
+                <div className="align-items-center row p-2">
+                    <Indicator></Indicator>
+                    <div
+                        id="playerText"
+                        className="text-justify text-truncate col-6 playerControlsContent"
+                    >
+                        {this.props.title.name} - {this.props.title.album}
+                    </div>
 
-          {this.props.title.name === "Journey" &&
-          this.props.title.artist === "Mseq" ? (
-            <div id="copyrightNotice" className="col text-center">
-              <a href="http://dig.ccmixter.org/files/Mseq/54702">Journey</a>
+                    {this.props.title.name === "Journey" &&
+                        this.props.title.artist === "Mseq" ? (
+                            <div id="copyrightNotice" className="col text-center">
+                                <a href="http://dig.ccmixter.org/files/Mseq/54702">Journey</a>
               &nbsp;by Mseq (c) copyright 2016 Licensed under a Creative
               Commons&nbsp;
-              <a href="http://creativecommons.org/licenses/by-nc/3.0/">
-                Attribution Noncommercial (3.0)
-              </a>
+                                <a href="http://creativecommons.org/licenses/by-nc/3.0/">
+                                    Attribution Noncommercial (3.0)
+                                </a>
               &nbsp; license. Ft: Admiral Bob,Texas Radio Fish
+                            </div>
+                        ) : null}
+                </div>
             </div>
-          ) : null}
-        </div>
-      </div>
-    );
-  }
+        );
+    }
 }
 
 function mapStateToProps(state: State): ControlProps {
-  return {
-    title: state.musicState.title,
-  };
+    return {
+        title: state.musicState.title,
+    };
 }
 
 export default connect(mapStateToProps)(Controls);
diff --git a/src/music/components/indicator.tsx b/src/music/components/indicator.tsx
index b033f4f..d916391 100644
--- a/src/music/components/indicator.tsx
+++ b/src/music/components/indicator.tsx
@@ -6,55 +6,55 @@ import { Dispatch, State } from "../store";
 import { togglePlay } from "../store/music/types";
 
 type IndicatorProps = {
-  muted: boolean;
-  playing: boolean;
+    muted: boolean;
+    playing: boolean;
 };
 
 type IndicatorDispatch = {
-  play: () => void;
+    play: () => void;
 };
 
 type Props = IndicatorProps & IndicatorDispatch;
 
 class Indicator extends React.Component<Props, State> {
-  click() {
-    this.props.play();
-  }
+    click() {
+        this.props.play();
+    }
 
-  render() {
-    const classes = classNames({
-      btn: true,
-      "col-auto": true,
-      fas: true,
-      "fa-muted": this.props.muted,
-      "fa-play": this.props.playing,
-      "fa-pause": !this.props.playing,
-    });
+    render() {
+        const classes = classNames({
+            btn: true,
+            "col-auto": true,
+            fas: true,
+            "fa-muted": this.props.muted,
+            "fa-play": this.props.playing,
+            "fa-pause": !this.props.playing,
+        });
 
-    return (
-      <button
-        type="button"
-        id="playerIndicator"
-        onClick={this.click.bind(this)}
-        className={classes}
-      ></button>
-    );
-  }
+        return (
+            <button
+                type="button"
+                id="playerIndicator"
+                onClick={this.click.bind(this)}
+                className={classes}
+            ></button>
+        );
+    }
 }
 
 function mapStateToProps(state: State): IndicatorProps {
-  return {
-    muted: state.musicState.muted,
-    playing: state.musicState.playing,
-  };
+    return {
+        muted: state.musicState.muted,
+        playing: state.musicState.playing,
+    };
 }
 
 function mapDispatchToProps(dispatch: Dispatch): IndicatorDispatch {
-  return {
-    play: () => {
-      dispatch(togglePlay());
-    },
-  };
+    return {
+        play: () => {
+            dispatch(togglePlay());
+        },
+    };
 }
 
 export default connect(mapStateToProps, mapDispatchToProps)(Indicator);
diff --git a/src/music/components/visualizer.tsx b/src/music/components/visualizer.tsx
index 53dfdf3..7fcda45 100644
--- a/src/music/components/visualizer.tsx
+++ b/src/music/components/visualizer.tsx
@@ -4,217 +4,217 @@ import * as three from "three";
 import { State } from "../store";
 
 type VisualizerProps = {
-  audioContext: AudioContext;
-  audioSource: AudioNode;
+    audioContext: AudioContext;
+    audioSource: AudioNode;
 };
 
 class CanvasDrawer {
-  private analyser: AnalyserNode;
-  private canvas: HTMLCanvasElement;
+    private analyser: AnalyserNode;
+    private canvas: HTMLCanvasElement;
 
-  private analyserData: Float32Array;
+    private analyserData: Float32Array;
 
-  private boxes: Array<three.Mesh>;
-  private camera: three.PerspectiveCamera;
-  private renderer: three.WebGLRenderer;
-  private scene: three.Scene;
+    private boxes: Array<three.Mesh>;
+    private camera: three.PerspectiveCamera;
+    private renderer: three.WebGLRenderer;
+    private scene: three.Scene;
 
-  private angle: number;
+    private angle: number;
 
-  private animationFrame: number;
-  private lastTime: number;
+    private animationFrame: number;
+    private lastTime: number;
 
-  constructor(analyser: AnalyserNode, canvas: HTMLCanvasElement) {
-    this.analyser = analyser;
-    this.canvas = canvas;
+    constructor(analyser: AnalyserNode, canvas: HTMLCanvasElement) {
+        this.analyser = analyser;
+        this.canvas = canvas;
 
-    // Set up analyser data storage
-    this.analyserData = new Float32Array(analyser.frequencyBinCount);
+        // Set up analyser data storage
+        this.analyserData = new Float32Array(analyser.frequencyBinCount);
 
-    // Initialize the scene
-    this.scene = new three.Scene();
+        // Initialize the scene
+        this.scene = new three.Scene();
 
-    // Make a bunch of boxes to represent the bars
-    this.boxes = Array(analyser.frequencyBinCount);
-    const width = 2 / analyser.frequencyBinCount;
-    for (let freq = 0; freq < analyser.frequencyBinCount; freq++) {
-      const geometry = new three.BoxGeometry(1, 1, 1);
-      const material = new three.MeshLambertMaterial({
-        color: new three.Color(0x99d1ce),
-      });
-      const cube = new three.Mesh(geometry, material);
+        // Make a bunch of boxes to represent the bars
+        this.boxes = Array(analyser.frequencyBinCount);
+        const width = 2 / analyser.frequencyBinCount;
+        for (let freq = 0; freq < analyser.frequencyBinCount; freq++) {
+            const geometry = new three.BoxGeometry(1, 1, 1);
+            const material = new three.MeshLambertMaterial({
+                color: new three.Color(0x99d1ce),
+            });
+            const cube = new three.Mesh(geometry, material);
 
-      cube.scale.set(width, 1e-6, width);
-      cube.position.set(-1 + freq * width, 0, 0);
+            cube.scale.set(width, 1e-6, width);
+            cube.position.set(-1 + freq * width, 0, 0);
 
-      this.scene.add(cube);
-      this.boxes[freq] = cube;
+            this.scene.add(cube);
+            this.boxes[freq] = cube;
+        }
+
+        // Add lights for shadowing
+        const ambientLight = new three.AmbientLight(0xffffff, 0.4);
+        this.scene.add(ambientLight);
+
+        const directionalLight = new three.DirectionalLight(0xffffff, 1);
+        directionalLight.position.set(-1, 0.3, -1);
+        directionalLight.castShadow = true;
+        this.scene.add(directionalLight);
+
+        // Add a camera
+        this.angle = 3;
+        this.camera = new three.PerspectiveCamera(
+            70,
+            canvas.width / canvas.height,
+            0.01,
+            10
+        );
+        this.camera.lookAt(0, 0, 0);
+        this.scene.add(this.camera);
+        this.rotateCamera(1);
+
+        // Add a renderer
+        this.renderer = new three.WebGLRenderer({
+            antialias: true,
+            canvas: canvas,
+            powerPreference: "low-power",
+        });
+
+        this.renderer.setClearColor(new three.Color(0x0f0f0f));
+        this.renderer.setSize(canvas.width, canvas.height);
+
+        // Set up canvas resizing
+        window.addEventListener("resize", this.resize.bind(this));
+
+        // Run the first, set the first animation frame time and start requesting
+        // animation frames
+        this.resize();
+        this.lastTime = 0;
+        this.animationFrame = requestAnimationFrame(this.render.bind(this));
     }
 
-    // Add lights for shadowing
-    const ambientLight = new three.AmbientLight(0xffffff, 0.4);
-    this.scene.add(ambientLight);
+    render(time: number) {
+        // Set our animation frame to 0, so that if we stop, we don't try to cancel a past animation frame
+        this.animationFrame = 0;
+        // Update elapsed time
+        const elapsed = time - this.lastTime;
+        this.lastTime = time;
 
-    const directionalLight = new three.DirectionalLight(0xffffff, 1);
-    directionalLight.position.set(-1, 0.3, -1);
-    directionalLight.castShadow = true;
-    this.scene.add(directionalLight);
+        const camera = this.camera;
+        const renderer = this.renderer;
+        const scene = this.scene;
 
-    // Add a camera
-    this.angle = 3;
-    this.camera = new three.PerspectiveCamera(
-      70,
-      canvas.width / canvas.height,
-      0.01,
-      10
-    );
-    this.camera.lookAt(0, 0, 0);
-    this.scene.add(this.camera);
-    this.rotateCamera(1);
+        this.scaleBoxes();
+        this.rotateCamera(elapsed);
 
-    // Add a renderer
-    this.renderer = new three.WebGLRenderer({
-      antialias: true,
-      canvas: canvas,
-      powerPreference: "low-power",
-    });
-
-    this.renderer.setClearColor(new three.Color(0x0f0f0f));
-    this.renderer.setSize(canvas.width, canvas.height);
-
-    // Set up canvas resizing
-    window.addEventListener("resize", this.resize.bind(this));
-
-    // Run the first, set the first animation frame time and start requesting
-    // animation frames
-    this.resize();
-    this.lastTime = 0;
-    this.animationFrame = requestAnimationFrame(this.render.bind(this));
-  }
-
-  render(time: number) {
-    // Set our animation frame to 0, so that if we stop, we don't try to cancel a past animation frame
-    this.animationFrame = 0;
-    // Update elapsed time
-    const elapsed = time - this.lastTime;
-    this.lastTime = time;
-
-    const camera = this.camera;
-    const renderer = this.renderer;
-    const scene = this.scene;
-
-    this.scaleBoxes();
-    this.rotateCamera(elapsed);
-
-    renderer.render(scene, camera);
-    this.animationFrame = requestAnimationFrame(this.render.bind(this));
-  }
-
-  scaleBoxes() {
-    const analyser = this.analyser;
-
-    analyser.getFloatFrequencyData(this.analyserData);
-
-    for (let freq = 0; freq < analyser.frequencyBinCount; freq++) {
-      let height = analyser.maxDecibels / this.analyserData[freq];
-
-      if (height > 0.3) {
-        height -= 0.3;
-      } else {
-        height = 1e-6;
-      }
-
-      this.boxes[freq].scale.y = height;
-    }
-  }
-
-  rotateCamera(elapsed: number) {
-    if (this.angle >= Math.PI * 2) {
-      this.angle = 0;
-    } else {
-      this.angle += 0.1 * (elapsed / 1000);
+        renderer.render(scene, camera);
+        this.animationFrame = requestAnimationFrame(this.render.bind(this));
     }
 
-    const camera = this.camera;
-    const angle = this.angle;
+    scaleBoxes() {
+        const analyser = this.analyser;
 
-    camera.position.x = 1.01 * Math.sin(angle);
-    camera.position.z = 1.01 * Math.cos(angle);
+        analyser.getFloatFrequencyData(this.analyserData);
 
-    /* camera.position.y = (1 - Math.abs(angle - 0.5) / 0.5); */
-    camera.lookAt(0, 0, 0);
-  }
+        for (let freq = 0; freq < analyser.frequencyBinCount; freq++) {
+            let height = analyser.maxDecibels / this.analyserData[freq];
 
-  resize() {
-    const canvas = this.canvas;
-    if (canvas.parentElement === null) {
-      throw Error("Could not access canvas parent for size calculation");
+            if (height > 0.3) {
+                height -= 0.3;
+            } else {
+                height = 1e-6;
+            }
+
+            this.boxes[freq].scale.y = height;
+        }
     }
 
-    // Compute the height of all our siblings
-    let combinedHeight = 0;
-    for (let i = 0; i < canvas.parentElement.children.length; i++) {
-      const child = canvas.parentElement.children[i];
+    rotateCamera(elapsed: number) {
+        if (this.angle >= Math.PI * 2) {
+            this.angle = 0;
+        } else {
+            this.angle += 0.1 * (elapsed / 1000);
+        }
 
-      if (child != canvas) {
-        combinedHeight += child.clientHeight;
-      }
+        const camera = this.camera;
+        const angle = this.angle;
+
+        camera.position.x = 1.01 * Math.sin(angle);
+        camera.position.z = 1.01 * Math.cos(angle);
+
+        /* camera.position.y = (1 - Math.abs(angle - 0.5) / 0.5); */
+        camera.lookAt(0, 0, 0);
     }
 
-    // The remaining space we want to fill
-    const remainingHeight = canvas.parentElement.clientHeight - combinedHeight;
-    canvas.height = remainingHeight;
-    canvas.width = canvas.parentElement.clientWidth;
+    resize() {
+        const canvas = this.canvas;
+        if (canvas.parentElement === null) {
+            throw Error("Could not access canvas parent for size calculation");
+        }
 
-    this.camera.aspect = canvas.width / remainingHeight;
-    this.camera.updateProjectionMatrix();
-    this.renderer.setSize(canvas.width, remainingHeight);
-  }
+        // Compute the height of all our siblings
+        let combinedHeight = 0;
+        for (let i = 0; i < canvas.parentElement.children.length; i++) {
+            const child = canvas.parentElement.children[i];
 
-  stop() {
-    if (this.animationFrame != 0) {
-      cancelAnimationFrame(this.animationFrame);
+            if (child != canvas) {
+                combinedHeight += child.clientHeight;
+            }
+        }
+
+        // The remaining space we want to fill
+        const remainingHeight = canvas.parentElement.clientHeight - combinedHeight;
+        canvas.height = remainingHeight;
+        canvas.width = canvas.parentElement.clientWidth;
+
+        this.camera.aspect = canvas.width / remainingHeight;
+        this.camera.updateProjectionMatrix();
+        this.renderer.setSize(canvas.width, remainingHeight);
+    }
+
+    stop() {
+        if (this.animationFrame != 0) {
+            cancelAnimationFrame(this.animationFrame);
+        }
     }
-  }
 }
 
 class Visualizer extends React.Component<VisualizerProps, State> {
-  private analyser: AnalyserNode;
-  private canvas: React.RefObject<HTMLCanvasElement>;
-  private drawer: CanvasDrawer;
+    private analyser: AnalyserNode;
+    private canvas: React.RefObject<HTMLCanvasElement>;
+    private drawer: CanvasDrawer;
 
-  constructor(props: VisualizerProps) {
-    super(props);
-    this.canvas = React.createRef();
-  }
-
-  render(): React.ReactNode {
-    return (
-      <canvas
-        id="visualizer"
-        ref={this.canvas}
-        style={{ width: "100%", height: "100%" }}
-      ></canvas>
-    );
-  }
-
-  componentDidMount(): void {
-    if (this.canvas.current === null) {
-      throw Error("Failed to create canvas; aborting");
+    constructor(props: VisualizerProps) {
+        super(props);
+        this.canvas = React.createRef();
     }
 
-    this.analyser = this.props.audioContext.createAnalyser();
-    this.analyser.fftSize = 2048;
-    this.analyser.smoothingTimeConstant = 0.8;
-    this.props.audioSource.connect(this.analyser);
+    render(): React.ReactNode {
+        return (
+            <canvas
+                id="visualizer"
+                ref={this.canvas}
+                style={{ width: "100%", height: "100%" }}
+            ></canvas>
+        );
+    }
 
-    this.drawer = new CanvasDrawer(this.analyser, this.canvas.current);
-  }
+    componentDidMount(): void {
+        if (this.canvas.current === null) {
+            throw Error("Failed to create canvas; aborting");
+        }
 
-  componentWillUnmount(): void {
-    this.drawer.stop();
-    this.props.audioSource.disconnect(this.analyser);
-  }
+        this.analyser = this.props.audioContext.createAnalyser();
+        this.analyser.fftSize = 2048;
+        this.analyser.smoothingTimeConstant = 0.8;
+        this.props.audioSource.connect(this.analyser);
+
+        this.drawer = new CanvasDrawer(this.analyser, this.canvas.current);
+    }
+
+    componentWillUnmount(): void {
+        this.drawer.stop();
+        this.props.audioSource.disconnect(this.analyser);
+    }
 }
 
 export default Visualizer;
diff --git a/src/music/index.tsx b/src/music/index.tsx
index bc31bdd..f11df8f 100644
--- a/src/music/index.tsx
+++ b/src/music/index.tsx
@@ -11,18 +11,18 @@ import mseq from "./Mseq_-_Journey.mp3";
 const rootElement = document.getElementById("playerUI");
 
 ReactDOM.render(
-  <Provider store={store}>
-    <MusicPlayer />
-  </Provider>,
-  rootElement
+    <Provider store={store}>
+        <MusicPlayer />
+    </Provider>,
+    rootElement
 );
 
 store.dispatch(setSource(mseq));
 store.dispatch(
-  setTitle({
-    name: "Journey",
-    artist: "Mseq",
-    album: "Unknown album",
-    length: 192052244,
-  })
+    setTitle({
+        name: "Journey",
+        artist: "Mseq",
+        album: "Unknown album",
+        length: 192052244,
+    })
 );
diff --git a/src/music/store/index.ts b/src/music/store/index.ts
index 8b2344d..3326f13 100644
--- a/src/music/store/index.ts
+++ b/src/music/store/index.ts
@@ -4,17 +4,17 @@ import { MusicState } from "./music/types";
 import { musicStateReducer } from "./music/reducers";
 
 export interface State {
-  musicState: MusicState;
+    musicState: MusicState;
 }
 
 const rootReducer = combineReducers<State>({
-  musicState: musicStateReducer,
+    musicState: musicStateReducer,
 });
 
 export const store = createStore(
-  rootReducer,
-  // @ts-ignore - These properties are set by the devtools extension
-  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
+    rootReducer,
+    // @ts-ignore - These properties are set by the devtools extension
+    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
 );
 
 export type Dispatch = typeof store.dispatch;
diff --git a/src/music/store/music/reducers.ts b/src/music/store/music/reducers.ts
index 83883d1..f351d60 100644
--- a/src/music/store/music/reducers.ts
+++ b/src/music/store/music/reducers.ts
@@ -2,44 +2,44 @@ import { createReducer } from "redux-act";
 import update from "immutability-helper";
 
 import {
-  Title,
-  MusicState,
-  setTitle,
-  toggleMute,
-  togglePlay,
-  setSource,
+    Title,
+    MusicState,
+    setTitle,
+    toggleMute,
+    togglePlay,
+    setSource,
 } from "./types";
 
 const defaultTitle: Title = {
-  name: "Untitled",
-  artist: "Unknown Artist",
-  album: "Unknown Album",
-  length: 0,
+    name: "Untitled",
+    artist: "Unknown Artist",
+    album: "Unknown Album",
+    length: 0,
 };
 
 const initialState: MusicState = {
-  muted: false,
-  playing: false,
-  title: defaultTitle,
-  playTime: 0,
+    muted: false,
+    playing: false,
+    title: defaultTitle,
+    playTime: 0,
 };
 
 export const musicStateReducer = createReducer<MusicState>(
-  {
-    [setTitle]: (state: MusicState, title: Title): MusicState => {
-      return update(state, {
-        title: { $set: title },
-      });
+    {
+        [setTitle]: (state: MusicState, title: Title): MusicState => {
+            return update(state, {
+                title: { $set: title },
+            });
+        },
+        [togglePlay]: (state: MusicState): MusicState => {
+            return update(state, { $toggle: ["playing"] });
+        },
+        [toggleMute]: (state: MusicState): MusicState => {
+            return update(state, { $toggle: ["muted"] });
+        },
+        [setSource]: (state: MusicState, source: string): MusicState => {
+            return update(state, { source: { $set: source } });
+        },
     },
-    [togglePlay]: (state: MusicState): MusicState => {
-      return update(state, { $toggle: ["playing"] });
-    },
-    [toggleMute]: (state: MusicState): MusicState => {
-      return update(state, { $toggle: ["muted"] });
-    },
-    [setSource]: (state: MusicState, source: string): MusicState => {
-      return update(state, { source: { $set: source } });
-    },
-  },
-  initialState
+    initialState
 );
diff --git a/src/music/store/music/types.ts b/src/music/store/music/types.ts
index 3ddc95e..13124be 100644
--- a/src/music/store/music/types.ts
+++ b/src/music/store/music/types.ts
@@ -1,29 +1,29 @@
 import { Action, createAction } from "redux-act";
 
 export interface Title {
-  name: string;
-  artist: string;
-  album: string;
-  /**
-   * The length of the title in nanoseconds.
-   */
-  length: number;
+    name: string;
+    artist: string;
+    album: string;
+    /**
+     * The length of the title in nanoseconds.
+     */
+    length: number;
 }
 
 export interface MusicState {
-  muted: boolean;
-  playing: boolean;
-  title: Title;
-  playTime: number;
-  source?: string;
+    muted: boolean;
+    playing: boolean;
+    title: Title;
+    playTime: number;
+    source?: string;
 }
 
 export const setTitle: (_title: Title) => Action<null, null> = createAction(
-  "set currently playing title"
+    "set currently playing title"
 );
 
 export const setPlayTime: (_time: number) => Action<null, null> = createAction(
-  "set the play time"
+    "set the play time"
 );
 
 export const toggleMute: () => Action<null, null> = createAction("toggle mute");
@@ -31,5 +31,5 @@ export const toggleMute: () => Action<null, null> = createAction("toggle mute");
 export const togglePlay: () => Action<null, null> = createAction("toggle play");
 
 export const setSource: (_source: string) => Action<null, null> = createAction(
-  "set the title"
+    "set the title"
 );