#!/bin/bash #------------------------------------------- # some kind of midi arpegiator (ab)using your window manager's # window placement as some kind of piano roll # by james morris - james ( at ) http://jwm-art.net # i make no guarantees this will work on your system. # required software # BASH # xwininfo # prefered software: xterm, and a lightweight window manager # thanks go to Pedro Lopez-Cabanillas for providing assistance # via the Linux Audio User mailing list with the midi stuff - # and also for the pointing out the note names chart, linked below... #------------------------------------------- # <<<<< ----- user options ----- >>>>> # ***** values are decimals, change ***** # ***** to suit your preferences. ***** # see http://upload.wikimedia.org/wikipedia/commons/7/7a/NoteNamesFrequenciesAndMidiNumbers.svg # for valid ranges for notelow and notehigh. notelow=30 notehigh=80 vellow=0 velhigh=127 # pattern: 1 = play note, 0 = don't play note pattern="11110110" # duration of note (seconds) notetime=0.1 # hang time (seconds) - how long the popup-xterms hang around hangtime=0.5 # controls for popup-xterms (affects window placement) wwidthmin=8 wwidthmax=14 wheightmin=2 wheightmax=8 #------------------------------------------- # <<<<< ----- system settings ----- >>>>> # midi device mididev="/dev/snd/midiC1D0" #------------------------------------------- # <<<<< ----- code ----- >>>>> noteoff=$1 patix=$2 if [[ -z "$noteoff" ]] then # << -- INITIALIZE -- >> noteoff="_" if [[ -z "$DISPLAY" ]] then echo "This script must be run from a terminal in X" exit fi exec 3>$mididev if [[ "$?" != "0" ]] then echo "an error occurred trying to open midi device: $midi" echo "set mididev to the midi device you wish to use" echo "in the system setting of this script" exit fi echo -ne '\xb0' >&3 echo -ne '\x07' >&3 echo -ne '\x7f' >&3 # volume patix=0 # << -- END INITIALIZE -- >> fi playnote=${pattern:$patix:1} patix=$(( $(( $patix + 1 )) % ${#pattern} )) # get stats of root window xystr="Absolute upper-left" wininfo=`xwininfo -root -stats` tmp=`echo "${wininfo}" | egrep "Width"` tmp2=`expr index "$tmp" ":"` scrmaxx=$(( ${tmp:$tmp2} )) tmp=`echo "${wininfo}" | egrep "Height"` tmp2=`expr index "$tmp" ":"` scrmaxy=$(( ${tmp:$tmp2} )) wwr=$(( $wwidthmax - $wwidthmin )) whr=$(( $wheightmax - $wheightmin )) ndiff=$(( $notehigh - $notelow )) vdiff=$(( $velhigh - $vellow )) xsc=$(( $scrmaxx / $ndiff )) ysc=$(( $scrmaxy / $vdiff )) wininfo=`xwininfo -stats -id $WINDOWID` tmp=`echo "${wininfo}" | egrep "${xystr} X"` tmp2=`expr index "$tmp" ":"` x=$(( ${tmp:$tmp2} )) tmp=`echo "${wininfo}" | egrep "${xystr} Y"` tmp2=`expr index "$tmp" ":"` y=$(( ${tmp:$tmp2} )) r=$(( $x / 10 % 256 )) g=$(( $x / $(( $y + 1 )) % 256 )) b=$(( $y / 10 % 256 )) bg=$( printf "#%02x%02x%02x\n" $r $g $b ) geo=$( printf "%sx%s" \ $(($RANDOM % $wwr + $wwidthmin)) \ $(($RANDOM % $whr + $wheightmin)) ) note=$(( $notelow + $x / $xsc )) vel=$(( $vellow + ($scrmaxy - $y) / $ysc )) if (( $note < $notelow )) then note=$notelow elif (( $note > $notehigh )) then $note=$notehigh fi if (( $vel < $vellow )) then vel=$vellow elif (( $vel > $velhigh )) then vel=$velhigh fi if [[ "$playnote" == "1" ]] then noteout='\x'$( printf "%02x" $note ) velout='\x'$( printf "%02x" $vel ) echo -ne '\x90' >&3 echo -ne $noteout >&3 echo -ne $velout >&3 else noteout="_" bg="#ffffff" fi sleep $notetime $TERM -bg "$bg" -geo "$geo" -e $0 $noteout $patix & if [[ "$noteoff" != "_" ]] then echo -ne '\x80' >&3 echo -ne $noteoff >&3 echo -ne '\x00' >&3 fi sleep $hangtime