Wednesday, October 22, 2025

Tuesday, October 14, 2025

one liner to reinstall xfce

I always end up breaking the desktop if i mess around with the settings long enough.
this one liner removes and then cleanly reinstalls xfce


sudo apt purge xfce4* xfdesktop4* thunar* xfwm4* && sudo apt autoremove --purge && sudo apt install xfce4 xfce4-goodies

Tuesday, October 7, 2025

Modularizing Your Bash Functions (Example: vicd with Vifm)

Step 1: Create a Modular Config Directory

Keep your Bash setup clean by separating custom scripts:


mkdir -p ~/.bashrc.d
This directory will store small .sh files instead of crowding your .bashrc.


Step 2: Add Your Function

Create a file just for your Vifm directory picker:


vim ~/.bashrc.d/vicd.sh
Paste this inside:

vicd() {
    local dst
    dst="$(command vifm --choose-dir - "$@")"
    if [ -z "$dst" ]; then
        echo 'Directory picking cancelled/failed'
        return 1
    fi
    cd "$dst"
}


Step 3: Source All Scripts Automatically

At the end of your ~/.bashrc, add:


for f in ~/.bashrc.d/*.sh; do
    [ -f "$f" ] && . "$f"
done
Reload your shell:

source ~/.bashrc
Now your vicd function (and any future ones) load automatically — tidy, modular, and easy to manage.

Saturday, October 4, 2025

fixed velocity for acorn masterkey on ios

streambyter has a fixed velocity script. It's supposed to be adjustable with cc 15 on channel one but it's not working for me.

Thursday, September 18, 2025

Tuesday, September 16, 2025

rp2040 breakout board for prototyping

its pretty cool you can just order the gerbers from pcbway, solder some headers and have easy access to those awkward pins to maximize the use of this tiny footprint

rp2040 breakout

Monday, September 15, 2025

Friday, September 12, 2025

getting a usb qwerty to be a midi keyboard without a computer

samd2695 + esp32s3

this m5 stack midi module

akai mpk play has built in sounds and a speaker but wasnt a fan. you could get a qy100 or some other old midi module on ebay or a pawn shop. An mt-32, soundcanvas, maybe a proteus. but now for 30$ on ali you can get one of these

Wednesday, September 10, 2025

Tuesday, September 9, 2025

how to convert mkv to mp4

so you've recorded a video on linux with guvcview and now you want to play it/edit it on an iphone,
heres a one liner you can use with ffmpeg to convert it to mp4:


for f in *.mkv; do ffmpeg -i "$f" -c:v libx264 -profile:v high -level 4.1 -c:a aac -movflags +faststart "${f%.mkv}.mp4"; done

Tuesday, September 2, 2025

build your own arduino drum brain

this kit is cool

beam forming

pretty cool these days to be able to dip your toes into medical ultrasound technology using cheaply available microcontrollers and sensors.
diy sonar scanner

Saturday, August 30, 2025

adding more gpio to an arduino nano/ raspberry pi

the mcp23017

the mcp3008 for adc good for adding pots

picoIO64
22$ some soldering required. gives you 64 gpio

modmypi mcp2308 pi zero hat adds 16 gpio 14.95$

Thursday, August 21, 2025

how to make pcbs with kicad

kicad tutorial one of the best. straight to the point

Tuesday, August 19, 2025

my sunvox shortcuts

reposting this because I put down sunvox for a while and had to relearn it.

  • cyclic shift is #1 the most important shortcut to add.
  • being able to move between patterns is another one.
  • shift space to play from line
  • doing chords with ctrl g b i
  • ctrl p paste evenly
  • ctrl t select track

my sunvox shortcuts

Friday, August 15, 2025

remaping the f310 to send midi with watchdog for auto reload


#!/usr/bin/env python3
import evdev
import rtmidi
from evdev import ecodes
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import os
import sys

DEVICE_PATH = '/dev/input/by-id/usb-Logitech_Logitech_Dual_Action_DF5CB332-event-joystick'

# ----------------------------
# Corrected human-readable button mappings
# ----------------------------
buttons = {
    'A': 61,    # physical A triggers MIDI note B
    'B': 62,    # physical B triggers MIDI note X
    'X': 60,    # physical X triggers MIDI note A
    'Y': 63,
    'L': 64,
    'R': 65,
    'Select': 66,
    'Start': 67,
    'Up': 68,
    'Down': 69,
    'Left': 70,
    'Right': 71
}

evdev_button_map = {
    288: 'A',
    289: 'B',
    290: 'X',
    291: 'Y',
    292: 'L',
    293: 'R',
    296: 'Select',
    297: 'Start',
    294: 'Up',
    295: 'Down',
    298: 'Left',
    299: 'Right'
}

# ----------------------------
# Axis mappings
# ----------------------------
axes = {
    'LX':  (10, -32768, 32767),
    'LY':  (11, -32768, 32767),
    'LT':  (12, 0, 255),
    'RT':  (13, 0, 255),
    'RX':  (14, -32768, 32767),
    'RY':  (15, -32768, 32767)
}

evdev_axis_map = {0: 'LX', 1: 'LY', 2: 'LT', 5: 'RT', 3: 'RX', 4: 'RY'}

# ----------------------------
# MIDI setup
# ----------------------------
midi_out = rtmidi.MidiOut()
midi_out.open_virtual_port("F310 MIDI")

def scale(value, min_val, max_val):
    return int((value - min_val) / (max_val - min_val) * 127)

# ----------------------------
# Main gamepad loop
# ----------------------------
def run():
    gamepad = evdev.InputDevice(DEVICE_PATH)
    print(f"Listening on {gamepad.name} ({gamepad.path})")
    for event in gamepad.read_loop():
        if event.type == ecodes.EV_KEY and event.code in evdev_button_map:
            label = evdev_button_map[event.code]
            note = buttons[label]
            if event.value == 1:
                midi_out.send_message([0x90, note, 112])
                print(f"Button pressed: {label}")
            elif event.value == 0:
                midi_out.send_message([0x80, note, 0])
        elif event.type == ecodes.EV_ABS and event.code in evdev_axis_map:
            label = evdev_axis_map[event.code]
            cc, min_val, max_val = axes[label]
            val = scale(event.value, min_val, max_val)
            midi_out.send_message([0xB0, cc, val])

# ----------------------------
# Watchdog for hot-reload
# ----------------------------
class ReloadHandler(FileSystemEventHandler):
    def on_modified(self, event):
        if event.src_path.endswith(os.path.basename(__file__)):
            print("Script changed. Restarting...")
            os.execv(sys.executable, ['python3'] + sys.argv)

observer = Observer()
observer.schedule(ReloadHandler(), path='.', recursive=False)
observer.start()

# ----------------------------
# Run forever
# ----------------------------
try:
    while True:
        run()
except KeyboardInterrupt:
    observer.stop()
observer.join()


Thursday, August 14, 2025

1 liner gpg encryption + qr

gpg - c creates, gpg - d decodes
this uses python qrcode (pip install it if you dont have it)


read -p "Input GPG file: " infile; read -p "Output PNG file: " outfile; python3 -c "import qrcode, base64; f=open('$infile','rb'); data=base64.b64encode(f.read()).decode(); f.close(); qrcode.make(data).save('$outfile')"

this passes the input of the qr as input and decodes the gpg (requires pyzbar. opencv is good to have also


read -p "QR PNG file: " qrfile; read -p "Output file: " outfile; python3 -c "import cv2, pyzbar.pyzbar as pyzbar, base64, sys; img=cv2.imread('$qrfile'); data=pyzbar.decode(img)[0].data; sys.stdout.buffer.write(base64.b64decode(data))" | gpg -d > "$outfile"