packages feed

tianbar-1.1.1.1: scripts/volume.js

/* jshint esversion: 6 */
/*
 * A widget to show and control the system volume.
 *
 * Requires 'jquery' to be available through RequireJS.
 */
define(['jquery', './socket'], function ($, socket) {
  "use strict";

  const UID_RE = /Uid:\t(\d+)/;

  const VOLUME_RE = /set-sink-volume.+ ([^ \n]+)/;
  const MUTE_RE = /set-sink-mute.+ ([^ \n]+)/;

  const MAX_VOLUME = 0x10000;

  const WIDTH = 25;
  const HEIGHT = 25;

  const WAVES = 5;

  const self = {};

  self.settings_command = 'gnome-control-center sound';

  function uid() {
    return $.ajax('tianbar:///root/proc/self/status')
    .then(function (result) {
      return +UID_RE.exec(result)[1];
    });
  }

  self.widget = () => $('.widget-volume');

  self.display = function () {
    const widget = self.widget();

    const canvas = $('<canvas />').attr({
      width: WIDTH,
      height: HEIGHT
    });

    widget.empty();
    widget.append(canvas);

    const context = canvas[0].getContext('2d');

    const middle = WIDTH / 2 - 2;

    const speakerBaseH = 5;
    const speakerBaseW = 4;
    const speakerW = 5;
    const speakerH = 13;

    const spacing = 2;

    const crossSize = 6;

    // Draw a speaker
    context.beginPath();
    context.moveTo(0, middle - speakerBaseH / 2);
    context.lineTo(0, middle + speakerBaseH / 2);
    context.lineTo(speakerBaseW, middle + speakerBaseH / 2);
    context.lineTo(speakerBaseW + speakerW, middle + speakerH / 2);
    context.lineTo(speakerBaseW + speakerW, middle - speakerH / 2);
    context.lineTo(speakerBaseW, middle - speakerBaseH / 2);
    context.lineTo(0, middle - speakerBaseH / 2);
    context.fill();

    if (self.mute) {
      // Draw a cross
      const crossLeft = speakerBaseW + speakerW + spacing;

      context.save();
      context.lineWidth = 1.5;

      context.beginPath();
      context.moveTo(crossLeft, middle - crossSize / 2);
      context.lineTo(crossLeft + crossSize, middle + crossSize / 2);
      context.stroke();

      context.beginPath();
      context.moveTo(crossLeft + crossSize, middle - crossSize / 2);
      context.lineTo(crossLeft, middle + crossSize / 2);
      context.stroke();

      context.restore();
    } else {
      // Draw waves
      const waveAngle = Math.PI / 6;
      for (var i = 0; i < self.volume * WAVES; i ++) {
        context.beginPath();
        context.arc(
          0, middle,
          speakerBaseW + speakerW + spacing + 3 * i,
          waveAngle / 2, -waveAngle / 2,
          true);
        context.stroke();
      }
    }

    const percentage = self.volume.toFixed(2) * 100;
    widget.attr('title', percentage + '%');
  };

  $.when(
    $.ajax('tianbar:///execute', {
      data: {
        command: 'pacmd load-module module-cli-protocol-unix'
      }
    }),
    uid()
  ).then(function (_, uid) {
    return socket('/var/run/user/' + uid + '/pulse/cli');
  }).then(function (pulseSocket) {
    pulseSocket.recv.add(function (dump) {
      self.mute = MUTE_RE.exec(dump)[1] === "yes";
      self.volume = parseInt(VOLUME_RE.exec(dump)[1], 16) / MAX_VOLUME;

      self.display();

      window.setTimeout(requestDump, 1000);

    });

    function requestDump () {
      pulseSocket.send('dump\n');
    }

    requestDump();
  });

  $(document).ready(function () {
    self.widget().click(function () {
      $.ajax('tianbar:///spawn', {
        data: {
          command: self.settings_command
        }
      });
    });
  });

  return self;
});