Compare commits

...
35 Commits
Author SHA1 Message Date
josh aa73c356f5 id3-album.rb: read metadata from info.txt 2026-10-30 10:59:43 -04:00
josh 6d97a84bf9 Attempt storing full release date 2026-10-26 11:56:48 -04:00
josh b1539e8985 Replace wav-to-mp3 2026-10-26 10:17:28 -04:00
josh 4796c9633e id3-album.rb: fail if albumart.jpg not found 2026-10-22 13:38:01 -04:00
josh 99724786ca id3-album.rb: fail early if no .mp3 files found 2026-10-22 13:21:14 -04:00
josh 343d1277d6 Add id3-album.rb 2026-10-22 10:48:47 -04:00
josh 3379b3c58b Add wav-to-mp3.sh 2026-10-22 10:27:52 -04:00
josh e0d1cf30b1 e: use absolute paths when starting server also 2026-05-13 16:34:58 -04:00
josh da79240044 e: use tab drop instead of tabedit to avoid new tabs for already-open files 2026-05-13 16:32:37 -04:00
josh 75a5e73356 e: set project name when launching server 2026-05-13 16:28:24 -04:00
josh 4f15356578 e: rework to pass all paths at once 2026-05-13 16:15:33 -04:00
josh 0d443f89d4 Switch EDITOR to nvim 2026-05-13 15:49:31 -04:00
josh 0b7ebab8c3 Update e to use nvim 2026-05-13 15:48:50 -04:00
josh eb9ba299aa git config: change init.defaultBranch to main 2026-05-13 14:58:17 -04:00
josh 5cacdec789 Add ctags alias 2026-05-08 08:49:36 -04:00
josh 670707a857 Record microphone input with gpu-screen-recorder 2026-05-07 13:38:03 -04:00
josh 1f89c56c2c Add gpu-screen-wrapper scripts 2026-05-05 17:05:14 -04:00
josh cb779f4134 Add git alias prunebranches 2026-03-19 19:16:18 -04:00
josh a7e00cbac7 Add claude aliases/gitignore 2026-03-19 19:15:55 -04:00
josh 203365a9fb Merge remote-tracking branch 'github/master' 2026-02-17 11:49:10 -05:00
josh c98db4a373 Add ctags config file 2026-02-17 11:48:38 -05:00
josh 800beefb11 Update mk-usb-music-disk-for-car 2026-02-17 11:45:44 -05:00
josh 893eff8eec Add git configuration for branch.autoSetupMerge 2025-07-18 11:45:22 -04:00
josh 5bae9bc66e Add bash_profile, profile 2025-06-04 08:05:34 -04:00
josh 0e1ecfedaa Add grepgit 2025-05-30 11:34:25 -04:00
josh e483adfba0 Update e for newer Ruby 2025-05-30 11:34:15 -04:00
josh cc63840fcb Add e-win 2024-04-19 13:54:08 -04:00
josh 5d0fec77eb Add xbindkeysrc 2024-03-08 14:20:18 -05:00
josh ebe988991d git config: add user.useConfigOnly 2023-07-13 13:54:59 -04:00
josh c71c875e8f Use \012 instead of \n in PS1 to avoid errors on Windows 2023-05-17 09:53:59 -04:00
josh 92a83779d9 Add macos-sendkey 2023-05-10 16:17:01 -04:00
josh 511abd591d tag-mp3s.py: robustify 2023-03-03 09:57:51 -05:00
josh 40fb9f1817 tag-mp3s: replace title and images 2023-03-03 09:57:15 -05:00
josh d3b5d86bca mk-usb-music-disk-for-car: do not print Creating message for directory that exists 2023-03-03 09:56:23 -05:00
josh 70b07abbae mk-usb-music-disk-for-car: add -s option to show directory sizes 2023-03-03 09:55:50 -05:00
23 changed files with 278 additions and 61 deletions

No files matched your search

