Rofi to select pipewire sink

This commit is contained in:
Mahesh Asolkar 2024-09-18 19:01:11 -07:00
parent 5623991a73
commit f5ab4aad25

114
rofi_sound.pl Executable file
View File

@ -0,0 +1,114 @@
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my $selection = $ARGV[0];
my $app = {};
if (defined $selection) {
select_sink($app, $selection);
} else {
show_sinks($app);
}
# -----------
# Subroutines
# -----------
sub show_sinks {
my ($app) = @_;
my @sinks = get_sinks($app);
print join("\n", @sinks);
}
# -----------
sub select_sink {
my ($app, $sink) = @_;
my $wp_h;
my ($id,$name) = $sink =~ /(\d+):(.*)/;
my $seld_sink = "NONE";
my $seld_id = "NONE";
open($wp_h, "pw-cli info $id |") or die "Could not run pw-cli command";
while (my $ln = <$wp_h>) {
if (my ($node_name) = $ln =~ /node.name\s*=\s*"(.*)"/) {
warn "Selected [$id] ($name) - $node_name\n";
$seld_sink = $node_name;
$seld_id = $id;
last;
}
}
enable_sink($app, $seld_sink, $seld_id);
}
# -----------
sub enable_sink {
my ($app, $sink, $id) = @_;
`wpctl set-default $id`;
unmute_master($app);
}
# -----------
sub unmute_master {
my ($app) = @_;
`amixer -c 0 set Master unmute`;
}
# -----------
sub parse_wpctl {
my $wp_h;
open($wp_h, "wpctl status |") or die "Could not run wpctl command";
my @lines = <$wp_h>;
my $section = "None";
my $sub_section = "None";
my $wp_data = {};
foreach my $ln (@lines) {
# Section
if (my ($mat) = $ln =~ /(^(PipeWire)|^(\w+)$)/) {
$section = $mat;
$wp_data->{$section} = {} unless (exists $wp_data->{$section});
}
# Sub-section
if (my ($mat) = $ln =~ /\s+(\w+):$/) {
$sub_section = $mat;
$wp_data->{$section}->{$sub_section} = [] unless (exists $wp_data->{$section}->{$sub_section});
}
# Entries
if (($section ne "None") && ($sub_section ne "None")) {
if (my ($sel, $id, $name) = $ln =~ /\s+(\*)?\s+(\d+)\.\s+(.*?)(\[|$)/) {
my $seld = (defined $sel) ? 1 : 0;
$name =~ s/^\s*//; $name =~ s/\s*$//;
push(@{$wp_data->{$section}->{$sub_section}}, {
'sel' => $seld,
'id' => $id,
'name' => $name
});
}
}
}
$app->{'wp_data'} = $wp_data;
}
# -----------
sub get_sinks {
my ($app) = @_;
parse_wpctl($app);
# warn Data::Dumper->Dump([$app->{'wp_data'}]);
return map { "$_->{'id'}:$_->{'name'}" } @{$app->{'wp_data'}->{'Audio'}->{'Sinks'}}
}