package Xconfigurator; # $Id$
use diagnostics;
use strict;
use vars qw($in $install @window_managers @depths @monitorSize2resolution @hsyncranges %min_hsync4wres @vsyncranges %depths @resolutions %serversdriver @svgaservers @accelservers @allbutfbservers @allservers %vgamodes %videomemory @ramdac_name @ramdac_id @clockchip_name @clockchip_id %keymap_translate %standard_monitors $XF86firstchunk_text $keyboardsection_start $keyboardsection_start_v4 $keyboardsection_part2 $keyboardsection_part3 $keyboardsection_part3_v4 $keyboardsection_end $pointersection_text $monitorsection_text1 $monitorsection_text2 $monitorsection_text3 $monitorsection_text4 $modelines_text_Trident_TG_96xx $modelines_text $devicesection_text $devicesection_text_v4 $screensection_text1 %lines @options %xkb_options $good_default_monitor $low_default_monitor $layoutsection_v4 $modelines_text_apple);
use common qw(:common :file :functional :system);
use log;
use detect_devices;
use run_program;
use Xconfigurator_consts;
use any;
use modules;
use my_gtk qw(:helpers :wrappers);
my $tmpconfig = "/tmp/Xconfig";
my ($prefix, %monitors, %standard_monitors_);
sub xtest {
my ($display) = @_;
$::isStandalone ?
system("DISPLAY=$display /usr/X11R6/bin/xtest") == 0 :
c::Xtest($display);
}
sub getVGAMode($) { $_[0]->{card}{vga_mode} || $vgamodes{"640x480x16"}; }
sub readCardsDB {
my ($file) = @_;
my ($card, %cards);
my $F = common::openFileMaybeCompressed($file);
my ($lineno, $cmd, $val) = 0;
my $fs = {
LINE => sub { push @{$card->{lines}}, $val unless $val eq "VideoRam" },
NAME => sub {
$cards{$card->{type}} = $card if $card;
$card = { type => $val };
},
SEE => sub {
my $c = $cards{$val} or die "Error in database, invalid reference $val at line $lineno";
push @{$card->{lines}}, @{$c->{lines} || []};
add2hash($card->{flags}, $c->{flags});
add2hash($card, $c);
},
CHIPSET => sub {
$card->{chipset} = $val;
$card->{flags}{needChipset} = 1 if $val eq 'GeForce DDR';
$card->{flags}{needVideoRam} = 1 if member($val, qw(mgag10 mgag200 RIVA128 SiS6326));
},
SERVER => sub { $card->{server} = $val; },
DRIVER => sub { $card->{driver} = $val; },
RAMDAC => sub { $card->{ramdac} = $val; },
DACSPEED => sub { $card->{dacspeed} = $val; },
CLOCKCHIP => sub { $card->{clockchip} = $val; $card->{flags}{noclockprobe} = 1; },
NOCLOCKPROBE => sub { $card->{flags}{noclockprobe} = 1 },
UNSUPPORTED => sub { $card->{flags}{unsupported} = 1 },
COMMENT => sub {},
};
local $_;
while (<$F>) { $lineno++;
s/\s+$//;
/^#/ and next;
/^$/ and next;
/^END/ and last;
($cmd, $val) = /(\S+)\s*(.*)/ or next; #log::l("bad line $lineno ($_)"), next;
my $f = $fs->{$cmd};
$f ? $f->() : log::l("unknown line $lineno ($_)");
}
\%cards;
}
sub readCardsNames {
my $file = "$ENV{SHARE_PATH}/ldetect-lst/CardsNames";
map { (split '=>')[0] } grep { !/^#/ } catMaybeCompressed($file);
}
sub cardName2RealName {
my ($name) = @_;
my $file = "$ENV{SHARE_PATH}/ldetect-lst/CardsNames";
foreach (catMaybeCompressed($file)) {
chop;
next if /^#/;
my ($name_, $real) = split '=>';
return $real if $name eq $name_;
}
$name;
}
sub updateCardAccordingName {
my ($card, $name) = @_;
my $cards = readCardsDB("$ENV{SHARE_PATH}/ldetect-lst/Cards+");
add2hash($card->{flags}, $cards->{$name}{flags});
add2hash($card, $cards->{$name});
$card;
}
sub readMonitorsDB {
my ($file) = @_;
%monitors and return;
my $F = common::openFileMaybeCompressed($file);
local $_;
my $lineno = 0; while (<$F>) {
$lineno++;
s/\s+$//;
/^#/ and next;
/^$/ and next;
my @fields = qw(vendor type eisa hsyncrange vsyncrange);
my @l = split /\s*;\s*/;
@l == @fields or log::l("bad line $lineno ($_)"), next;
my %l; @l{@fields} = @l;
if ($monitors{$l{type}}) {
my $i; for ($i = 0; $monitors{"$l{type} ($i)"}; $i++) {}
$l{type} = "$l{type} ($i)";
}
$monitors{"$l{vendor}|$l{type}"} = \%l;
}
while (my ($k, $v) = each %standard_monitors) {
$monitors{'Generic|' . translate($k)} = $standard_monitors_{$k} =
{ hsyncrange => $v->[1], vsyncrange => $v->[2] };
}
}
sub keepOnlyLegalModes {
my ($card, $monitor) = @_;
my $mem = 1024 * ($card->{memory} || ($card->{server} eq 'FBDev' ? 2048 : 99999));
my $hsync = max(split(/[,-]/, $monitor->{hsyncrange}));
while (my ($depth, $res) = each %{$card->{depth}}) {
@$res = grep {
$mem >= product(@$_, $depth / 8) &&
$hsync >= ($min_hsync4wres{$_->[0]} || 0) &&
($card->{server} ne 'FBDev' || $vgamodes{"$_->[0]x$_->[1]x$depth"})
} @$res;
delete $card->{depth}{$depth} if @$res == 0;
}
}
sub cardConfigurationAuto() {
my @cards;
if (my @c = grep { $_->{driver} =~ /(Card|Server):/ } detect_devices::probeall(1)) {
foreach my $i (0..$#c) {
local $_ = $c[$i]->{driver};
my $card = { identifier => ($c[$i]{description} . (@c > 1 && " $i")) };
$card->{type} = $1 if /Card:(.*)/;
$card->{server} = $1 if /Server:(.*)/;
$card->{flags}{needVideoRam} &&= /86c368/;
$card->{busid} = "PCI:$c[$i]{pci_bus}:$c[$i]{pci_device}:$c[$i]{pci_function}";
push @{$card->{lines}}, @{$lines{$card->{identifier}} || []};
push @cards, $card;
}
}
#- take a default on sparc if nothing has been found.
if (arch() =~ /^sparc/ && !@cards) {
log::l("Using probe with /proc/fb as nothing has been found!");
local $_ = cat_("/proc/fb");
if (/Mach64/) { push @cards, { server => "Mach64" } }
elsif (/Permedia2/) { push @cards, { server => "3DLabs" } }
else { push @cards, { server => "Sun24" } }
}
#- special case for dual head card using only one busid.
@cards = map { my $dup = $_->{identifier} =~ /MGA G450/ ? 2 : 1;
if ($dup > 1) {
my @result;
my $orig = $_;
foreach (1..$dup) {
my $card = {};
add2hash($card, $orig);
push @result, $card;
}
@result;
} else {
($_);
}
} @cards;
#- make sure no type are already used, duplicate both screen
#- and rename type (because used as id).
if (@cards > 1) {
my $card = 1;
foreach (@cards) {
updateCardAccordingName($_, $_->{type}) if $_->{type};
$_->{type} = "$_->{type} $card";
$card++;
}
}
#- in case of only one cards, remove all busid reference, this will avoid
#- need of change of it if the card is moved.
#- on many PPC machines, card is on-board, busid is important, leave?
@cards == 1 and delete $cards[0]{busid} if arch() !~ /ppc/;
@cards;
}
sub cardConfiguration(;$$$) {
my ($card, $noauto, $cardOptions) = @_;
$card ||= {};
updateCardAccordingName($card, $card->{type}) if $card->{type}; #- try to get info from given type
undef $card->{type} unless $card->{server}; #- bad type as we can't find the server
my @cards = cardConfigurationAuto();
if (@cards > 1 && ($noauto || !$card->{server})) {#} && !$::isEmbedded) {
my (%single_heads, @choices, $tc);
my $configure_multi_head = sub {
|