basic formatting

This commit is contained in:
Daniel Bulant 2021-09-13 19:18:14 +02:00
parent 09cb648e5b
commit fd5bc47cb7
11 changed files with 132 additions and 58 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
/node_modules
/pnpm-lock.yaml
/pnpm-lock.yaml
dist

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"typescript.preferences.importModuleSpecifierEnding": "js"
}

11
README.md Normal file
View file

@ -0,0 +1,11 @@
# PS4 controller colors
I had the great idea to programatically set colors of my PS4 controller.
It's not supposed to be easy to setup, but if you need help just contact me. For now, scripts try to find all the connected joy sticks (doesn't filter by type) and set their LEDs (No idea what happens if a joystick doesn't have one), and then sets colors on them.
Project highly depends on linux (uses sys class to control the LEDs) and requires root (non-root operations are setuid'd internally).
## Spotify colors
Uses DBUS which needs your username. For now just edit the utils function getUsername to return your username.

View file

@ -1,28 +0,0 @@
import { JoyStick } from "./joystick";
const devices = await JoyStick.getList();
for(const device of devices) {
const colors = await device.getColors();
const max = await device.getMaxColors();
console.log(`Found device ${device.name}:
Colors:
RED ${colors.red}
GREEN ${colors.green}
BLUE ${colors.blue}
Max colors:
RED ${max.red}
GREEN ${max.green}
BLUE ${max.blue}`)
const newColors = {
red: Math.floor(Math.random() * max.red),
green: Math.floor(Math.random() * max.green),
blue: Math.floor(Math.random() * max.blue),
};
await device.setColors(newColors);
console.log(`
Updated colors:
RED ${newColors.red}
GREEN ${newColors.green}
BLUE ${newColors.blue}`);
}

View file

@ -1,4 +1,4 @@
import { exec, readUTF, writeUTF } from "./utils";
import { exec, readUTF, writeUTF } from "./utils.js";
import * as fs from "fs";
interface IJoyStick {

View file

@ -1,6 +1,10 @@
{
"dependencies": {
"@types/node": "^16.9.1",
"got": "^11.8.2",
"node-vibrant": "^3.2.1-alpha.1"
}
"node-vibrant": "^3.2.1-alpha.1",
"ts-node": "^10.2.1",
"typescript": "^4.4.3"
},
"type": "module"
}

View file

@ -1,21 +0,0 @@
import { exec } from "./utils";
interface Track {
length: number;
artURL: string;
id: string;
url: string;
artist: string;
album: string;
albumArtist: string;
}
class Spotify {
async getCurrentTrack() {
const data: Record<string, string> = {};
const out = await exec(["qdbus", "org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player.Metadata"]);
}
}
export default new Spotify();

48
spotifyColors/index.ts Normal file
View file

@ -0,0 +1,48 @@
import { JoyStick } from "../joystick.js";
import spotify from "./spotify.js";
import { getColor, lerp } from "../utils.js";
type ThenArg<T> = T extends PromiseLike<infer U> ? U : T;
type Palette = ThenArg<ReturnType<typeof getColor>>;
const devices = await JoyStick.getList();
var color: Palette, lastURL: string, lastColor: Palette["DarkMuted"];
const perColor = 1000;
setInterval(async () => {
const track = await spotify.getCurrentTrack();
if(lastURL !== track.artURL) {
console.log("Track:", track.artist, "-", track.title);
color = await getColor(track.artURL);
lastURL = track.artURL;
}
function transitionColors(startColor: Palette["DarkMuted"], endColor: Palette["DarkMuted"]) {
return new Promise<void>((resolve) => {
const start = Date.now();
var i = setInterval(async() => {
if(start + perColor < Date.now()) {
resolve();
return clearInterval(i);
}
const progress = (Date.now() - start) / perColor;
const newColors = {
red: Math.round(lerp(startColor.r, endColor.r, progress)),
green: Math.round(lerp(startColor.g, endColor.g, progress)),
blue: Math.round(lerp(startColor.b, endColor.b, progress)),
};
for(const device of devices) {
await device.setColors(newColors);
}
}, 10);
});
}
await transitionColors(lastColor || color.LightMuted, color.LightVibrant);
await transitionColors(color.LightVibrant, color.Vibrant);
await transitionColors(color.Vibrant, color.DarkVibrant);
lastColor = color.DarkVibrant;
}, perColor * 3);

37
spotifyColors/spotify.ts Normal file
View file

@ -0,0 +1,37 @@
import { exec, getCurrentUser } from "../utils.js";
interface Track {
length: number;
title: string;
artURL: string;
id: string;
url: string;
artist: string;
album: string;
albumArtist: string;
}
class Spotify {
async getCurrentTrack() {
const data: Record<string, string> = {};
const out = await exec(["machinectl", "shell", "--uid=" + await getCurrentUser(), ".host", "/usr/bin/qdbus", "org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player.Metadata"]);
for(const line of out.split("\n")) {
const key = line.substr(0, line.indexOf(" ")).trim();
if(!key) continue;
const value = line.substr(line.indexOf(" ") + 1).trim();
data[key] = value;
}
return {
length: Number(data["mpris:length:"]),
title: data["xesam:title:"],
artURL: data["mpris:artUrl:"],
id: data["mpris:trackid:"],
url: data["xesam:url:"],
artist: data["xesam:artist:"],
album: data["xesam:album:"],
albumArtist: data["xesam:albumArtist:"]
} as Track;
}
}
export default new Spotify();

View file

@ -1,8 +1,15 @@
{
"compilerOptions": {
"module": "esnext",
"allowJs": true,
"target": "es2020",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
}
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"outDir": "dist"
},
"buildOptions": {
"incremental": true
},
"ts-node": {}
}

View file

@ -7,25 +7,37 @@ export async function readUTF(file: string) {
return await afs.readFile(file, { encoding: "utf-8" }) as string;
}
export async function writeUTF(file: string, data: string) {
return await afs.writeFile(file, data);
await afs.writeFile(file, data);
}
export function exec(cmd: string[]) {
return new Promise<string>((resolve, reject) => {
var output = "";
var error = "";
const p = spawn(cmd.shift(), cmd);
p.stdout.on("data", (chunk) => output += chunk);
p.stderr.on("data", (chunk) => error += chunk);
p.on("exit", (code) => {
if(code) return reject(code);
if(code) return reject(error);
resolve(output);
});
});
}
export async function getCurrentUser() {
return "dan";
}
export async function getColor(image: string) {
var resp = await got(image, {
responseType: "buffer"
});
var vibrant = new Vibrant(resp.body);
var color = await vibrant.getPalette();
}
return color;
}
export function lerp(a: number, b: number, u: number) {
return (1 - u) * a + u * b;
};