#!/usr/bin/perl
# Copyright (C) 2005-2010 by Mandriva SA
# Pascal Rigaux
# Anssi Hannula
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
use Getopt::Long;
use Parse::EDID;
GetOptions(
'v' => \ (my $verbose),
'perl' => \ (my $raw_perl),
'MonitorsDB' => \ (my $MonitorsDB),
) or usage();
my ($file, $F);
if (@ARGV == 0) {
$F = *STDIN;
} elsif (@ARGV == 1) {
open($F, $file = $ARGV[0]) or usage();
} else {
usage();
}
my $input = join('', <$F>);
my @raw_edids;
my $length = length($input);
if ($length % 128 == 0 && $length >= 128 && $length <= 128 * 254) {
@raw_edids = $input;
} else {
@raw_edids = find_edid_in_string($input) or error("bad edid");
}
foreach my $raw_edid (@raw_edids) {
my $edid = parse_edid($raw_edid, $verbose);
if (my $err = check_parsed_edid($edid)) {
die "$err\n";
}
$edid->{file} = $file if $file;
if ($raw_perl) {
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
my $s = Dumper($edid);
$s =~ s/.*? = \{/+{/; # remove variable name we don't want
$s =~ s/};$/}/m;
print $s;
} elsif ($MonitorsDB) {
my $s = to_MonitorsDB($edid);
print "$s\n" if $s;
} else {
print_edid($edid, $verbose);
}
}
sub usage() {
die <<'EOF';
usage: monitor-parse-edid [-v] [--perl] []
You can also do "xrandr --prop | monitor-parse-edid"
EOF
}
sub error {
my ($msg) = @_;
print STDERR ($file ? "$file: " : ''), $msg, "\n";
exit 1;
}
sub print_edid {
my ($edid, $verbose) = @_;
print "Name: $edid->{monitor_name}\n" if $edid->{monitor_name};
print "EISA ID: $edid->{EISA_ID}\n" if $edid->{EISA_ID};
print "EDID version: $edid->{edid_version}.$edid->{edid_revision}\n";
# this is a number, despite the official name containing "flag":
print "EDID extension blocks: $edid->{extension_flag}\n";
printf "Screen size: %.1f cm x %.1f cm (%3.2f inches%s)\n",
$edid->{max_size_horizontal},
$edid->{max_size_vertical},
$edid->{diagonal_size},
$edid->{ratio_name} ? sprintf(", aspect ratio %s = %.2f", $edid->{ratio_name}, $edid->{ratio}) :
$edid->{ratio} ? sprintf(", aspect ratio %.2f", $edid->{ratio}) : '';
print "Gamma: ", $edid->{gamma} / 100 + 1, "\n";
printf "%s signal\n", $edid->{video_input_definition}{digital} ? 'Digital' : 'Analog';
if ($verbose) {
foreach (@{$edid->{established_timings} || []}) {
print "Standard resolution: $_->{X}x$_->{Y} @ $_->{vfreq} Hz (established timing)\n" if !$_->{interlace};
}
foreach (@{$edid->{standard_timings} || []}) {
print "Standard resolution: $_->{X}x$_->{Y} @ $_->{vfreq} Hz, ratio $_->{ratio}",
$edid->{ratio_name} && index($edid->{ratio_name}, $_->{ratio}) == -1 ? ' (!)' : '',
"\n";
}
}
if ($edid->{monitor_range}) {
printf "Max video bandwidth: %u MHz\n", $edid->{monitor_range}{pixel_clock_max} if $edid->{monitor_range}{pixel_clock_max};
print "\n";
printf "\tHorizSync %u-%u\n", $edid->{monitor_range}{horizontal_min}, $edid->{monitor_range}{horizontal_max};
printf "\tVertRefresh %u-%u\n", $edid->{monitor_range}{vertical_min}, $edid->{monitor_range}{vertical_max};
}
foreach my $h (@{$edid->{detailed_timings}}) {
print "\n";
print "\t", $h->{ModeLine_comment}, $h->{bad_ratio} ? ' (bad ratio)' : '', "\n";
print "\tModeLine ", $h->{ModeLine}, "\n";
}
}
sub to_MonitorsDB {
my ($edid) = @_;
if (!$edid->{monitor_range}) {
print STDERR "No monitor range data in EDID.\n";
return;
}
if (!$edid->{EISA_ID}) {
print STDERR "No monitor EISA_ID in EDID.\n";
return;
}
my $detailed_timings = $edid->{detailed_timings} || [];
my @preferred_resolutions = map {
join('x', $_->{horizontal_active}, $_->{vertical_active});
} grep { !$_->{bad_ratio} } @$detailed_timings;
(my $monitor_name = $edid->{monitor_name}) =~ s/;/,/g;
my ($raw_vendor, $raw_model) = $edid->{EISA_ID} =~ /(...)(.*)/;
my ($VendorName, $only_Model) = $monitor_name =~ /(\S+)\s(.*)/ ?
($1, $2) : ($raw_vendor, $monitor_name || $raw_model);
join('; ',
$VendorName, "$VendorName $only_Model", $edid->{EISA_ID},
sprintf("%u-%u", $edid->{monitor_range}{horizontal_min}, $edid->{monitor_range}{horizontal_max}),
sprintf("%u-%u", $edid->{monitor_range}{vertical_min}, $edid->{monitor_range}{vertical_max}),
@$detailed_timings == 1 ? @preferred_resolutions : (),
);
}