554 lines
19 KiB
Lua
554 lines
19 KiB
Lua
-----------------------------------
|
|
-- This is the volume controller --
|
|
-----------------------------------
|
|
|
|
-- Awesome Libs
|
|
local awful = require("awful")
|
|
local dpi = require("beautiful").xresources.apply_dpi
|
|
local gears = require("gears")
|
|
local wibox = require("wibox")
|
|
local gobject = require("gears.object")
|
|
|
|
local capi = {
|
|
awesome = awesome,
|
|
mousegrabber = mousegrabber,
|
|
}
|
|
|
|
local rubato = require("src.lib.rubato")
|
|
|
|
-- Icon directory path
|
|
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/audio/"
|
|
|
|
local volume_controler = { mt = {} }
|
|
|
|
function volume_controler.get_device_widget()
|
|
local device = wibox.widget {
|
|
{
|
|
{
|
|
{
|
|
id = "icon",
|
|
resize = false,
|
|
valign = "center",
|
|
halign = "center",
|
|
widget = wibox.widget.imagebox
|
|
},
|
|
spacing = dpi(10),
|
|
{
|
|
text = name,
|
|
id = "node",
|
|
widget = wibox.widget.textbox
|
|
},
|
|
id = "device_layout",
|
|
layout = wibox.layout.fixed.horizontal
|
|
},
|
|
id = "device_margin",
|
|
margins = dpi(9),
|
|
widget = wibox.container.margin
|
|
},
|
|
id = "background",
|
|
bg = Theme_config.volume_controller.device_bg,
|
|
border_color = Theme_config.volume_controller.device_border_color,
|
|
border_width = Theme_config.volume_controller.device_border_width,
|
|
shape = Theme_config.volume_controller.device_shape,
|
|
widget = wibox.container.background
|
|
}
|
|
if true then
|
|
device:connect_signal(
|
|
"button::press",
|
|
function(_, _, _, key)
|
|
if key == 1 then
|
|
if node then
|
|
--awful.spawn("./.config/awesome/src/scripts/vol.sh set_sink " .. node)
|
|
--capi.awesome.emit_signal("update::bg_sink", node)
|
|
end
|
|
end
|
|
end
|
|
)
|
|
--[[ capi.awesome.connect_signal(
|
|
"update::bg_sink",
|
|
function(new_node)
|
|
if node == new_node then
|
|
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
|
|
Theme_config.volume_controller.device_icon_color)
|
|
device.bg = Theme_config.volume_controller.device_headphones_selected_bg
|
|
device.fg = Theme_config.volume_controller.device_headphones_selected_fg
|
|
Hover_signal(device)
|
|
else
|
|
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
|
|
Theme_config.volume_controller.device_headphones_selected_icon_color)
|
|
device.bg = Theme_config.volume_controller.device_bg
|
|
device.fg = Theme_config.volume_controller.device_headphones_fg
|
|
Hover_signal(device)
|
|
end
|
|
end
|
|
) ]]
|
|
else
|
|
device:connect_signal(
|
|
"button::press",
|
|
function(_, _, _, key)
|
|
if key == 1 then
|
|
if node then
|
|
--awful.spawn("./.config/awesome/src/scripts/mic.sh set_source " .. node)
|
|
--capi.awesome.emit_signal("update::bg_source", node)
|
|
end
|
|
end
|
|
end
|
|
)
|
|
--[[ capi.awesome.connect_signal(
|
|
"update::bg_source",
|
|
function(new_node)
|
|
if node == new_node then
|
|
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
|
|
Theme_config.volume_controller.device_icon_color)
|
|
device.bg = Theme_config.volume_controller.device_microphone_selected_bg
|
|
device.fg = Theme_config.volume_controller.device_microphone_selected_fg
|
|
Hover_signal(device)
|
|
else
|
|
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
|
|
Theme_config.volume_controller.device_microphone_selected_icon_color)
|
|
device.bg = Theme_config.volume_controller.device_bg
|
|
device.fg = Theme_config.volume_controller.device_microphone_fg
|
|
Hover_signal(device)
|
|
end
|
|
end
|
|
) ]]
|
|
end
|
|
return device
|
|
end
|
|
|
|
-- Get all source devices
|
|
function volume_controler:get_source_devices()
|
|
|
|
end
|
|
|
|
-- Get all input devices
|
|
function volume_controler:get_input_devices()
|
|
|
|
end
|
|
|
|
function volume_controler:toggle()
|
|
volume_controler.popup.visible = not volume_controler.popup.visible
|
|
end
|
|
|
|
function volume_controler.run(args)
|
|
|
|
args = args or {}
|
|
|
|
local ret = gobject {}
|
|
|
|
local w = wibox.widget {
|
|
{
|
|
{
|
|
-- Audio Device selector
|
|
{
|
|
{
|
|
{
|
|
{
|
|
{
|
|
resize = false,
|
|
image = gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
Theme_config.volume_controller.device_headphones_selected_icon_color),
|
|
widget = wibox.widget.imagebox,
|
|
valign = "center",
|
|
halign = "center",
|
|
id = "icon"
|
|
},
|
|
id = "center",
|
|
halign = "center",
|
|
valign = "center",
|
|
widget = wibox.container.place,
|
|
},
|
|
{
|
|
{
|
|
text = "Output Device",
|
|
widget = wibox.widget.textbox,
|
|
id = "device_name"
|
|
},
|
|
margins = dpi(5),
|
|
widget = wibox.container.margin
|
|
},
|
|
id = "audio_volume",
|
|
layout = wibox.layout.fixed.horizontal
|
|
},
|
|
id = "audio_bg",
|
|
bg = Theme_config.volume_controller.list_bg,
|
|
fg = Theme_config.volume_controller.list_headphones_fg,
|
|
shape = Theme_config.volume_controller.list_shape,
|
|
widget = wibox.container.background
|
|
},
|
|
id = "audio_selector_margin",
|
|
left = dpi(10),
|
|
right = dpi(10),
|
|
top = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
{
|
|
id = "volume_list",
|
|
widget = {
|
|
{
|
|
{
|
|
{
|
|
{
|
|
spacing = dpi(10),
|
|
layout = require("src.lib.overflow_widget.overflow").vertical,
|
|
scrollbar_width = 0,
|
|
step = dpi(50),
|
|
id = "volume_device_list",
|
|
},
|
|
id = "margin",
|
|
margins = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
id = "place",
|
|
height = dpi(200),
|
|
strategy = "max",
|
|
widget = wibox.container.constraint
|
|
},
|
|
border_color = Theme_config.volume_controller.list_border_color,
|
|
border_width = Theme_config.volume_controller.list_border_width,
|
|
id = "volume_device_background",
|
|
shape = Theme_config.volume_controller.list_shape,
|
|
widget = wibox.container.background
|
|
},
|
|
left = dpi(10),
|
|
right = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
forced_height = 0
|
|
},
|
|
-- Microphone selector
|
|
{
|
|
{
|
|
{
|
|
{
|
|
{
|
|
resize = false,
|
|
image = gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
Theme_config.volume_controller.device_microphone_selected_icon_color),
|
|
widget = wibox.widget.imagebox,
|
|
valign = "center",
|
|
halign = "center",
|
|
id = "icon",
|
|
},
|
|
id = "center",
|
|
halign = "center",
|
|
valign = "center",
|
|
widget = wibox.container.place,
|
|
},
|
|
{
|
|
{
|
|
text = "Input Device",
|
|
widget = wibox.widget.textbox,
|
|
id = "device_name"
|
|
},
|
|
margins = dpi(5),
|
|
widget = wibox.container.margin
|
|
},
|
|
id = "mic_volume",
|
|
layout = wibox.layout.fixed.horizontal
|
|
},
|
|
id = "mic_bg",
|
|
bg = Theme_config.volume_controller.list_bg,
|
|
fg = Theme_config.volume_controller.list_microphone_fg,
|
|
shape = Theme_config.volume_controller.selector_shape,
|
|
widget = wibox.container.background
|
|
},
|
|
id = "mic_selector_margin",
|
|
left = dpi(10),
|
|
right = dpi(10),
|
|
top = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
{
|
|
id = "mic_list",
|
|
widget = {
|
|
{
|
|
{
|
|
{
|
|
{
|
|
spacing = dpi(10),
|
|
layout = require("src.lib.overflow_widget.overflow").vertical,
|
|
id = "volume_device_list",
|
|
scrollbar_width = 0,
|
|
step = dpi(50),
|
|
},
|
|
id = "margin",
|
|
margins = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
id = "place",
|
|
height = dpi(200),
|
|
strategy = "max",
|
|
widget = wibox.container.constraint
|
|
},
|
|
id = "volume_device_background",
|
|
border_color = Theme_config.volume_controller.list_border_color,
|
|
border_width = Theme_config.volume_controller.list_border_width,
|
|
shape = Theme_config.volume_controller.list_shape,
|
|
widget = wibox.container.background
|
|
},
|
|
left = dpi(10),
|
|
right = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
forced_height = 0
|
|
},
|
|
-- Audio volume slider
|
|
{
|
|
{
|
|
{
|
|
resize = false,
|
|
widget = wibox.widget.imagebox,
|
|
valign = "center",
|
|
halign = "center",
|
|
image = gears.color.recolor_image(icondir .. "volume-high.svg", Theme_config.volume_controller.volume_fg),
|
|
id = "icon",
|
|
},
|
|
{
|
|
{
|
|
bar_shape = function(cr, width, height)
|
|
gears.shape.rounded_rect(cr, width, height, dpi(5))
|
|
end,
|
|
bar_height = dpi(5),
|
|
bar_color = Theme_config.volume_controller.border_color,
|
|
bar_active_color = Theme_config.volume_controller.volume_fg,
|
|
handle_color = Theme_config.volume_controller.volume_fg,
|
|
handle_shape = gears.shape.circle,
|
|
handle_border_color = Theme_config.volume_controller.volume_fg,
|
|
handle_width = dpi(12),
|
|
maximum = 100,
|
|
forced_height = dpi(26),
|
|
widget = wibox.widget.slider,
|
|
id = "slider"
|
|
},
|
|
left = dpi(5),
|
|
id = "slider_margin",
|
|
widget = wibox.container.margin
|
|
},
|
|
id = "audio_volume",
|
|
layout = wibox.layout.align.horizontal
|
|
},
|
|
id = "audio_volume_margin",
|
|
top = dpi(10),
|
|
left = dpi(10),
|
|
right = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
-- Microphone volume slider
|
|
{
|
|
{
|
|
{
|
|
resize = false,
|
|
widget = wibox.widget.imagebox,
|
|
valign = "center",
|
|
halign = "center",
|
|
image = gears.color.recolor_image(icondir .. "microphone.svg", Theme_config.volume_controller.microphone_fg),
|
|
id = "icon"
|
|
},
|
|
{
|
|
{
|
|
bar_shape = function(cr, width, height)
|
|
gears.shape.rounded_rect(cr, width, height, dpi(5))
|
|
end,
|
|
bar_height = dpi(5),
|
|
bar_color = Theme_config.volume_controller.device_border_color,
|
|
bar_active_color = Theme_config.volume_controller.microphone_fg,
|
|
handle_color = Theme_config.volume_controller.microphone_fg,
|
|
handle_shape = gears.shape.circle,
|
|
handle_border_color = Theme_config.volume_controller.microphone_fg,
|
|
handle_width = dpi(12),
|
|
maximum = 100,
|
|
forced_height = dpi(26),
|
|
widget = wibox.widget.slider,
|
|
id = "slider"
|
|
},
|
|
left = dpi(5),
|
|
id = "slider_margin",
|
|
widget = wibox.container.margin
|
|
},
|
|
id = "mic_volume",
|
|
layout = wibox.layout.align.horizontal
|
|
},
|
|
id = "mic_volume_margin",
|
|
left = dpi(10),
|
|
right = dpi(10),
|
|
top = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
id = "controller_layout",
|
|
layout = wibox.layout.fixed.vertical
|
|
},
|
|
id = "controller_margin",
|
|
margins = dpi(10),
|
|
widget = wibox.container.margin
|
|
},
|
|
bg = Theme_config.volume_controller.bg,
|
|
border_color = Theme_config.volume_controller.border_color,
|
|
border_width = Theme_config.volume_controller.border_width,
|
|
shape = Theme_config.volume_controller.shape,
|
|
forced_width = dpi(400),
|
|
widget = wibox.container.background
|
|
}
|
|
|
|
ret.widget = w
|
|
ret.audio_dropdown = w:get_children_by_id("audio_list")[1]
|
|
ret.mic_dropdown = w:get_children_by_id("mic_list")[1]
|
|
ret.audio_slider = w:get_children_by_id("slider")[1]
|
|
ret.mic_slider = w:get_children_by_id("slider")[1]
|
|
|
|
-- Main container
|
|
ret.popup = awful.popup {
|
|
widget = w,
|
|
ontop = true,
|
|
bg = Theme_config.volume_controller.bg,
|
|
stretch = false,
|
|
visible = false,
|
|
screen = args.screen,
|
|
--! Calculate the popup position instead of hardcoding it
|
|
placement = function(c) awful.placement.align(c,
|
|
{ position = "top_right", margins = { right = dpi(305), top = dpi(60) } })
|
|
end,
|
|
shape = Theme_config.volume_controller.shape,
|
|
}
|
|
|
|
-- Set the volume and icon
|
|
capi.awesome.connect_signal(
|
|
"audio::get",
|
|
function(muted, volume)
|
|
if muted then
|
|
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color
|
|
.recolor_image(icondir .. "volume-mute.svg", Theme_config.volume_controller.volume_fg))
|
|
else
|
|
volume = tonumber(volume)
|
|
if not volume then
|
|
return
|
|
end
|
|
local icon = icondir .. "volume"
|
|
if volume < 1 then
|
|
icon = icon .. "-mute"
|
|
elseif volume >= 1 and volume < 34 then
|
|
icon = icon .. "-low"
|
|
elseif volume >= 34 and volume < 67 then
|
|
icon = icon .. "-medium"
|
|
elseif volume >= 67 then
|
|
icon = icon .. "-high"
|
|
end
|
|
|
|
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.slider_margin.slider:
|
|
set_value(volume)
|
|
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color
|
|
.recolor_image(icon
|
|
.. ".svg", Theme_config.volume_controller.volume_fg))
|
|
end
|
|
end
|
|
)
|
|
|
|
-- Get microphone volume
|
|
capi.awesome.connect_signal(
|
|
"microphone::get",
|
|
function(muted, volume)
|
|
if muted then
|
|
--volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(0))
|
|
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
|
|
.. "microphone-off.svg", Theme_config.volume_controller.microphone_fg))
|
|
else
|
|
volume = tonumber(volume)
|
|
if not volume then
|
|
return
|
|
end
|
|
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(volume))
|
|
if volume > 0 then
|
|
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
|
|
.. "microphone.svg", Theme_config.volume_controller.microphone_fg))
|
|
else
|
|
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
|
|
.. "microphone-off.svg", Theme_config.volume_controller.microphone_fg))
|
|
end
|
|
end
|
|
end
|
|
)
|
|
|
|
-- Microphone slider change event
|
|
ret.widget:connect_signal(
|
|
"property::value",
|
|
function()
|
|
end
|
|
)
|
|
|
|
-- Slide animation
|
|
ret.audio_dropdown:connect_signal(
|
|
"button::press",
|
|
function(_, _, _, key)
|
|
if key == 1 then
|
|
local rubato_timer = rubato.timed {
|
|
duration = 0.4,
|
|
intro = 0.1,
|
|
outro = 0.1,
|
|
pos = mic_list.forced_height,
|
|
easing = rubato.linear,
|
|
subscribed = function(v)
|
|
mic_list.forced_height = v
|
|
end
|
|
}
|
|
if mic_list.forced_height == 0 then
|
|
rubato_timer.target = dpi(200)
|
|
mic_selector_margin.mic_bg.shape = function(cr, width, height)
|
|
gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
|
|
end
|
|
mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg",
|
|
Theme_config.volume_controller.device_microphone_selected_icon_color))
|
|
else
|
|
rubato_timer.target = 0
|
|
mic_bg.shape = function(cr, width, height)
|
|
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
|
end
|
|
mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
Theme_config.volume_controller.device_microphone_selected_icon_color))
|
|
end
|
|
end
|
|
end
|
|
)
|
|
|
|
-- Slide animation
|
|
ret.mic_dropdown:connect_signal(
|
|
"button::press",
|
|
function(_, _, _, key)
|
|
if key == 1 then
|
|
local rubato_timer = rubato.timed {
|
|
duration = 0.4,
|
|
intro = 0.1,
|
|
outro = 0.1,
|
|
pos = volume_list.forced_height,
|
|
easing = rubato.linear,
|
|
subscribed = function(v)
|
|
volume_list.forced_height = v
|
|
end
|
|
}
|
|
if volume_list.forced_height == 0 then
|
|
rubato_timer.target = dpi(200)
|
|
audio_bg.shape = function(cr, width, height)
|
|
gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
|
|
end
|
|
audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg",
|
|
Theme_config.volume_controller.device_headphones_selected_icon_color))
|
|
else
|
|
rubato_timer.target = 0
|
|
audio_bg.shape = function(cr, width, height)
|
|
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
|
end
|
|
audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
Theme_config.volume_controller.device_headphones_selected_icon_color))
|
|
end
|
|
end
|
|
end
|
|
)
|
|
|
|
return ret
|
|
end
|
|
|
|
function volume_controler.mt:__call(...)
|
|
return volume_controler.run(...)
|
|
end
|
|
|
|
return setmetatable(volume_controler, volume_controler.mt)
|