Commit cd7010eb authored by Lionel Le Folgoc's avatar Lionel Le Folgoc Committed by Nick Schermer

Display the screen vendor in the ui

Drop the code that tried to read the ConnectorType property, it is not
supported by any driver (although it is marked as mandatory by the xrandr 1.3
spec). Instead, read the screen's EDID data to find its vendor name. It should
be easier to identify a screen in the ui now…
parent c8fbe1f9
......@@ -118,6 +118,17 @@ dnl ***********************************
XDT_CHECK_OPTIONAL_PACKAGE([XRANDR], [xrandr], [1.1.0],
[xrandr], [Xrandr support])
dnl ***********************************
dnl *** Optional support for hwdata ***
dnl ***********************************
AC_ARG_WITH([pnp-ids-path],
[AC_HELP_STRING([--with-pnp-ids-path],
[Specify the path to pnp.ids (default=\${datadir}/hwdata/pnp.ids)])],
[with_pnp_ids_path=$withval],
[with_pnp_ids_path="\${datadir}/hwdata/pnp.ids"])
PNP_IDS=$with_pnp_ids_path
AC_SUBST(PNP_IDS)
dnl **************************************
dnl *** Optional support for Libnotify ***
dnl **************************************
......
......@@ -6,6 +6,7 @@ INCLUDES = \
-DSRCDIR=\"$(top_srcdir)\" \
-DLOCALEDIR=\"$(localedir)\" \
-DG_LOG_DOMAIN=\"xfce4-display-settings\" \
-DPNP_IDS=\"$(PNP_IDS)\" \
$(PLATFORM_CPPFLAGS)
bin_PROGRAMS = \
......@@ -18,7 +19,10 @@ xfce4_display_settings_SOURCES = \
xfce-randr-legacy.c \
xfce-randr-legacy.h \
display-dialog_ui.h \
display-dialog-xrandr1.2_ui.h
display-dialog-xrandr1.2_ui.h \
display-name.c \
edid-parse.c \
edid.h
xfce4_display_settings_CFLAGS = \
$(GTK_CFLAGS) \
......
/*
* Copyright 2007 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* Author: Soren Sandmann <sandmann@redhat.com> */
/* Downloaded from <http://git.gnome.org/browse/gnome-desktop/tree/libgnome-desktop>
(git commit 60f318f3d5a890c267160562f54a048d862def18)
Slightly modified by Lionel Le Folgoc <mrpouit@gmail.com> to build with full debug */
#include <config.h>
#include <glib/gi18n-lib.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include "edid.h"
typedef struct Vendor Vendor;
struct Vendor
{
const char vendor_id[4];
const char vendor_name[28];
};
/* This list of vendor codes derived from lshw
*
* http://ezix.org/project/wiki/HardwareLiSter
*
* Note: we now prefer to use data coming from hwdata (and shipped with
* gnome-desktop). See
* http://git.fedorahosted.org/git/?p=hwdata.git;a=blob_plain;f=pnp.ids;hb=HEAD
* All contributions to the list of vendors should go there.
*/
static const struct Vendor vendors[] =
{
{ "AIC", "AG Neovo" },
{ "ACR", "Acer" },
{ "DEL", "DELL" },
{ "SAM", "SAMSUNG" },
{ "SNY", "SONY" },
{ "SEC", "Epson" },
{ "WAC", "Wacom" },
{ "NEC", "NEC" },
{ "CMO", "CMO" }, /* Chi Mei */
{ "BNQ", "BenQ" },
{ "ABP", "Advansys" },
{ "ACC", "Accton" },
{ "ACE", "Accton" },
{ "ADP", "Adaptec" },
{ "ADV", "AMD" },
{ "AIR", "AIR" },
{ "AMI", "AMI" },
{ "ASU", "ASUS" },
{ "ATI", "ATI" },
{ "ATK", "Allied Telesyn" },
{ "AZT", "Aztech" },
{ "BAN", "Banya" },
{ "BRI", "Boca Research" },
{ "BUS", "Buslogic" },
{ "CCI", "Cache Computers Inc." },
{ "CHA", "Chase" },
{ "CMD", "CMD Technology, Inc." },
{ "COG", "Cogent" },
{ "CPQ", "Compaq" },
{ "CRS", "Crescendo" },
{ "CSC", "Crystal" },
{ "CSI", "CSI" },
{ "CTL", "Creative Labs" },
{ "DBI", "Digi" },
{ "DEC", "Digital Equipment" },
{ "DBK", "Databook" },
{ "EGL", "Eagle Technology" },
{ "ELS", "ELSA" },
{ "ESS", "ESS" },
{ "FAR", "Farallon" },
{ "FDC", "Future Domain" },
{ "HWP", "Hewlett-Packard" },
{ "IBM", "IBM" },
{ "INT", "Intel" },
{ "ISA", "Iomega" },
{ "LEN", "Lenovo" },
{ "MDG", "Madge" },
{ "MDY", "Microdyne" },
{ "MET", "Metheus" },
{ "MIC", "Micronics" },
{ "MLX", "Mylex" },
{ "NVL", "Novell" },
{ "OLC", "Olicom" },
{ "PRO", "Proteon" },
{ "RII", "Racal" },
{ "RTL", "Realtek" },
{ "SCM", "SCM" },
{ "SKD", "SysKonnect" },
{ "SGI", "SGI" },
{ "SMC", "SMC" },
{ "SNI", "Siemens Nixdorf" },
{ "STL", "Stallion Technologies" },
{ "SUN", "Sun" },
{ "SUP", "SupraExpress" },
{ "SVE", "SVEC" },
{ "TCC", "Thomas-Conrad" },
{ "TCI", "Tulip" },
{ "TCM", "3Com" },
{ "TCO", "Thomas-Conrad" },
{ "TEC", "Tecmar" },
{ "TRU", "Truevision" },
{ "TOS", "Toshiba" },
{ "TYN", "Tyan" },
{ "UBI", "Ungermann-Bass" },
{ "USC", "UltraStor" },
{ "VDM", "Vadem" },
{ "VMI", "Vermont" },
{ "WDC", "Western Digital" },
{ "ZDS", "Zeos" },
/* From http://faydoc.tripod.com/structures/01/0136.htm */
{ "ACT", "Targa" },
{ "ADI", "ADI" },
{ "AOC", "AOC Intl" },
{ "API", "Acer America" },
{ "APP", "Apple Computer" },
{ "ART", "ArtMedia" },
{ "AST", "AST Research" },
{ "CPL", "Compal" },
{ "CTX", "Chuntex Electronic Co." },
{ "DPC", "Delta Electronics" },
{ "DWE", "Daewoo" },
{ "ECS", "ELITEGROUP" },
{ "EIZ", "EIZO" },
{ "FCM", "Funai" },
{ "GSM", "LG Electronics" },
{ "GWY", "Gateway 2000" },
{ "HEI", "Hyundai" },
{ "HIT", "Hitachi" },
{ "HSL", "Hansol" },
{ "HTC", "Hitachi" },
{ "ICL", "Fujitsu ICL" },
{ "IVM", "Idek Iiyama" },
{ "KFC", "KFC Computek" },
{ "LKM", "ADLAS" },
{ "LNK", "LINK Tech" },
{ "LTN", "Lite-On" },
{ "MAG", "MAG InnoVision" },
{ "MAX", "Maxdata" },
{ "MEI", "Panasonic" },
{ "MEL", "Mitsubishi" },
{ "MIR", "miro" },
{ "MTC", "MITAC" },
{ "NAN", "NANAO" },
{ "NEC", "NEC Tech" },
{ "NOK", "Nokia" },
{ "OQI", "OPTIQUEST" },
{ "PBN", "Packard Bell" },
{ "PGS", "Princeton" },
{ "PHL", "Philips" },
{ "REL", "Relisys" },
{ "SDI", "Samtron" },
{ "SMI", "Smile" },
{ "SPT", "Sceptre" },
{ "SRC", "Shamrock Technology" },
{ "STP", "Sceptre" },
{ "TAT", "Tatung" },
{ "TRL", "Royal Information Company" },
{ "TSB", "Toshiba, Inc." },
{ "UNM", "Unisys" },
{ "VSC", "ViewSonic" },
{ "WTC", "Wen Tech" },
{ "ZCM", "Zenith Data Systems" },
{ "???", "Unknown" },
};
static GHashTable *pnp_ids = NULL;
static void
read_pnp_ids (void)
{
gchar *contents;
gchar **lines;
gchar *line;
gchar *code, *name;
gint i;
if (pnp_ids)
return;
pnp_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
if (g_file_get_contents (PNP_IDS, &contents, NULL, NULL))
{
lines = g_strsplit (contents, "\n", -1);
for (i = 0; lines[i]; i++)
{
line = lines[i];
if (line[3] == '\t')
{
code = line;
line[3] = '\0';
name = line + 4;
g_hash_table_insert (pnp_ids, code, name);
}
}
g_free (lines);
g_free (contents);
}
}
static const char *
find_vendor (const char *code)
{
const char *vendor_name;
unsigned int i;
read_pnp_ids ();
vendor_name = g_hash_table_lookup (pnp_ids, code);
if (vendor_name)
return vendor_name;
for (i = 0; i < sizeof (vendors) / sizeof (vendors[0]); ++i)
{
const Vendor *v = &(vendors[i]);
if (strcmp (v->vendor_id, code) == 0)
return v->vendor_name;
}
return code;
};
char *
make_display_name (const MonitorInfo *info)
{
const char *vendor;
int width_mm, height_mm, inches;
if (info)
{
vendor = find_vendor (info->manufacturer_code);
}
else
{
/* Translators: "Unknown" here is used to identify a monitor for which
* we don't know the vendor. When a vendor is known, the name of the
* vendor is used. */
vendor = C_("Monitor vendor", "Unknown");
}
if (info && info->width_mm != -1 && info->height_mm)
{
width_mm = info->width_mm;
height_mm = info->height_mm;
}
else if (info && info->n_detailed_timings)
{
width_mm = info->detailed_timings[0].width_mm;
height_mm = info->detailed_timings[0].height_mm;
}
else
{
width_mm = -1;
height_mm = -1;
}
if (width_mm != -1 && height_mm != -1)
{
double d = sqrt (width_mm * width_mm + height_mm * height_mm);
inches = (int)(d / 25.4 + 0.5);
}
else
{
inches = -1;
}
if (inches > 0)
return g_strdup_printf ("%s %d\"", vendor, inches);
else
return g_strdup (vendor);
}
/*
* Copyright 2007 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* Author: Soren Sandmann <sandmann@redhat.com> */
/* Downloaded from <http://git.gnome.org/browse/gnome-desktop/tree/libgnome-desktop>
(git commit 42452cada8cf1c4d7a81aded0a3ddbb5e97441de)
Slightly modified by Lionel Le Folgoc <mrpouit@gmail.com> to build with full debug */
#include "edid.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <glib.h>
static int
get_bit (int in, int bit)
{
return (in & (1 << bit)) >> bit;
}
static int
get_bits (int in, int begin, int end)
{
int mask = (1 << (end - begin + 1)) - 1;
return (in >> begin) & mask;
}
static int
decode_header (const uchar *edid)
{
if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
return TRUE;
return FALSE;
}
static int
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
{
int is_model_year;
/* Manufacturer Code */
info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6);
info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3;
info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4);
info->manufacturer_code[3] = '\0';
info->manufacturer_code[0] += 'A' - 1;
info->manufacturer_code[1] += 'A' - 1;
info->manufacturer_code[2] += 'A' - 1;
/* Product Code */
info->product_code = edid[0x0b] << 8 | edid[0x0a];
/* Serial Number */
info->serial_number =
edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
/* Week and Year */
is_model_year = FALSE;
switch (edid[0x10])
{
case 0x00:
info->production_week = -1;
break;
case 0xff:
info->production_week = -1;
is_model_year = TRUE;
break;
default:
info->production_week = edid[0x10];
break;
}
if (is_model_year)
{
info->production_year = -1;
info->model_year = 1990 + edid[0x11];
}
else
{
info->production_year = 1990 + edid[0x11];
info->model_year = -1;
}
return TRUE;
}
static int
decode_edid_version (const uchar *edid, MonitorInfo *info)
{
info->major_version = edid[0x12];
info->minor_version = edid[0x13];
return TRUE;
}
static int
decode_display_parameters (const uchar *edid, MonitorInfo *info)
{
/* Digital vs Analog */
info->is_digital = get_bit (edid[0x14], 7);
if (info->is_digital)
{
int bits;
static const int bit_depth[8] =
{
-1, 6, 8, 10, 12, 14, 16, -1
};
static const Interface interfaces[6] =
{
UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
};
bits = get_bits (edid[0x14], 4, 6);
info->connector.digital.bits_per_primary = bit_depth[bits];
bits = get_bits (edid[0x14], 0, 3);
if (bits <= 5)
info->connector.digital.interface = interfaces[bits];
else
info->connector.digital.interface = UNDEFINED;
}
else
{
int bits = get_bits (edid[0x14], 5, 6);
static const double levels[][3] =
{
{ 0.7, 0.3, 1.0 },
{ 0.714, 0.286, 1.0 },
{ 1.0, 0.4, 1.4 },
{ 0.7, 0.0, 0.7 },
};
info->connector.analog.video_signal_level = levels[bits][0];
info->connector.analog.sync_signal_level = levels[bits][1];
info->connector.analog.total_signal_level = levels[bits][2];
info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
}
/* Screen Size / Aspect Ratio */
if (edid[0x15] == 0 && edid[0x16] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = -1.0;
}
else if (edid[0x16] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
}
else if (edid[0x15] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = 100.0 / (edid[0x16] + 99);
info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
}
else
{
info->width_mm = 10 * edid[0x15];
info->height_mm = 10 * edid[0x16];
}
/* Gamma */
if (edid[0x17] == 0xFF)
info->gamma = -1.0;
else
info->gamma = (edid[0x17] + 100.0) / 100.0;
/* Features */
info->standby = get_bit (edid[0x18], 7);
info->suspend = get_bit (edid[0x18], 6);
info->active_off = get_bit (edid[0x18], 5);
if (info->is_digital)
{
info->connector.digital.rgb444 = TRUE;
if (get_bit (edid[0x18], 3))
info->connector.digital.ycrcb444 = 1;
if (get_bit (edid[0x18], 4))
info->connector.digital.ycrcb422 = 1;
}
else
{
int bits = get_bits (edid[0x18], 3, 4);
ColorType color_type[4] =
{
MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
};
info->connector.analog.color_type = color_type[bits];
}
info->srgb_is_standard = get_bit (edid[0x18], 2);
/* In 1.3 this is called "has preferred timing" */
info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
/* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
info->continuous_frequency = get_bit (edid[0x18], 0);
return TRUE;
}
static double
decode_fraction (int high, int low)
{
double result = 0.0;
int i;
high = (high << 2) | low;
for (i = 0; i < 10; ++i)
result += get_bit (high, i) * pow (2, i - 10);
return result;
}
static int
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
{
info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
return TRUE;
}
static int
decode_established_timings (const uchar *edid, MonitorInfo *info)
{
static const Timing established[][8] =
{
{
{ 800, 600, 60 },
{ 800, 600, 56 },
{ 640, 480, 75 },
{ 640, 480, 72 },
{ 640, 480, 67 },
{ 640, 480, 60 },
{ 720, 400, 88 },
{ 720, 400, 70 }
},
{
{ 1280, 1024, 75 },
{ 1024, 768, 75 },
{ 1024, 768, 70 },