Created
September 4, 2018 10:42
-
-
Save diegok/e0dd90455d74bc375033e53b9b731f8e to your computer and use it in GitHub Desktop.
Script to auto-configure external displays
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use FindBin qw($Bin); | |
use lib "$Bin/local/lib/perl5"; | |
use Mojo::Base -strict, -signatures; | |
use Mojo::File qw( path ); | |
use Parse::EDID qw/ parse_edid /; | |
use Mojo::JSON qw/ to_json /; | |
my $cards = cards_info(); | |
my $cmd = auto_cmd($cards); | |
path('/tmp/autorandr.last')->spurt(to_json({ | |
cmd => $cmd, | |
debug => $cards | |
})); | |
system($cmd); | |
sub auto_cmd($cards) { | |
if ( $cards->[1]{connected} ) { | |
my ( $main, $ext ) = $cards->@*; | |
$cards->[0]{opt} = "--output $main->{name} --mode $main->{mode}{string} --pos 0x@{[ abs( $ext->{mode}{vertical} - $main->{mode}{vertical} ) ]}"; | |
$cards->[1]{opt} = "--output $ext->{name} --mode $ext->{mode}{string} --pos $main->{mode}{horizontal}x0"; | |
} | |
else { | |
$cards->[0]{opt} = "--output $cards->[0]{name} --mode $cards->[0]{mode}{string} --pos 0x0"; | |
$cards->[1]{opt} = "--output $cards->[1]{name} --off"; | |
} | |
join(' ', 'xrandr', map { $_->{opt} } $cards->@* ); | |
} | |
sub cards_info() { | |
my $cards = [ | |
{ name => 'eDP1', path => path('/sys/class/drm/card0-eDP-1') }, | |
{ name => 'DP1', path => path('/sys/class/drm/card0-DP-1') }, | |
]; | |
for my $card ( $cards->@* ) { | |
$card->{enabled} = (read_card($card, 'enabled') eq 'enabled') || 0; | |
$card->{connected} = (read_card($card, 'status') eq 'connected') || 0; | |
# Get screen info when it's connected | |
next unless $card->{connected}; | |
my $edid_bin = $card->{path}->child('edid')->slurp || do { | |
# When screen is mounted it takes some time to be ready | |
# so we need to retry until we can read EDID. | |
# Calling xrandr makes this work faster :-/ | |
my ($try, $data) = (0, undef); | |
while ( !$data && ++$try < 20 ) { | |
$_ = `xrandr`; | |
sleep 1; | |
$data = $card->{path}->child('edid')->slurp | |
} | |
$card->{waited} = $try; | |
$data; | |
}; | |
next unless $edid_bin; | |
my $edid = parse_edid($edid_bin); | |
#$card->{edid} = $edid; | |
$card->{screen_id} = $edid->{EISA_ID}; | |
$card->{screen_name} = $edid->{monitor_name} || 'Embed'; | |
$card->{ratio} = $edid->{ratio_name}; | |
$card->{modes} = [map {{ | |
preferred => $_->{preferred} || 0, | |
horizontal => $_->{horizontal_active}, | |
vertical => $_->{vertical_active}, | |
string => "$_->{horizontal_active}x$_->{vertical_active}" . ($_->{ModeLine} =~ /Interlace/ ? 'i' : ''), | |
line => $_->{ModeLine}, | |
comment => $_->{ModeLine_comment}, | |
}} $edid->{detailed_timings}->@*]; | |
($card->{mode}) = grep { $_->{preferred} } $card->{modes}->@*; | |
} | |
$cards; | |
} | |
sub read_card($card, $file) { | |
chomp( my $value = $card->{path}->child($file)->slurp ); | |
$value; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment