Skip to content

Instantly share code, notes, and snippets.

@syrm
Created June 14, 2024 08:41
Show Gist options
  • Save syrm/b1019ebb06410b2bd823915851de92b5 to your computer and use it in GitHub Desktop.
Save syrm/b1019ebb06410b2bd823915851de92b5 to your computer and use it in GitHub Desktop.
sound linux setup
-- .config/m2i/basic.lua
-- https://gitlab.com/enetheru/midi2input
--[[ global settings ]]--
-- autoconnect: can be true, false, or a named jack port. default = true
autoconnect = true
Knob_1 = 11.0
Knob_2 = 12.0
Knob_3 = 13.0
Knob_4 = 14.0
Knob_5 = 15.0
Knob_6 = 16.0
Knob_7 = 17.0
Knob_8 = 18.0
Knob_M = 10.0
Button_01 = 32.0
Button_02 = 33.0
Button_03 = 34.0
Button_04 = 35.0
Button_05 = 36.0
Button_06 = 37.0
Button_07 = 38.0
Button_08 = 39.0
Button_11 = 40.0
Button_12 = 41.0
Button_13 = 42.0
Button_14 = 43.0
Button_15 = 44.0
Button_16 = 45.0
Button_17 = 46.0
Button_18 = 47.0
Devices = {
Main_device = {
name = function ()
return "alsa_output.pci-0000_0e_00.4.analog-stereo"
end,
type = "sink",
knob = Knob_1,
button = Button_01
},
Headset_device = {
name = function ()
return "alsa_output.usb-MV-SILICON_fifine_SC3_20190808-00.analog-stereo"
end,
type = "sink",
knob = Knob_M,
},
Music_device = {
name = function ()
return "music"
end,
type = "sink",
knob = Knob_4,
button = Button_04
},
Micro_device = {
name = function ()
return "alsa_input.usb-MV-SILICON_fifine_SC3_20190808-00.analog-stereo"
end,
type = "source",
button = Button_18
},
Chrome_app = {
name = function ()
return GetSinkID("chrome")
end,
type = "sink-input",
knob = Knob_2,
button = Button_02
}
}
--[[ initialisation function ]]--
-- run immediately after the application launches and connects to the device
function script_init()
print("init")
alsaconnect('X-TOUCH MINI', '*')
-- bug ?
for index in pairs(Devices) do
UpdateXTouchVolume(Devices[index])
UpdateXTouchMute(Devices[index])
end
end
function loop()
detectwindow()
end
--[[ Input Event Handler ]]--
function midi_recv(data1, data2, status)
print("==========> ", data1, " ", data2, " ==> ", status)
for index in pairs(Devices) do
if (data1 == 138.0 and data2 == Devices[index].button) then
ToggleMute(Devices[index])
end
if (data1 == 186.0 and data2 == Devices[index].knob) then
SetVolume(Devices[index], status)
end
end
end
function Exec(command)
local handle = io.popen(command)
local result = handle:read("*a")
handle:close()
return result:gsub("%s+", "")
end
function SetVolume(device, volumeXTouch)
local amount = math.floor(65536 * tonumber(volumeXTouch)/127)
Exec("pactl set-" .. device.type .. "-volume " .. device.name() .. " " .. tostring(amount))
end
function UpdateXTouchVolume(device)
if not device.knob then
return
end
midi_send({186.0, device.knob, GetVolume(device)})
end
function UpdateXTouchMute(device)
if not device.button then
return
end
if GetMuteState(device) then
ToggleOn(device.button)
else
ToggleOff(device.button)
end
end
function ToggleMute(device)
if GetMuteState(device) then
ToggleOff(device.button)
Exec("pactl set-" .. device.type .. "-mute " .. device.name() .. " 0")
else
ToggleOn(device.button)
Exec("pactl set-" .. device.type .. "-mute " .. device.name() .. " 1")
end
end
function ToggleOn(index)
midi_send({154.0, index, 127.0})
end
function ToggleOff(index)
midi_send({138.0, index, 0.0})
end
function GetSinkID(application)
return Exec("pactl list sink-inputs | grep " .. application .. " -B30 | grep \"Sink Input\" | tail -1 | cut -d# -f2")
end
function GetMuteState(device)
local state
if device.type == "sink-input" then
state = Exec("pactl list sink-inputs | grep \"Sink Input #".. device.name() .."\" -A30 | grep \"Mute\"")
else
state = Exec("pactl get-" .. device.type .. "-mute " .. device.name())
end
if state == "Mute:no" then
return false
end
return true
end
function GetVolume(device)
local volume
if device.type == "sink-input" then
volume = Exec("pactl list sink-inputs | grep \"Sink Input #".. device.name() .."\" -A30 | grep \"Volume\" | awk 'NR==1{ print $3 }'")
else
volume = Exec("pactl get-sink-volume " .. device.name() .. " | awk 'NR==1{ print $3 }'")
end
return volume - 1
end
// .config/pipewire/pipewire.conf.d/music.conf
context.objects = [
{ factory = adapter
args = {
factory.name = support.null-audio-sink
node.name = "music"
media.class = Audio/Sink
audio.position = [ FL FR ]
monitor.channel-volumes = true
monitor.passthrough = true
adapter.auto-port-config = {
mode = dsp
monitor = true
position = preserve
}
}
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment