#!/usr/bin/wpexec

local argv = ...

-- Print help message if no argument is provided
if argv['action'] == nil then
    print [[
Usage: wpexec volume.lua action=[value] step=[volume_step]
[value] can be either 'print_sink', 'print_source', 'toggle_sink', 'toggle_source', 'increase' or 'decrease'
[volume_step] is a float in range (0,1), only required if action is 'increase' or 'decrease']]
    Core.quit()
    return
end

local function findValue(tbl, value)
    for _, v in ipairs(tbl) do
        if v == value then
            return value
        end
    end
    return nil
end

local options = { 'print_sink', 'toggle_sink', 'increase', 'decrease', 'print_source', 'toggle_source' }
local action = assert(findValue(options, argv['action']), 'Invalid value of parameter "action".')

-- Load the necessary Wireplumber API modules
Core.require_api('default-nodes', 'mixer', function(...)
    local default_nodes, mixer = ...

    -- configure volumes to be printed in the cubic scale
    -- this is also what the pulseaudio API shows
    mixer.scale = 'cubic'

    local id_source = default_nodes:call('get-default-node', 'Audio/Source')
    local volume_source = mixer:call('get-volume', id_source)

    local id_sink = default_nodes:call('get-default-node', 'Audio/Sink')
    local volume_sink = mixer:call('get-volume', id_sink)

    if action == 'toggle_source' then
        mixer:call('set-volume', id_source, { mute = not volume_source.mute })
    elseif action == 'print_source' then
        print(string.format([[
Volume: %s
Mute: %s]], string.format('%.2f', volume_source.volume), volume_source.mute))
    elseif action == 'toggle_sink' then
        mixer:call('set-volume', id_sink, { mute = not volume_sink.mute })
    elseif action == 'print_sink' then
        print(string.format([[
Volume: %s
Mute: %s]], string.format('%.2f', volume_sink.volume), volume_sink.mute))
    else
        -- Too lazy to check for errors here
        -- assert() and error() don't quit the process in the fallback function
        local step = tonumber(argv['step'])

        if action == 'increase' then
            mixer:call('set-volume', id_sink, { volume = volume_sink.volume + step })
        else
            mixer:call('set-volume', id_sink, { volume = volume_sink.volume - step })
        end
    end

    Core.quit()
end)