+3 -3
View File
@@ -155,8 +155,8 @@ PS1="${PS1} $(ps-color bold cyan)\w"
PS1="${PS1}$(ps-color bold blue)\$(prompt_ps1_job_count \\j)"
# shell level
PS1="${PS1}$(ps-color bold green)\$(prompt_ps1_shlvl)"
# \n
PS1="${PS1}$(ps-color reset)\n"
# \n: \012 used instead to avoid errors on Windows
PS1="${PS1}$(ps-color reset)\012"
# rvm gemset
PS1="${PS1}$(ps-color bold green)\$(prompt_ps1_rvm_gemset)"
# git/svn info
@@ -287,7 +287,7 @@ alias rsync-vfat='rsync -rtv --stats --modify-window=2'
###########################################################################
export LESS='Ri'
export EDITOR=vim
export EDITOR=nvim
export LC_COLLATE=C
###########################################################################
+1
View File
@@ -0,0 +1 @@
alias claude='claude --name "Claude: $(basename $PWD)"'
+1
View File
@@ -0,0 +1 @@
alias ctags='ctags --c-kinds=+p --c++-kinds=+p'
+8 -1
View File
@@ -25,7 +25,14 @@ function git-config-joshs()
git config --global mergetool.bc.cmd \
'git_bcmerge "$LOCAL" "$REMOTE" "$BASE" "$MERGED"'
git config --global alias.authors '!git log --pretty="%an" | sort | uniq -c | sort -n'
git config --global init.defaultBranch master
git config --global init.defaultBranch main
# Only use configured user.name/user.email; do not guess them
git config --global user.useConfigOnly true
# Do not automatically mark my branch as tracking the remote branch that I
# happened to use as the starting point.
git config --global branch.autoSetupMerge false
# delete all branches that have been merged to HEAD
git config --global alias.prunebranches '!git branch --merged | grep -v '^\*' | xargs git branch -d'
}
function git-config-local-personal()
{
+1
View File
@@ -0,0 +1 @@
alias grepgit='git ls-files -z | xargs -0 grep --color=auto -H'
+2
View File
@@ -0,0 +1,2 @@
source $HOME/.profile
source $HOME/.bashrc
+1 -1
View File
@@ -6,7 +6,7 @@ import getopt
from subprocess import *
def main(argv):
bitrate = 128
bitrate = 256
try:
opts, args = getopt.getopt(argv[1:], "b:")
except getopt.GetoptError:
+1
View File
@@ -0,0 +1 @@
--excmd=combine
+41 -24
View File
@@ -1,39 +1,56 @@
#!/usr/bin/env ruby
# Use HighContrast GTK2 theme for gvim.
ENV["GTK2_RC_FILES"] = "/usr/share/themes/HighContrast/gtk-2.0/gtkrc"
require "open3"
def get_server_name(path)
if path
path = File.expand_path(path)
while path != "/"
dirname = File.dirname(path)
if File.exists?(File.join(dirname, "project.vim"))
if dirname =~ %r{([^/]+)/([^/]+)/*$}
sn = "#{$2}(#{$1})"
else
sn = File.basename(dirname)
end
return sn
SEARCH = %w[.git project.vim]
EDITOR = "nvim-qt"
def find_proj_root(path)
path = File.expand_path(path)
loop do
dirname = File.dirname(path)
if SEARCH.any? {|s| File.exist?(File.join(dirname, s))}
if dirname =~ %r{([^/]+)/([^/]+)/*$}
pretty_name = "#{$2}(#{$1})"
else
pretty_name = File.basename(dirname)
end
path = dirname
stdout, stderr, status = Open3.capture3("xxh32sum", stdin_data: dirname)
socket_name = stdout.sub(/\s.*/m, "")
return [socket_name, pretty_name]
end
path = dirname
if path == "/"
return nil
end
end
return "GVIM"
nil
end
def server_running?(server_name)
`gvim --serverlist`.lines.map(&:chomp).include?(server_name.upcase)
def run_dir
ENV["XDG_RUNTIME_DIR"] || "/tmp"
end
if ARGV.empty?
server_name = get_server_name('local_file')
exec("/usr/bin/gvim", "--servername", server_name, err: "/dev/null")
exec(EDITOR)
else
ARGV.each_with_index do |path, i|
server_name = get_server_name(path)
sleep(0.2) if i > 0
system("/usr/bin/gvim", "--servername", server_name, "--remote-tab-silent", path, err: "/dev/null")
socket_name, pretty_name = find_proj_root(ARGV[0])
if socket_name
socket_path = "#{run_dir}/e-#{socket_name}.sock"
if File.exist?(socket_path)
opencmds = ARGV.map do |path|
path = File.expand_path(path).gsub(" ", "\\ ")
%[:tab drop #{path}<CR>]
end.join
exec("nvim", "--headless", "--server", socket_path, "--remote-send", "<Esc>#{opencmds}:call GuiForeground()<CR><C-l>")
else
paths = ARGV.map do |path|
File.expand_path(path)
end
exec(EDITOR, "--", "--listen", socket_path, "--cmd", "let g:project_name = '#{pretty_name}'", "-p", *paths)
end
else
exec(EDITOR, "--", "-p", *ARGV)
end
end
+38
View File
@@ -0,0 +1,38 @@
#!/c/Ruby32-x64/bin/ruby
GVIM = "C:/apps/vim/vim91/gvim.exe"
def get_server_name(path)
if path
path = File.expand_path(path)
while path !~ %r{^.\\|/$}
dirname = File.dirname(path)
if File.exist?(File.join(dirname, "project.vim"))
if dirname =~ %r{([^/]+)/([^/]+)/*$}
sn = "#{$2}(#{$1})"
else
sn = File.basename(dirname)
end
return sn
end
path = dirname
end
end
return "GVIM"
end
def server_running?(server_name)
`gvim --serverlist`.lines.map(&:chomp).include?(server_name.upcase)
end
if ARGV.empty?
server_name = get_server_name('local_file')
exec(GVIM, "--servername", server_name, err: "/dev/null")
else
ARGV.each_with_index do |path, i|
server_name = get_server_name(path)
sleep(0.2) if i > 0
Process.detach(Process.spawn(GVIM, "--servername", server_name, "--remote-tab-silent", path))
end
end
+1
View File
@@ -10,3 +10,4 @@ tags
/.ruby-version
/.ruby-gemset
/_local/
.claude/
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
exec gpu-screen-recorder -w screen -o ~/Videos -r 90 -c mp4 -a default_output -a default_input -ac aac
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
exec killall -SIGUSR1 gpu-screen-recorder
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
#DEFAULT_SINK=$(pactl get-default-sink)
#MONITOR_SINK="${DEFAULT_SINK}.monitor"
#gpu-screen-recorder -w screen -o ~/Videos -r 90 -c mp4 -a "$MONITOR_SINK" -a default_input -ac aac >> $HOME/.gpu-screen-recorder.log &
gpu-screen-recorder -w screen -o ~/Videos -r 90 -c mp4 -a default_output -a default_input -ac aac >> $HOME/.gpu-screen-recorder.log &
PID=$!
"$@"
kill -SIGINT $PID
wait $PID
Executable
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env ruby
# Install: kid3-common
require "fileutils"
$stdout.sync = true
files = Dir.glob("*.mp3").sort
if files.empty?
$stderr.puts "No .mp3 files found"
exit 1
end
unless File.exist?("albumart.jpg")
$stderr.puts "albumart.jpg not found"
exit 1
end
unless File.exist?("info.txt")
$stderr.puts "info.txt not found"
exit 1
end
info = File.read("info.txt")
info =~ /^artist: (.*)$/
artist = $1
info =~ /^album: (.*)$/
album = $1
info =~ /^year: (.*)$/
date = $1
unless artist && album && date
$stderr.puts "invalid info.txt format"
exit 1
end
#$stdout.write("Release date (YYYY-MM-DD): ")
#date = gets.chomp
#unless date =~ /^\d{4}-\d{2}-\d{2}$/
# $stderr.puts "Unexpected date format"
# exit 1
#end
files.each do |file|
if file =~ /^(\d+)\s*(.*)\.mp3$/
track_number, title = $1.to_i, $2
command = %w[kid3-cli]
command += ["-c", "revert", "-c", "save"]
command += ["-c", %[set artist "#{artist}" 12]]
command += ["-c", %[set title "#{title}" 12]]
command += ["-c", %[set album "#{album}" 12]]
command += ["-c", %[set date "#{date}" 12]]
command += ["-c", %[set track "#{track_number}" 12]]
command += ["-c", %[set picture:albumart.jpg 'Front Cover' 2]]
command += ["-c", "save"]
command << file
system(*command)
else
$stderr.puts "Warning: skipping #{file}, unrecognized name format"
end
end
+4
View File
@@ -21,12 +21,16 @@ def install_file(src, dst):
files = [
('bash_aliases', '.bash_aliases'),
('bash_aliases.d', '.bash_aliases.d'),
('bash_profile', '.bash_profile'),
('profile', '.profile'),
('inputrc', '.inputrc'),
('screenrc', '.screenrc'),
('gitignore', '.gitignore'),
('colordiffrc', '.colordiffrc'),
('rvmrc', '.rvmrc'),
('toprc', '.toprc'),
('ctags', '.ctags'),
]
for s, d in files:
Executable
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env ruby
# I edited the global keyboard shortcuts and turned on Mission Control > Switch
# to Desktop 1 with shortcut set to Control + Alt + Command + Tab
require "open3"
script = 'tell application "System Events" to keystroke tab using {option down, command down, control down}'
stdout, status = Open3.capture2("osascript", stdin_data: script)
+37 -11
View File
@@ -5,29 +5,44 @@ BASE = "/pegasus/pub/music/artists"
DEST = "/media/josh/JoshMusic"
ARTISTS = <<EOF
Avenged Sevenfold
A Perfect Circle
All That Remains
#Avenged Sevenfold
Collective Soul
Dave Matthews Band
Days Of The New
DevilDriver
Falling in Reverse
deadmau5
#Falling in Reverse
Eluveitie
Fear Factory
Fuel
Godsmack
#Godsmack
Hans Zimmer
Incubus
LFO
Lamb of God
Machine Head
Linkin Park
London Symphony Orchestra
#Machine Head
Matchbox Twenty
Mudvayne
Our Lady Peace
POD
Staind
Static-X
System of a Down
Ra
Rush
#Staind
#Static-X
#System of a Down
Tantric
Taproot
The Goo Goo Dolls
The Offspring
Tool
#Tool
Trans-Siberian Orchestra
Trivium
Volbeat
Weezer
EOF
EXCLUDE = <<EOF.split("\n").map(&:chomp)
@@ -36,18 +51,29 @@ EOF
require "fileutils"
artists = ARTISTS.lines.map do |artist|
if artist !~ /#/
artist.chomp
end
end.compact
if ARGV[0] == "-s"
cmd = %w[du -shc] + artists.map {|a| "#{BASE}/#{a}"}
system(*cmd)
exit 0
end
unless Dir.exist?(DEST)
$stderr.puts "#{DEST} does not exist"
end
ARTISTS.lines.each do |artist|
artist = artist.chomp
artists.each do |artist|
Dir.glob("#{BASE}/#{artist}/*").sort.each do |album_dir|
next if album_dir.split("/").any? {|part| EXCLUDE.include?(part)}
album = File.basename(album_dir)
mp3_files = Dir.glob("#{album_dir}/*.mp3").sort
dest = "#{DEST}/#{artist}/#{album}"
puts "Creating #{dest}"
puts "Creating #{dest}" unless Dir.exist?(dest)
FileUtils.mkdir_p(dest)
mp3_files.each do |mp3_file|
unless File.exist?("#{dest}/#{File.basename(mp3_file)}")
+2
View File
@@ -0,0 +1,2 @@
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
export PATH="$HOME/bin":"$PATH"
+6 -5
View File
@@ -9,11 +9,11 @@ def process_mp3(mp3_path)
dirname = File.dirname(mp3_path)
current_info, stderr, status = Open3.capture3("id3info", mp3_path)
current_info.force_encoding("ASCII-8BIT")
if current_info =~ /TIT2\s.*: (.*)/
title = $1
else
#if current_info =~ /TIT2\s.*: (.*)/
# title = $1
#else
title = File.basename(mp3_path).sub(/\.mp3$/, "")
end
#end
artist = File.basename(File.dirname(File.dirname(mp3_path)))
album = File.basename(File.dirname(mp3_path))
if current_info =~ /TYER\s.*: (.*)/
@@ -33,8 +33,9 @@ def process_mp3(mp3_path)
args += %W[--track=#{track_number}] if track_number
args += %W[--release-year=#{year}] if year
# 2017 Outback likes to show picture for OTHER but not FRONT_COVER...
args += %W[--add-image=#{album_art}:OTHER] if album_art
#args += %W[--add-image=#{album_art}:OTHER] if album_art
args += [mp3_path]
system("eyeD3", "--remove-all", mp3_path)
system("eyeD3", *args)
end
+19 -16
View File
@@ -35,7 +35,7 @@ def choose_artwork(mp3s, jpgs):
if len(mp3s) < min_mp3s_for_album:
return None
if len(jpgs) == 0:
sys.stderr.write("No .jpg files found\n")
sys.stderr.write("No .jpg files found in %s\n" % (os.path.dirname(mp3s[0])))
return None
if len(jpgs) > 1:
sys.stderr.write("Multiple .jpg album artwork files found\n")
@@ -61,7 +61,7 @@ def clean_tag(mp3, tagname):
orig_text = tag.text[0]
new_text = clean_title(orig_text)
if new_text != orig_text:
sys.stdout.write("Changing %s from \"%s\" to \"%s\"\n" % (tagname, orig_text, new_text))
sys.stdout.write("Changing %s from \"%s\" to \"%s\" for %s\n" % (tagname, orig_text, new_text, mp3.filename))
tag.text = [new_text]
return True
return False
@@ -69,20 +69,23 @@ def clean_tag(mp3, tagname):
def process_mp3(mp3_path, artwork_path):
mp3 = mutagen.mp3.MP3(mp3_path)
current_tags = mp3.tags
changed = False
changed = clean_tag(mp3, "TIT2") or changed
changed = clean_tag(mp3, "TALB") or changed
if artwork_path is not None:
apic_tags = [tag for tag in current_tags if tag == "APIC" or tag.startswith("APIC:")]
if len(apic_tags) < 1:
print("Adding APIC tag to %s..." % mp3_path)
jpg_data = read_file(artwork_path)
apic = mutagen.id3.APIC(0, "image/jpeg", 0, "", jpg_data)
mp3.tags.add(apic)
changed = True
if changed and not dry_run:
sys.stdout.write("Writing %s\n" % mp3_path)
mp3.save()
if current_tags is not None:
changed = False
changed = clean_tag(mp3, "TIT2") or changed
changed = clean_tag(mp3, "TALB") or changed
if artwork_path is not None:
apic_tags = [tag for tag in current_tags if tag == "APIC" or tag.startswith("APIC:")]
if len(apic_tags) < 1:
print("Adding APIC tag to %s..." % mp3_path)
jpg_data = read_file(artwork_path)
apic = mutagen.id3.APIC(0, "image/jpeg", 0, "", jpg_data)
mp3.tags.add(apic)
changed = True
if changed and not dry_run:
sys.stdout.write("Writing %s\n" % mp3_path)
mp3.save()
else:
sys.stdout.write("Warning: no tags found for %s\n" % (mp3_path))
def main(argv):
base_dir = "."
Executable
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env ruby
if ARGV.empty?
files = Dir["*.wav"].sort
else
files = ARGV
end
files.each do |infile|
outfile = infile.sub(".wav", ".mp3")
puts "Converting: #{infile} -> #{outfile}"
command = %W[lame -v -b 256 #{infile} #{outfile}]
system(*command)
end
puts "Conversion complete!"
+5
View File
@@ -0,0 +1,5 @@
# Set mouse button 8 to send "Back" key
# Bind "Back" to "Toggle Present Windows (Current desktop)" to expose windows from mouse button!
# Install 'xautomation' and 'xbindkeys' packages to use.
"xte 'key XF86Back'"
b:8