From 21aa80032f685b3ded10fe293ca083d2f46ae18c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Thu, 21 Nov 2013 15:38:19 +0100 Subject: alpha --- oldsrc/beamergui.pro | 27 +++ oldsrc/displaymanager.cpp | 36 ++++ oldsrc/displaymanager.h | 32 ++++ oldsrc/main.cpp | 11 ++ oldsrc/output.cpp | 119 ++++++++++++ oldsrc/output.h | 47 +++++ oldsrc/widget.cpp | 145 ++++++++++++++ oldsrc/widget.h | 31 +++ oldsrc/widget.ui | 39 ++++ src/beamer.conf2 | 26 +++ src/beamergui.pro | 13 +- src/config.cpp | 109 +++++++++++ src/config.h | 45 +++++ src/displaymanager.cpp | 36 ---- src/displaymanager.h | 32 ---- src/main.cpp | 420 ++++++++++++++++++++++++++++++++++++++++ src/output.cpp | 119 ------------ src/output.h | 47 ----- src/widget.cpp | 201 ++++++++------------ src/widget.h | 14 +- src/x.cpp | 473 ++++++++++++++++++++++++++++++++++++++++++++++ src/x.h | 281 +++++++++++++++++++++++++++ 22 files changed, 1933 insertions(+), 370 deletions(-) create mode 100644 oldsrc/beamergui.pro create mode 100644 oldsrc/displaymanager.cpp create mode 100644 oldsrc/displaymanager.h create mode 100644 oldsrc/main.cpp create mode 100644 oldsrc/output.cpp create mode 100644 oldsrc/output.h create mode 100644 oldsrc/widget.cpp create mode 100644 oldsrc/widget.h create mode 100644 oldsrc/widget.ui create mode 100644 src/beamer.conf2 create mode 100644 src/config.cpp create mode 100644 src/config.h delete mode 100644 src/displaymanager.cpp delete mode 100644 src/displaymanager.h delete mode 100644 src/output.cpp delete mode 100644 src/output.h create mode 100644 src/x.cpp create mode 100644 src/x.h diff --git a/oldsrc/beamergui.pro b/oldsrc/beamergui.pro new file mode 100644 index 0000000..936b664 --- /dev/null +++ b/oldsrc/beamergui.pro @@ -0,0 +1,27 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2013-10-14T14:24:40 +# +#------------------------------------------------- + +QT += core gui + +TARGET = beamergui +TEMPLATE = app + + +SOURCES += main.cpp\ + widget.cpp \ + output.cpp \ + displaymanager.cpp + +HEADERS += \ + widget.h \ + output.h \ + displaymanager.h + +FORMS += widget.ui + + +LIBS += -lXrandr -lX11 + diff --git a/oldsrc/displaymanager.cpp b/oldsrc/displaymanager.cpp new file mode 100644 index 0000000..61f35ea --- /dev/null +++ b/oldsrc/displaymanager.cpp @@ -0,0 +1,36 @@ +#include "displaymanager.h" + + +DisplayManager * DisplayManager::Instance = NULL; + +DisplayManager::DisplayManager() +{ + dpy = NULL; + resources = NULL; + + + // Get initial data (to be freed) + dpy = XOpenDisplay(NULL); + resources = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy)); + + // Get outputs + for (int i = 0; i < resources->noutput; ++i) { + XRROutputInfo *info = XRRGetOutputInfo (dpy, resources, resources->outputs[i]); + if (info->connection == RR_Connected) + Outputs.push_back(Output(dpy, resources, resources->outputs[i])); + XRRFreeOutputInfo(info); + } +} + +DisplayManager::~DisplayManager() +{ + XCloseDisplay(dpy); + XRRFreeScreenResources(resources); +} + +DisplayManager *DisplayManager::Inst() +{ + if (Instance == 0) + Instance = new DisplayManager(); + return Instance; +} diff --git a/oldsrc/displaymanager.h b/oldsrc/displaymanager.h new file mode 100644 index 0000000..775b87b --- /dev/null +++ b/oldsrc/displaymanager.h @@ -0,0 +1,32 @@ +#ifndef DISPLAYMANAGER_H +#define DISPLAYMANAGER_H + +#include +#include "output.h" + +#include +using namespace std; + +class DisplayManager +{ +public: + + inline vector& getConnectedOutputs(){ return Outputs; } + +private: + + Display *dpy; + XRRScreenResources *resources; + vector Outputs; + + +/** Singleton pattern **/ +public: + static DisplayManager * Inst(); +private: + static DisplayManager * Instance; + DisplayManager(); + ~DisplayManager(); +}; + +#endif // DISPLAYMANAGER_H diff --git a/oldsrc/main.cpp b/oldsrc/main.cpp new file mode 100644 index 0000000..cb48fbb --- /dev/null +++ b/oldsrc/main.cpp @@ -0,0 +1,11 @@ +#include +#include "widget.h" + + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + Widget w; + w.show(); + return a.exec(); +} diff --git a/oldsrc/output.cpp b/oldsrc/output.cpp new file mode 100644 index 0000000..94f6c89 --- /dev/null +++ b/oldsrc/output.cpp @@ -0,0 +1,119 @@ +#include "output.h" +#include "stdio.h" + + +//DEVUTG +#include + +Output::Output(Display *dpy, XRRScreenResources *resources, RROutput output) + :dpy(dpy), resources(resources), ID(output) +{ + +} + + +bool Output::hasEDID() const +{ + int nprop; + Atom *props = XRRListOutputProperties(dpy, ID, &nprop); + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + unsigned char *prop; + XRRPropertyInfo *propinfo; + int bytes_per_item, k; + + for (int i = 0; i < nprop; ++i) { + char *atom_name = XGetAtomName (dpy, props[i]); + if ( strcmp (atom_name, "EDID") == 0) + { + fprintf (stderr, "EDIDCHECK"); + XRRGetOutputProperty (dpy, ID, props[i], + 0, 100, False, False, + AnyPropertyType, + &actual_type, &actual_format, + &nitems, &bytes_after, &prop); + + propinfo = XRRQueryOutputProperty(dpy, ID, props[i]); + bytes_per_item = actual_format / 8; + + fprintf (stderr, "\t%s: ", atom_name); + + for (k = 0; k < nitems; k++) + { + if (k != 0) + { + if ((k % 16) == 0) + { + fprintf (stderr, "\n\t\t"); + } + } + const uint8_t *val = prop + (k * bytes_per_item); + fprintf (stderr, "%d02", *val); + + } + free(propinfo); + return true; + } + } + +} + + + +bool Output::isProjector() const +{ + XRROutputInfo *info = XRRGetOutputInfo (dpy, resources, ID); + bool result = ( info->mm_height == 0 && info->mm_width == 0 ); + XRRFreeOutputInfo(info); + return result; +} + +Resolution Output::getCurrentMode() const +{ + XRROutputInfo *OutputInfo = XRRGetOutputInfo (dpy, resources, ID); + XRRCrtcInfo *CrtcInfo = XRRGetCrtcInfo(dpy, resources, OutputInfo->crtc); + Resolution result = { CrtcInfo->width, CrtcInfo->height }; + XRRFreeCrtcInfo(CrtcInfo); + XRRFreeOutputInfo(OutputInfo); + return result; +} + + +Resolution Output::getPreferredMode() const +{ + XRROutputInfo *OutputInfo = XRRGetOutputInfo (dpy, resources, ID); + RRMode preferred = OutputInfo->modes[OutputInfo->npreferred]; + XRRFreeOutputInfo(OutputInfo); + return getResolution(preferred); +} + + +QSet Output::getSupportedModes() const +{ + QSet result; + XRROutputInfo *info = XRRGetOutputInfo (dpy, resources, ID); + for (int i = 0; i < info->nmode; ++i) + result.insert(getResolution(info->modes[i])); + XRRFreeOutputInfo(info); + return result; +} + + +Resolution Output::addMode(Resolution) const +{ + // TODO + return Resolution(); +} + +Resolution Output::getResolution(RRMode mode) const +{ + for (int i = 0; i < resources->nmode; ++i) { + if ( resources->modes[i].id == mode ) { + Resolution res = {resources->modes[i].width, resources->modes[i].height}; + return res; + } + } + fprintf ( stderr, "Could not find a mode for the requested XID %d", (int)mode); + exit(1); +} diff --git a/oldsrc/output.h b/oldsrc/output.h new file mode 100644 index 0000000..553444d --- /dev/null +++ b/oldsrc/output.h @@ -0,0 +1,47 @@ +#ifndef OUTPUT_H +#define OUTPUT_H + +#include +#include + +#include +#include + +typedef struct _Resolution{ + unsigned int width; + unsigned int height; +}Resolution; + +inline bool operator==(const Resolution& lhs, const Resolution& rhs) { + return lhs.width == rhs.width && lhs.height == rhs.height; +} + +inline uint qHash(const Resolution &key) +{ + return qHash(key.width ^ key.height); +} + +class Output +{ +public: + + + Output(Display *dpy, XRRScreenResources *resources, RROutput output); + + bool hasEDID() const; + bool isProjector() const; + Resolution getCurrentMode() const; + Resolution getPreferredMode() const; + QSet getSupportedModes() const; + Resolution addMode(Resolution) const; + +private: + + Display *dpy; + XRRScreenResources *resources; + RROutput ID; + + Resolution getResolution(RRMode) const; +}; + +#endif // OUTPUT_H diff --git a/oldsrc/widget.cpp b/oldsrc/widget.cpp new file mode 100644 index 0000000..7867f92 --- /dev/null +++ b/oldsrc/widget.cpp @@ -0,0 +1,145 @@ +#include "widget.h" +#include "ui_widget.h" +#include "displaymanager.h" + + +//#include +//#include +//#include +#include +using namespace std; + +#include + +Widget::Widget(QWidget *parent) : + QWidget(parent), + ui(new Ui::Widget) +{ + ui->setupUi(this); + + DisplayManager* DM = DisplayManager::Inst(); + + for (std::vector::iterator i = DM->getConnectedOutputs().begin(); i != DM->getConnectedOutputs().end(); ++i) + { + qDebug() << "EDID?" << ( (*i).hasEDID() ? "true" : "false"); + qDebug() << "Proj?" << ( (*i).isProjector() ? "true" : "false"); + qDebug() << "Current?" << (*i).getCurrentMode().width<< (*i).getCurrentMode().height; + qDebug() << "Preferred?" << (*i).getPreferredMode().width << (*i).getPreferredMode().height; + QSet modes = (*i).getSupportedModes(); + for ( QSet::iterator i = modes.begin(); i != modes.end(); ++i ) + { + qDebug() << "---- " << (*i).width << (*i).height; + } + } + + + + + +// XManager * XM = XManager::Inst(); + + +// switch ( XM->getOutputInfos().size() ){ +// /*************************************************************************/ +// case 1:// In case of one connected output - xrandr --auto +// qDebug() << "Normal output"; +// exit(0); +// break; +// /*************************************************************************/ +// case 2: // In case of two connected outputs + +// /*********************************************************************/ +// // If one of the two connected outputs is a beamer +// if ( true ) //( XM->getOutputInfos()[0]->mm_width == 0 && XM->getOutputInfos()[0]->mm_height == 0 ) +// // || ( XM->getOutputInfos()[1]->mm_width == 0 && XM->getOutputInfos()[1]->mm_height == 0 ) ) +// { +// /*****************************************************************/ +// // If the beamer transmits reliable EDID data. +// if( isReliableEDIDpresent() ) +// { +// qDebug() << "beamer output reliable EDID "; +// configureWidgetForBeamerWithEDID(); +// } +// /*****************************************************************/ +// // If the beamer DOES NOT transmits reliable EDID data. +// else +// { +// qDebug() << "beamer output no reliable EDID "; +// configureWidgetForBeamerWithEDID(); +// } +// /*****************************************************************/ + +// } +// /*********************************************************************/ +// // If NEITHER of the outputs is a beamer (likely dualscreen setup) +// else +// { +// // Just apply preferred settings +// qDebug() << "dualscreen output"; + +// } +// break; +// /*************************************************************************/ +// default: +// // If there are more than 3 outputs +// // its up to the user. Quit. +// exit(0); +// break; +// } +// /*************************************************************************/ + + + + + + + //Remove borders and stuff + setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + + + + + // QSet outputs0, outputs1; + // for (int i = 0; i < XManager::Inst()->getOutputInfos()[0]->nmode; ++i) + // outputs0.insert(XManager::Inst()->getOutputInfos()[0]->modes[i]); + // for (int i = 0; i < XManager::Inst()->getOutputInfos()[1]->nmode; ++i) + // outputs1.insert(XManager::Inst()->getOutputInfos()[1]->modes[i]); + // outputs0.intersect(outputs1); + + // // Fill treewidget with data from cups dests; + // for ( QSet::iterator it = outputs0.begin(); it != outputs0.end(); ++it ) + // { + // qDebug() << *it; + // qDebug() << XManager::Inst()->getModeMap()[*it]; + // ui->comboBox->addItem(XManager::Inst()->getModeMap().at(*it), (unsigned long long int)*it); + // } + + // // Fill treewidget with data from cups dests; + // for ( map::iterator it = XManager::Inst()->getModeMap().begin(); it != XManager::Inst()->getModeMap().end(); ++it ) + // { + // qDebug() << it->first ; + //// qDebug() << XManager::getInstance()->getModeMap()[*it]; + //// ui->comboBox->addItem(XManager::getInstance()->getModeMap().at(*it), (unsigned long long int)*it); + // } + + // Resize widget to its content + resize(sizeHint()); + + // Center dialog on screenbottom + const QRect desktopRect = QApplication::desktop()->screenGeometry(); + this->move( desktopRect.width()/2-this->width()/2, + desktopRect.height()-this->height()); + } + + Widget::~Widget() + { + delete ui; + } + + void Widget::configureWidgetForBeamerWithEDID() + { + } + + void Widget::configureWidgetForBeamerWithOUTEDID() + { + } diff --git a/oldsrc/widget.h b/oldsrc/widget.h new file mode 100644 index 0000000..fc8570a --- /dev/null +++ b/oldsrc/widget.h @@ -0,0 +1,31 @@ +#ifndef WIDGET_H +#define WIDGET_H + +#include +#include + +#include +#include + +namespace Ui { +class Widget; +} + +class Widget : public QWidget +{ + Q_OBJECT + +public: + explicit Widget(QWidget *parent = 0); + ~Widget(); + +private: + + Ui::Widget * ui; + + void configureWidgetForBeamerWithEDID(); + void configureWidgetForBeamerWithOUTEDID(); + +}; + +#endif // WIDGET_H diff --git a/oldsrc/widget.ui b/oldsrc/widget.ui new file mode 100644 index 0000000..cfa9bdf --- /dev/null +++ b/oldsrc/widget.ui @@ -0,0 +1,39 @@ + + + Widget + + + + 0 + 0 + 600 + 480 + + + + + 0 + 0 + + + + + + + + + + + + PushButton + + + + + + + + + + + diff --git a/src/beamer.conf2 b/src/beamer.conf2 new file mode 100644 index 0000000..0cf780f --- /dev/null +++ b/src/beamer.conf2 @@ -0,0 +1,26 @@ +# 16:10 +Modeline 83.50 1280 1352 1480 1680 800 803 809 831 -hsync +vsync +Modeline 106.50 1440 1528 1672 1904 900 903 909 934 -hsync +vsync +Modeline 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync +Modeline 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync +Modeline 348.50 2560 2760 3032 3504 1600 1603 1609 1658 -hsync +vsync + +# 16:9 +Modeline 74.50 1280 1344 1472 1664 720 723 728 748 -hsync +vsync +Modeline 85.25 1368 1440 1576 1784 768 771 781 798 -hsync +vsync +Modeline 118.25 1600 1696 1856 2112 900 903 908 934 -hsync +vsync +Modeline 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync +Modeline 312.25 2560 2752 3024 3488 1440 1443 1448 1493 -hsync +vsync + +# 4:3 +Modeline 38.25 800 832 912 1024 600 603 607 624 -hsync +vsync +Modeline 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync +Modeline 81.75 1152 1216 1336 1520 864 867 871 897 -hsync +vsync +Modeline 101.25 1280 1360 1488 1696 960 963 967 996 -hsync +vsync +Modeline 121.75 1400 1488 1632 1864 1050 1053 1057 1089 -hsync +vsync + +# Display to use +Display :0 + +# IP specific configs +IP 132.230.4.100 1280x900 diff --git a/src/beamergui.pro b/src/beamergui.pro index 936b664..6c1fbdc 100644 --- a/src/beamergui.pro +++ b/src/beamergui.pro @@ -12,16 +12,15 @@ TEMPLATE = app SOURCES += main.cpp\ widget.cpp \ - output.cpp \ - displaymanager.cpp + config.cpp \ + x.cpp -HEADERS += \ - widget.h \ - output.h \ - displaymanager.h +HEADERS += widget.h \ + displaymanager.h \ + config.h \ + x.h FORMS += widget.ui LIBS += -lXrandr -lX11 - diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..1e3f827 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" + +#define GROUP_GENERAL "General" +#define GROUP_MODELINES "Modelines" +#define GROUP_SPECIFIC "SpecificSettings" +#define DISPLAY_KEY "display" +#define DISPLAY_DEFAULT ":0" +#define IFACE_KEY "interface" +#define IFACE_DEFAULT "eth0" + +Config * Config::Instance = NULL; + +//_____________________________________________________________________________ + + +Config::Config() +{ + // Defaults + display = ":0"; + interface = "eth0"; +} + +//_____________________________________________________________________________ + + +void Config::loadSettings(QString _file) +{ + // Open setting file + settingsPath = _file; + QSettings settings(settingsPath, QSettings::NativeFormat); + + // Get general information + settings.beginGroup(GROUP_GENERAL); + display = settings.value(DISPLAY_KEY, DISPLAY_DEFAULT).toString(); + interface = settings.value(IFACE_KEY, IFACE_DEFAULT).toString(); + settings.endGroup(); + + + /* Check for ip specific settings */ + + // Get local ip + QString IPV4 = getIPV4ofInterface(interface); + + // Find any information saved about this ip + settings.beginGroup(GROUP_SPECIFIC); + if ( settings.contains(IPV4) ) + ipSpecificXConf = settings.value(IPV4).toStringList(); + settings.endGroup(); + + + /* Get the "must-have-modelines" */ + + settings.beginGroup(GROUP_MODELINES); + + // Get all keys in this group (Keys are modenames) + QStringList modeKeys = settings.allKeys(); + + // Get the modeline for each key + for (QStringList::const_iterator i = modeKeys.constBegin(); i != modeKeys.constEnd(); ++i) + { + // Prepend the name and save in list + modeLines.insert(*i, settings.value(*i).toStringList()); + } + settings.endGroup(); + +} + +//_____________________________________________________________________________ + + +QString Config::getIPV4ofInterface(QString _if) const +{ + struct ifaddrs * ifAddrStruct=NULL; + struct ifaddrs * ifa=NULL; + void * tmpAddrPtr=NULL; + QString result; + + getifaddrs(&ifAddrStruct); + + // Iterate through the adresses. + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) + { + // If the address is IP V4 and the interface is _if + if (ifa ->ifa_addr->sa_family==AF_INET && ( strcmp(ifa->ifa_name, _if.toUtf8().constData()) == 0) ) + { + // Get the IP + tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; + + // convert to readable form + char addressBuffer[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); + result = addressBuffer; + } + } + + // clean up + if (ifAddrStruct!=NULL) + freeifaddrs(ifAddrStruct); + + return result; +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..20f67d3 --- /dev/null +++ b/src/config.h @@ -0,0 +1,45 @@ +#ifndef CONIG_H +#define CONIG_H + +#include +#include +#include +#include +#include + +#define CONFIG_PATH "/home/manuel/beamer.conf" + +class Config +{ + Config(); + ~Config(); + + static Config * Instance; + + QString settingsPath; + QString display; + QString interface; + QStringList ipSpecificXConf; + QMap modeLines; + + QString getIPV4ofInterface(QString) const; + +public: + + void loadSettings(QString); + + // Getters + inline const QString& getSettingsPath() { return settingsPath; } + inline const QString& getDisplay() { return display; } + inline const QString& getInterface() { return interface; } + inline const QStringList& getIpSpecificXConf(){ return ipSpecificXConf; } + inline const QMap& getModeLines() { return modeLines; } + + // Singleton // + inline static Config * inst() { + if (Instance == NULL) Instance = new Config(); + return Instance; + } +}; + +#endif // CONIG_H diff --git a/src/displaymanager.cpp b/src/displaymanager.cpp deleted file mode 100644 index 61f35ea..0000000 --- a/src/displaymanager.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "displaymanager.h" - - -DisplayManager * DisplayManager::Instance = NULL; - -DisplayManager::DisplayManager() -{ - dpy = NULL; - resources = NULL; - - - // Get initial data (to be freed) - dpy = XOpenDisplay(NULL); - resources = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy)); - - // Get outputs - for (int i = 0; i < resources->noutput; ++i) { - XRROutputInfo *info = XRRGetOutputInfo (dpy, resources, resources->outputs[i]); - if (info->connection == RR_Connected) - Outputs.push_back(Output(dpy, resources, resources->outputs[i])); - XRRFreeOutputInfo(info); - } -} - -DisplayManager::~DisplayManager() -{ - XCloseDisplay(dpy); - XRRFreeScreenResources(resources); -} - -DisplayManager *DisplayManager::Inst() -{ - if (Instance == 0) - Instance = new DisplayManager(); - return Instance; -} diff --git a/src/displaymanager.h b/src/displaymanager.h deleted file mode 100644 index 775b87b..0000000 --- a/src/displaymanager.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef DISPLAYMANAGER_H -#define DISPLAYMANAGER_H - -#include -#include "output.h" - -#include -using namespace std; - -class DisplayManager -{ -public: - - inline vector& getConnectedOutputs(){ return Outputs; } - -private: - - Display *dpy; - XRRScreenResources *resources; - vector Outputs; - - -/** Singleton pattern **/ -public: - static DisplayManager * Inst(); -private: - static DisplayManager * Instance; - DisplayManager(); - ~DisplayManager(); -}; - -#endif // DISPLAYMANAGER_H diff --git a/src/main.cpp b/src/main.cpp index cb48fbb..9c95f7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,431 @@ + + #include +#include +#include +#include +#include #include "widget.h" +#include "config.h" +#include "x.h" + + +// Prototypes +QString getIP (); + +void usage() +{ +} int main(int argc, char *argv[]) { +// /////////////////// +// // Debug +// argv[1] = "/home/manuel/beamer.conf"; +// ///////////////////7 + +// if ( argc < 1 ) +// { +// std::cerr << "Too many arguments. The only parameter shall be a path to a config file." << std::endl; +// exit(1); +// } +// if ( argc == 1 ) +// { +// // Check if file exists +// std::ifstream f(argv[1]); +// if (!f) +// { +// std::cerr << "The config file does not exist" << std::endl; +// exit(1); +// } +// else +// f.close(); +// } + +// //Load settings +// Config::inst()->loadSettings(argv[1]); +// qDebug() << X::Screen::inst(); + + +// qDebug() << Config::inst()->getDisplay(); +// qDebug() << Config::inst()->getInterface(); +// qDebug() << Config::inst()->getIpSpecificXConf(); +// qDebug() << Config::inst()->getModeLines(); +// qDebug() << Config::inst()->getSettingsPath(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// // Get initial data (to be freed) +// Display *dpy = XOpenDisplay(NULL); +// XRRScreenResources *sr = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy)); + + + + +// int X=1;RandR:: +// int M=1; + +// XRROutputInfo *output_first_info = XRRGetOutputInfo(dpy, sr, sr->outputs[X]); + +// // XRRSet +// // HOLY +// XRRSetCrtcConfig(dpy, +// sr, +// output_first_info->crtc, +// CurrentTime, +// 0, 0, +// sr->modes[output_first_info->npreferred -1].id, +// RR_Rotate_0, +// &sr->outputs[X], +// 1); + + + + + + + + + + QApplication a(argc, argv); Widget w; w.show(); return a.exec(); } + + + + +////////////////////////////////////////// CODE MÜLLEIMER + + + // eine datei + + +//Widget::Widget(QWidget *parent) : +// QWidget(parent), +// ui(new Ui::Widget) +//{ +// ui->setupUi(this); + +// for (std::vector::iterator i = DisplayManager::Inst()->getConnectedOutputs().begin(); +// i != DisplayManager::Inst()->getConnectedOutputs().end(); +// ++i) +// { +// qDebug() << "EDID?" << ( (*i).hasEDID() ? "true" : "false"); +// qDebug() << "Proj?" << ( (*i).isProjector() ? "true" : "false"); +// qDebug() << "Current?" +// << DisplayManager::Inst()->getResolution((*i).getCurrentMode()).width +// << DisplayManager::Inst()->getResolution((*i).getCurrentMode()).height; +// Resolution res; +// if ((*i).getPreferredMode()) +// qDebug() << "Preferred?" +// << DisplayManager::Inst()->getResolution((*i).getPreferredMode()).width +// << DisplayManager::Inst()->getResolution((*i).getPreferredMode()).height; + +// QSet modes = (*i).getSupportedModes(); + +// for ( QSet::iterator i = modes.begin(); i != modes.end(); ++i ) +// { +// qDebug() << "---- " +// << DisplayManager::Inst()->getResolution(*i).width +// << DisplayManager::Inst()->getResolution(*i).height; +// } +// } + + +// switch ( DisplayManager::Inst()->getConnectedOutputs().size() ){ +// /*************************************************************************/ +// case 1:// In case of one connected output - xrandr --auto +// qDebug() << "Normal output"; +// exit(0); +// break; +// /*************************************************************************/ +// case 2: // In case of two connected outputs + +// /*********************************************************************/ +// // If one of the two connected outputs is a beamer + +// if ( true)//DisplayManager::Inst()->isProjectorConnected() ) +// { +// /* +// Here the usecases have to be listed theoretically there are two +// in this case. 2 Projectors, 1 projectors and on monitor. Only the +// latter is asumed here. +// */ + +// // Remember which one is the projector +// int ProjectorIndex; +// DisplayManager::Inst()->getConnectedOutputs().at(0).isProjector() +// ? ProjectorIndex = 0 : ProjectorIndex = 0; + +// /*****************************************************************/ +// // If the beamer transmits reliable EDID data. +// if( DisplayManager::Inst()->getConnectedOutputs().at(ProjectorIndex).hasEDID() ) +// { +// // Now we can assume that the preferred mode of the projector to be correnct +// // to be correct. + +// // Get the AR of the beamer +// Resolution res; +// if ( DisplayManager::Inst()->getConnectedOutputs().at(ProjectorIndex).getPreferredMode() ) +// fprintf(stderr, "Beamer has EDID but no preferred mode."); + +// float AR = res.width/res.height; + +// QSet BeamerModes = +// DisplayManager::Inst()->getConnectedOutputs().at(ProjectorIndex).getSupportedModes(); + +// QSet MonitorModes = +// DisplayManager::Inst()->getConnectedOutputs().at(1-ProjectorIndex).getSupportedModes(); + +// QSet CommonModes = BeamerModes.unite(MonitorModes); + +// CommonModes.intersect(BeamerModes); +// CommonModes.intersect(MonitorModes); + +// // Fill treewidget with data from cups dests; +// for ( QSet::iterator i = CommonModes.begin(); i != CommonModes.end(); ++i ) +// { +// char * ModeString; +// sprintf(ModeString, "%dx%d", +// DisplayManager::Inst()->getResolution(*i).width, +// DisplayManager::Inst()->getResolution(*i).height +// ); + +// qDebug() << ModeString; +// ui->comboBox->addItem(ModeString, QVariant((unsigned long long int)*i)); +// } +// } +// /*****************************************************************/ +// // If the beamer DOES NOT transmits reliable EDID data. +// else +// { +// qDebug() << "beamer output no reliable EDID "; +// configureWidgetForBeamerWithEDID(); +// } +// /*****************************************************************/ + +// } +// /*********************************************************************/ +// // If NEITHER of the outputs is a beamer (likely dualscreen setup) +// else +// { +// // Just apply preferred settings + +// qDebug() << "dualscreen output"; + +// } +// break; +// /*************************************************************************/ +// default: +// // If there are more than 3 outputs +// // its up to the user. Quit. +// exit(0); +// break; +// } +// /*************************************************************************/ + + + + + + +// //Remove borders and stuff +// setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + + + + +// // QSet outputs0, outputs1; +// // for (int i = 0; i < XManager::Inst()->getOutputInfos()[0]->nmode; ++i) +// // outputs0.insert(XManager::Inst()->getOutputInfos()[0]->modes[i]); +// // for (int i = 0; i < XManager::Inst()->getOutputInfos()[1]->nmode; ++i) +// // outputs1.insert(XManager::Inst()->getOutputInfos()[1]->modes[i]); +// // outputs0.intersect(outputs1); + +// // // Fill treewidget with data from cups dests; +// // for ( QSet::iterator it = outputs0.begin(); it != outputs0.end(); ++it ) +// // { +// // qDebug() << *it; +// // qDebug() << XManager::Inst()->getModeMap()[*it]; +// // ui->comboBox->addItem(XManager::Inst()->getModeMap().at(*it), (unsigned long long int)*it); +// // } + +// // // Fill treewidget with data from cups dests; +// // for ( map::iterator it = XManager::Inst()->getModeMap().begin(); it != XManager::Inst()->getModeMap().end(); ++it ) +// // { +// // qDebug() << it->first ; +// //// qDebug() << XManager::getInstance()->getModeMap()[*it]; +// //// ui->comboBox->addItem(XManager::getInstance()->getModeMap().at(*it), (unsigned long long int)*it); +// // } + +// // Resize widget to its content +// resize(sizeHint()); + +// // Center dialog on screenbottom +// const QRect desktopRect = QApplication::desktop()->screenGeometry(); +// this->move( desktopRect.width()/2-this->width()/2, +// desktopRect.height()-this->height()); +// } + +// Widget::~Widget() +// { +// delete ui; +// } + +// void Widget::configureWidgetForBeamerWithEDID() +// { +// } + +// void Widget::configureWidgetForBeamerWithOUTEDID() +// { +// } + + + + + + // eine andre datei + + + + + + +//Widget::Widget(QWidget *parent) : +// QWidget(parent), +// ui(new Ui::Widget) +//{ +// ui->setupUi(this); + + +// X11::XManager * XM = X11::XManager::getInstance(); + + +// switch ( XM->getOutputInfos().size() ){ +// /*************************************************************************/ +// case 1:// In case of one connected output - xrandr --auto +// qDebug() << "Normal output"; +// exit(0); +// break; +// /*************************************************************************/ +// case 2: // In case of two connected outputs + +// /*********************************************************************/ +// // If one of the two connected outputs is a beamer +// if ( true ) //( XM->getOutputInfos()[0]->mm_width == 0 && XM->getOutputInfos()[0]->mm_height == 0 ) +// // || ( XM->getOutputInfos()[1]->mm_width == 0 && XM->getOutputInfos()[1]->mm_height == 0 ) ) +// { +// /*****************************************************************/ +// // If the beamer transmits reliable EDID data. +// if( isReliableEDIDpresent() ) +// { +// qDebug() << "beamer output reliable EDID "; +// configureWidgetForBeamerWithEDID(); +// } +// /*****************************************************************/ +// // If the beamer DOES NOT transmits reliable EDID data. +// else +// { +// qDebug() << "beamer output no reliable EDID "; +// configureWidgetForBeamerWithEDID(); +// } +// /*****************************************************************/ + +// } +// /*********************************************************************/ +// // If NEITHER of the outputs is a beamer (likely dualscreen setup) +// else +// { +// // Just apply preferred settings +// qDebug() << "dualscreen output"; + +// } +// break; +// /*************************************************************************/ +// default: +// // If there are more than 3 outputs +// // its up to the user. Quit. +// exit(0); +// break; +// } +// /*************************************************************************/ + + + + +// Remove borders and stuff +// setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + + + + +// QSet outputs0, outputs1; +// for (int i = 0; i < XManager::Inst()->getOutputInfos()[0]->nmode; ++i) +// outputs0.insert(XManager::Inst()->getOutputInfos()[0]->modes[i]); +// for (int i = 0; i < XManager::Inst()->getOutputInfos()[1]->nmode; ++i) +// outputs1.insert(XManager::Inst()->getOutputInfos()[1]->modes[i]); +// outputs0.intersect(outputs1); + +// // Fill treewidget with data from cups dests; +// for ( QSet::iterator it = outputs0.begin(); it != outputs0.end(); ++it ) +// { +// qDebug() << *it; +// qDebug() << XManager::Inst()->getModeMap()[*it]; +// ui->comboBox->addItem(XManager::Inst()->getModeMap().at(*it), (unsigned long long int)*it); +// } + +// // Fill treewidget with data from cups dests; +// for ( map::iterator it = XManager::Inst()->getModeMap().begin(); it != XManager::Inst()->getModeMap().end(); ++it ) +// { +// qDebug() << it->first ; +//// qDebug() << XManager::getInstance()->getModeMap()[*it]; +//// ui->comboBox->addItem(XManager::getInstance()->getModeMap().at(*it), (unsigned long long int)*it); +// } + +// // Resize widget to its content +// resize(sizeHint()); + +// // Center dialog on screenbottom +// const QRect desktopRect = QApplication::desktop()->screenGeometry(); +// this->move( desktopRect.width()/2-this->width()/2, +// desktopRect.height()-this->height()); +//} + + diff --git a/src/output.cpp b/src/output.cpp deleted file mode 100644 index 94f6c89..0000000 --- a/src/output.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "output.h" -#include "stdio.h" - - -//DEVUTG -#include - -Output::Output(Display *dpy, XRRScreenResources *resources, RROutput output) - :dpy(dpy), resources(resources), ID(output) -{ - -} - - -bool Output::hasEDID() const -{ - int nprop; - Atom *props = XRRListOutputProperties(dpy, ID, &nprop); - Atom actual_type; - int actual_format; - unsigned long nitems, bytes_after; - unsigned char *prop; - XRRPropertyInfo *propinfo; - int bytes_per_item, k; - - for (int i = 0; i < nprop; ++i) { - char *atom_name = XGetAtomName (dpy, props[i]); - if ( strcmp (atom_name, "EDID") == 0) - { - fprintf (stderr, "EDIDCHECK"); - XRRGetOutputProperty (dpy, ID, props[i], - 0, 100, False, False, - AnyPropertyType, - &actual_type, &actual_format, - &nitems, &bytes_after, &prop); - - propinfo = XRRQueryOutputProperty(dpy, ID, props[i]); - bytes_per_item = actual_format / 8; - - fprintf (stderr, "\t%s: ", atom_name); - - for (k = 0; k < nitems; k++) - { - if (k != 0) - { - if ((k % 16) == 0) - { - fprintf (stderr, "\n\t\t"); - } - } - const uint8_t *val = prop + (k * bytes_per_item); - fprintf (stderr, "%d02", *val); - - } - free(propinfo); - return true; - } - } - -} - - - -bool Output::isProjector() const -{ - XRROutputInfo *info = XRRGetOutputInfo (dpy, resources, ID); - bool result = ( info->mm_height == 0 && info->mm_width == 0 ); - XRRFreeOutputInfo(info); - return result; -} - -Resolution Output::getCurrentMode() const -{ - XRROutputInfo *OutputInfo = XRRGetOutputInfo (dpy, resources, ID); - XRRCrtcInfo *CrtcInfo = XRRGetCrtcInfo(dpy, resources, OutputInfo->crtc); - Resolution result = { CrtcInfo->width, CrtcInfo->height }; - XRRFreeCrtcInfo(CrtcInfo); - XRRFreeOutputInfo(OutputInfo); - return result; -} - - -Resolution Output::getPreferredMode() const -{ - XRROutputInfo *OutputInfo = XRRGetOutputInfo (dpy, resources, ID); - RRMode preferred = OutputInfo->modes[OutputInfo->npreferred]; - XRRFreeOutputInfo(OutputInfo); - return getResolution(preferred); -} - - -QSet Output::getSupportedModes() const -{ - QSet result; - XRROutputInfo *info = XRRGetOutputInfo (dpy, resources, ID); - for (int i = 0; i < info->nmode; ++i) - result.insert(getResolution(info->modes[i])); - XRRFreeOutputInfo(info); - return result; -} - - -Resolution Output::addMode(Resolution) const -{ - // TODO - return Resolution(); -} - -Resolution Output::getResolution(RRMode mode) const -{ - for (int i = 0; i < resources->nmode; ++i) { - if ( resources->modes[i].id == mode ) { - Resolution res = {resources->modes[i].width, resources->modes[i].height}; - return res; - } - } - fprintf ( stderr, "Could not find a mode for the requested XID %d", (int)mode); - exit(1); -} diff --git a/src/output.h b/src/output.h deleted file mode 100644 index 553444d..0000000 --- a/src/output.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef OUTPUT_H -#define OUTPUT_H - -#include -#include - -#include -#include - -typedef struct _Resolution{ - unsigned int width; - unsigned int height; -}Resolution; - -inline bool operator==(const Resolution& lhs, const Resolution& rhs) { - return lhs.width == rhs.width && lhs.height == rhs.height; -} - -inline uint qHash(const Resolution &key) -{ - return qHash(key.width ^ key.height); -} - -class Output -{ -public: - - - Output(Display *dpy, XRRScreenResources *resources, RROutput output); - - bool hasEDID() const; - bool isProjector() const; - Resolution getCurrentMode() const; - Resolution getPreferredMode() const; - QSet getSupportedModes() const; - Resolution addMode(Resolution) const; - -private: - - Display *dpy; - XRRScreenResources *resources; - RROutput ID; - - Resolution getResolution(RRMode) const; -}; - -#endif // OUTPUT_H diff --git a/src/widget.cpp b/src/widget.cpp index 7867f92..994f3d1 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1,145 +1,98 @@ #include "widget.h" #include "ui_widget.h" -#include "displaymanager.h" - - -//#include -//#include -//#include -#include -using namespace std; +#include +#include #include + Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { - ui->setupUi(this); - - DisplayManager* DM = DisplayManager::Inst(); - - for (std::vector::iterator i = DM->getConnectedOutputs().begin(); i != DM->getConnectedOutputs().end(); ++i) + ui->setupUi(this); + + X::OutputList outputs = X::Screen::inst()->getConnectedOutputList(); + + switch ( X::Screen::inst()->getConnectedOutputList().size() ){ + /*************************************************************************/ + case 1:// In case of one connected output - xrandr --auto + qDebug() << "Normal output"; + exit(0); + break; + /*************************************************************************/ + case 2: // In case of two connected outputs + + // If one of the two connected outputs is a beamer + if (true) + //X::Screen::inst()->getOutputMap()[outputs[0]]->isProjector() + // || X::Screen::inst()->getOutputMap()[outputs[1]]->isProjector() ) { - qDebug() << "EDID?" << ( (*i).hasEDID() ? "true" : "false"); - qDebug() << "Proj?" << ( (*i).isProjector() ? "true" : "false"); - qDebug() << "Current?" << (*i).getCurrentMode().width<< (*i).getCurrentMode().height; - qDebug() << "Preferred?" << (*i).getPreferredMode().width << (*i).getPreferredMode().height; - QSet modes = (*i).getSupportedModes(); - for ( QSet::iterator i = modes.begin(); i != modes.end(); ++i ) - { - qDebug() << "---- " << (*i).width << (*i).height; - } + qDebug() << "Cloned output"; + /*****************************************************************/ + // If the beamer transmits no reliable EDID data add modes + if ( ! ( X::Screen::inst()->getOutputMap()[outputs[0]]->hasReliableEDID() + && X::Screen::inst()->getOutputMap()[outputs[1]]->hasReliableEDID() ) ) + { + // TODO ADD MODES + qDebug() << "Normal output"; + } + + // Get a set of unique modes as string. Ugly but same resolutions may + // have different ids. This means modes are compared by name which is + X::ModeSet ModeSet1 = X::Screen::inst()->getOutputMap()[outputs[0]]->getModeSet(); + X::ModeSet ModeSet2 = X::Screen::inst()->getOutputMap()[outputs[1]]->getModeSet(); + QSet ModeNames1, ModeNames2; + for (X::ModeSet::iterator i = ModeSet1.begin(); + i != ModeSet1.end(); ++i) + ModeNames1.insert(X::Screen::inst()->getModeMap()[*i]._name); + for (X::ModeSet::iterator i = ModeSet2.begin(); + i != ModeSet2.end(); ++i) + ModeNames2.insert(X::Screen::inst()->getModeMap()[*i]._name); + ModeNames1.intersect(ModeNames2); + + // Fill widget with data + for ( QSet::iterator i = ModeNames1.begin(); i != ModeNames1.end(); ++i ) + ui->comboBox->addItem(*i); } + /*********************************************************************/ + // If NEITHER of the outputs is a beamer (likely dualscreen setup) + else + { + // TODO(manuel): Furture feature. Setup dualscreen + qDebug() << "Dual output"; + exit(0); + } + break; + /*************************************************************************/ + default: + // If there are more than 3 outputs + // its up to the user. Quit. + qDebug() << ">2 outputs. Quit."; + exit(0); + break; + } + /*************************************************************************/ -// XManager * XM = XManager::Inst(); - - -// switch ( XM->getOutputInfos().size() ){ -// /*************************************************************************/ -// case 1:// In case of one connected output - xrandr --auto -// qDebug() << "Normal output"; -// exit(0); -// break; -// /*************************************************************************/ -// case 2: // In case of two connected outputs - -// /*********************************************************************/ -// // If one of the two connected outputs is a beamer -// if ( true ) //( XM->getOutputInfos()[0]->mm_width == 0 && XM->getOutputInfos()[0]->mm_height == 0 ) -// // || ( XM->getOutputInfos()[1]->mm_width == 0 && XM->getOutputInfos()[1]->mm_height == 0 ) ) -// { -// /*****************************************************************/ -// // If the beamer transmits reliable EDID data. -// if( isReliableEDIDpresent() ) -// { -// qDebug() << "beamer output reliable EDID "; -// configureWidgetForBeamerWithEDID(); -// } -// /*****************************************************************/ -// // If the beamer DOES NOT transmits reliable EDID data. -// else -// { -// qDebug() << "beamer output no reliable EDID "; -// configureWidgetForBeamerWithEDID(); -// } -// /*****************************************************************/ - -// } -// /*********************************************************************/ -// // If NEITHER of the outputs is a beamer (likely dualscreen setup) -// else -// { -// // Just apply preferred settings -// qDebug() << "dualscreen output"; - -// } -// break; -// /*************************************************************************/ -// default: -// // If there are more than 3 outputs -// // its up to the user. Quit. -// exit(0); -// break; -// } -// /*************************************************************************/ - - - - - - - //Remove borders and stuff - setWindowFlags(windowFlags() | Qt::FramelessWindowHint); - - - - - // QSet outputs0, outputs1; - // for (int i = 0; i < XManager::Inst()->getOutputInfos()[0]->nmode; ++i) - // outputs0.insert(XManager::Inst()->getOutputInfos()[0]->modes[i]); - // for (int i = 0; i < XManager::Inst()->getOutputInfos()[1]->nmode; ++i) - // outputs1.insert(XManager::Inst()->getOutputInfos()[1]->modes[i]); - // outputs0.intersect(outputs1); - - // // Fill treewidget with data from cups dests; - // for ( QSet::iterator it = outputs0.begin(); it != outputs0.end(); ++it ) - // { - // qDebug() << *it; - // qDebug() << XManager::Inst()->getModeMap()[*it]; - // ui->comboBox->addItem(XManager::Inst()->getModeMap().at(*it), (unsigned long long int)*it); - // } - - // // Fill treewidget with data from cups dests; - // for ( map::iterator it = XManager::Inst()->getModeMap().begin(); it != XManager::Inst()->getModeMap().end(); ++it ) - // { - // qDebug() << it->first ; - //// qDebug() << XManager::getInstance()->getModeMap()[*it]; - //// ui->comboBox->addItem(XManager::getInstance()->getModeMap().at(*it), (unsigned long long int)*it); - // } - // Resize widget to its content - resize(sizeHint()); - // Center dialog on screenbottom - const QRect desktopRect = QApplication::desktop()->screenGeometry(); - this->move( desktopRect.width()/2-this->width()/2, - desktopRect.height()-this->height()); - } + // Remove borders and stuff COMMENT FOR DEBUIGGIN + //setWindowFlags(windowFlags() | Qt::FramelessWindowHint); - Widget::~Widget() - { - delete ui; - } + // Resize widget to its content + resize(sizeHint()); - void Widget::configureWidgetForBeamerWithEDID() - { - } + // Center dialog on screenbottom + const QRect desktopRect = QApplication::desktop()->screenGeometry(); + this->move( desktopRect.width()/2-this->width()/2, + desktopRect.height()-this->height()); +} - void Widget::configureWidgetForBeamerWithOUTEDID() - { - } +Widget::~Widget() +{ + delete ui; +} diff --git a/src/widget.h b/src/widget.h index fc8570a..fff5510 100644 --- a/src/widget.h +++ b/src/widget.h @@ -3,9 +3,8 @@ #include #include - -#include -#include +#include +#include namespace Ui { class Widget; @@ -13,18 +12,23 @@ class Widget; class Widget : public QWidget { + Q_OBJECT + public: + explicit Widget(QWidget *parent = 0); ~Widget(); + + +public: + private: Ui::Widget * ui; - void configureWidgetForBeamerWithEDID(); - void configureWidgetForBeamerWithOUTEDID(); }; diff --git a/src/x.cpp b/src/x.cpp new file mode 100644 index 0000000..6c9e0e2 --- /dev/null +++ b/src/x.cpp @@ -0,0 +1,473 @@ +#include "x.h" +#include +namespace X +{ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + + Screen * Screen::_instance = NULL; + + Screen::Screen() + { + // Get initial data (to be freed) + _display = XOpenDisplay(NULL); + _screenResources = XRRGetScreenResourcesCurrent(_display, DefaultRootWindow(_display)); + + /* Get informations about Xserver */ + + // Create the modemap + for (int i = 0; i < _screenResources->nmode; ++i) + { + _modeMap.insert( + _screenResources->modes[i].id, + Mode(&_screenResources->modes[i]) + ); + } + + // Create crtcMap + for (int i = 0; i < _screenResources->ncrtc; ++i) + { + _crtcMap.insert( + _screenResources->crtcs[i], + Crtc(_screenResources->crtcs[i],this) + ); + } + + // Create outputMap + for (int i = 0; i < _screenResources->noutput; ++i) + { + _outputMap.insert( + _screenResources->outputs[i], + new Output(_screenResources->outputs[i], this) + ); + } + + // Create connectedOutputMap + for (OutputMap::iterator it = _outputMap.begin(); + it != _outputMap.end(); ++it) + if ( (*it)->isConnected() ) + _connectedOutputList.push_back((*it)->_id); + + } + + //___________________________________________________________________________ + Screen::~Screen() + { + XCloseDisplay(_display); + XRRFreeScreenResources(_screenResources); + for (int i = 0; i < _outputMap.size(); ++i) + delete _outputMap[i]; + } + + +// //_________________________________________________________________________ +//// int Screen::applyChanges() +//// { +//// // First make backup to restore in case of an error or user interaction + +//// // Calculate screensize +//// QRect screenSize; +//// for (CrtcMap::iterator i = _crtcMap.begin(); i != _crtcMap.end(); ++i) +//// screenSize = screenSize.united(i->getRect()); + +//// /* values from xrandr */ +//// float dpi = (25.4 * DisplayHeight(_display, 0)) / +//// DisplayHeightMM(_display, 0); +//// int widthMM = (int) ((25.4 * screenSize.width()) / dpi); +//// int heightMM = (int) ((25.4 * screenSize.height()) / dpi); + +//// // Set screensize +//// XRRSetScreenSize(_display, DefaultRootWindow(_display), +//// screenSize.width(), +//// screenSize.height(), +//// widthMM, heightMM); + +//// // Apply changes of each crtc +//// // Stupid applying here, sanitychecks have to be done before +//// for (CrtcMap::iterator i = _crtcMap.begin(); i != _crtcMap.end(); ++i) +//// { +//// if ( i->applyChanges() ) +//// { +//// revertChanges(); +//// return EXIT_FAILURE; +//// } +//// } +//// return EXIT_SUCCESS; +//// } + + +//// //_________________________________________________________________________ +//// void Screen::revertChanges() +//// { +//// // TODO +//// } + +//// OutputList Screen::getConnectedOutputs() const +//// { +//// OutputList result; +//// for (OutputMap::const_iterator it = _outputMap.begin(); +//// it != _outputMap.end(); ++it) +//// if (it->isConnected()) +//// result.push_back(it->_id); +//// return result; +//// } + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + XElement::XElement(XID xid) + : _id(xid), _validity(false) {} + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + Mode::Mode(XRRModeInfo *info) + { + if ( info == NULL ) + return; + _id = info->id; + _dotClock = info->dotClock; + _hSyncStart = info->hSyncStart; + _hSyncEnd = info->hSyncEnd; + _hTotal = info->hTotal; + _hSkew = info->hSkew; + _vSyncStart = info->vSyncStart; + _vSyncEnd = info->vSyncEnd; + _vTotal = info->vTotal; + _name = QString(info->name); + _modeFlags = info->modeFlags; + _resolution.setWidth(info->width); + _resolution.setHeight(info->height); + _validity = true; + // rate = ((float) info->dotClock / ((float) info->hTotal * (float) info->vTotal)); + + qDebug() << "Mode: " << _id << _resolution.width() << _resolution.height(); + } + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + Crtc::Crtc(XID id = None, Screen * parent = NULL) + : XElement(id), _parent(parent) + { + // Get the information from XRROutputInfo + XRRCrtcInfo * info = XRRGetCrtcInfo( + const_cast(_parent->display()), + const_cast(_parent->screenResources()), + id); + + // Leave invalid if XID not existent + if ( !info ){ + return; + } + + _timestamp = info->timestamp; + _crtcRect = QRect( + info->x, + info->y, + info->width, + info->height); + _mode = info->mode; + + for (int i = 0; i < info->noutput; ++i) + _outputs.append(info->outputs[i]); + + for (int i = 0; i < info->npossible; ++i) + _possible.append(info->possible[i]); + + _rotation = info->rotation; + _rotations = info->rotations; + _validity = true; + XRRFreeCrtcInfo(info); + + qDebug() << "Crtc: " << _id << _mode << _outputs + << _crtcRect; + } + +//// int Crtc::applyChanges() +//// { +//// return XRRSetCrtcConfig(_parent->display, +//// _parent->screenResources, +//// _id, +//// _timestamp, +//// _crtcRect.x(), +//// _crtcRect.y(), +//// _mode, +//// _rotation, +//// _outputs.toVector().data(), +//// _outputs.size() +//// ); +//// } + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + Output::Output(XID id, Screen * parent) + : XElement(id), _parent(parent), _hasReliableEDID(false) + { + // Get the information from XRROutputInfo + XRROutputInfo* info = XRRGetOutputInfo( + const_cast(_parent->display()), + const_cast(_parent->screenResources()), + id); + + // Leave invalid if XID not existent + if ( !info ){ + return; + } + + _timestamp = info->timestamp; + _crtc = info->crtc; + _name = QString(info->name); + _metricDimension.setWidth(info->mm_width); + _metricDimension.setHeight(info->mm_height); + _connection = (State)info->connection; + //subpixel_order = info->subpixel_order; + for (int i = 0; i < info->ncrtc; ++i) + _crtcs.append(info->crtcs[i]); + for (int i = 0; i < info->nclone; ++i) + _clones.append(info->clones[i]); + + // List the supported modes and extract preferred + // This is the point where creating the modemap before the outputmap + // gets a contition. + for (int i = 0; i < info->nmode; ++i){ + _modes.insert(info->modes[i]); + if (i < info->npreferred) + _preferred = i; + } + XRRFreeOutputInfo(info); + + // Check if this is a beamer + _isProjector = _metricDimension.isEmpty(); + + // Maybe obsolete, since no preferred mode means no EDID. + // // EDID = ?; + int nprop; + Atom *props = XRRListOutputProperties( + const_cast(_parent->display()), + _id, + &nprop); + + for (int i = 0; i < nprop; ++i) + { + char *atom_name = XGetAtomName ( + const_cast(_parent->display()), + props[i]); + if ( strcmp (atom_name, "EDID") == 0) + { +// // Print Stuff +// unsigned long nitems, bytes_after; +// unsigned char *prop; +// int actual_format; +// Atom actual_type; +// int bytes_per_item; + +// XRRGetOutputProperty (dpy, ID, props[i], +// 0, 100, False, False, +// AnyPropertyType, +// &actual_type, &actual_format, +// &nitems, &bytes_after, &prop); + +// XRRPropertyInfo *propinfo = XRRQueryOutputProperty(dpy, ID, props[i]); +// bytes_per_item = actual_format / 8; + +// fprintf (stderr, "\t%s: ", atom_name); +// for (unsigned int k = 0; k < nitems; k++) +// { +// if (k != 0) +// { +// if ((k % 16) == 0) +// { +// fprintf (stderr, "\n\t\t"); +// } +// } +// const uint8_t *val = prop + (k * bytes_per_item); +// fprintf (stderr, "%d02", *val); +// } +// free(propinfo); + _hasReliableEDID = true; + } + } + free(props); + + + qDebug() << "Output: " << _id << _name << _crtc + << _metricDimension << _clones << _modes; + } + +// //_________________________________________________________________________ +//// int Screen::Output::changeMode(XID mode) +//// { +//// // Check if this mode is supported +//// if ( ! _modes.contains(mode) ) +//// return 1; + +//// // Check if this output is connected +//// if ( _connection != Output::Connected ) +//// return 2; + +//// // If this output is NOT conected to a crtc +//// if ( ! isActive() ) +//// { +//// // Try to find a unconnected crtc which +//// // this output can be connected to +//// for (CrtcList::iterator i = _crtcs.begin(); ; ++i) +//// { +//// // If this search reches end no appropriate +//// // crtc has been found +//// if ( i == _crtcs.end() ) +//// return 3; + +//// // If a free crtc was found connect and apply mode +//// if ( _parent->_crtcMap[*i].getConnectedOutputs().empty() ) +//// { +//// _parent->_crtcMap[*i].connect(this, mode); +//// break; +//// } +//// } +//// } +//// //If it is already connected apply mode to the crtc +//// // TODO(Manuel):continue +//// return 0; +//// } + +//// //_________________________________________________________________________ +//// int Output::changePos() +//// { +//// return 1; +//// } +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +} + + + + + + + + + + + + + + + + + + + + + + + +//// qDebug() << XRRSetCrtcConfig(display, +//// screenResources, +//// screenResources->crtcs[1], +//// CurrentTime, +//// 0, 0, +//// 597, +//// RR_Rotate_0, +//// &(screenResources->outputs[3]), +//// 1); +//// qDebug() << XRRSetCrtcConfig(display, +//// screenResources, +//// screenResources->crtcs[0], +//// CurrentTime, +//// 1920, 0, +//// 586, +//// RR_Rotate_0, +//// &(screenResources->outputs[1]), +//// 1); +//// HOLY!! +//// XRRSetCrtcConfig(display, +//// screenResources, +//// screenResources->crtcs[1], +//// CurrentTime, +//// 0, 0, +//// 587, +//// RR_Rotate_0, +//// &screenResources->outputs[1], +//// 1); + + + + + + + + + +/////////////////////////////// DBEUG //// DEBUG ////////////////////////////////// +//// //SCREEN +//// qDebug() << "ScreenResources: "; +//// qDebug() << "Count of crtcs: " << screenResources->ncrtc; +//// qDebug() << "Count of outputs: " << screenResources->noutput; +//// qDebug() << "Count of modes: " << screenResources->nmode; + +//// //MODES +//// for (int i = 0; i < screenResources->nmode; ++i) +//// { +//// qDebug() << screenResources->modes[i].id +//// << screenResources->modes[i].width +//// << screenResources->modes[i].height +////// << screenResources->modes[i].dotClock +////// << screenResources->modes[i].hSyncStart +////// << screenResources->modes[i].hSyncEnd +////// << screenResources->modes[i].hTotal +////// << screenResources->modes[i].hSkew +////// << screenResources->modes[i].vSyncStart +////// << screenResources->modes[i].vSyncEnd +////// << screenResources->modes[i].vTotal +////// << screenResources->modes[i].nameLength +//// << screenResources->modes[i].name; +//// } + +//// //CRTCS +//// for (int j = 0; j < screenResources->ncrtc; ++j) +//// { +//// XRRCrtcInfo *CrtcInfo = XRRGetCrtcInfo(display, screenResources, screenResources->crtcs[j]); +//// qDebug() << "\n-------- CrtcInfo"; +//// qDebug() << "timestamp: " << CrtcInfo->timestamp; +//// qDebug() << "x: " << CrtcInfo->x; +//// qDebug() << "y: " << CrtcInfo->y; +//// qDebug() << "width: " << CrtcInfo->width; +//// qDebug() << "height: " << CrtcInfo->height; +//// qDebug() << "rotation: " << CrtcInfo->rotation; +//// qDebug() << "noutput: " << CrtcInfo->noutput; +//// qDebug() << "rotations: " << CrtcInfo->rotations; +//// qDebug() << "npossible: " << CrtcInfo->npossible; +//// XRRFreeCrtcInfo(CrtcInfo); +//// } + +//// // OUTPUTS +//// for (int nOut = 0; nOut < screenResources->noutput; ++nOut) +//// { +//// XRROutputInfo *OutputInfo = XRRGetOutputInfo (display, screenResources, screenResources->outputs[nOut]); +////// if (OutputInfo->connection == RR_Connected) { +//// qDebug() << "\n--- Output " << nOut; +//// qDebug() << "name " << OutputInfo->name; +//// qDebug() << "mm_width " << OutputInfo->mm_width; +//// qDebug() << "mm_height " << OutputInfo->mm_height; +//// qDebug() << "ncrtc " << OutputInfo->ncrtc; +//// qDebug() << "nclone " << OutputInfo->nclone; +//// qDebug() << "nmode " << OutputInfo->nmode; +//// qDebug() << "npreferred " << OutputInfo->npreferred; + +//// for (int j = 0; j < OutputInfo->nmode; j++) +//// { +//// qDebug() << "mode" << j << ": " << OutputInfo->modes[j]; +//// } +////// } +//// XRRFreeOutputInfo (OutputInfo); +//// } +/////////////////////////////////////////////////////////////////////////////////// diff --git a/src/x.h b/src/x.h new file mode 100644 index 0000000..4e2265e --- /dev/null +++ b/src/x.h @@ -0,0 +1,281 @@ +#ifndef XRANDR_H +#define XRANDR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace X +{ + class Mode; + class Output; + class Crtc; + + + typedef QSet ModeSet; + typedef QSet CrtcSet; + typedef QSet OutputSet; + + typedef QList ModeList; + typedef QList CrtcList; + typedef QList OutputList; + + + + /////////////////////////////////////////////////////////////////////////// + + + class Screen + { + friend class Crtc; + friend class Output; + + public: + + typedef QMap ModeMap; + typedef QMap CrtcMap; + typedef QMap OutputMap; + + int applyChanges(); + void revertChanges(); + + // Getters + inline const Display* display() const {return _display;} + inline const XRRScreenResources* screenResources() const {return _screenResources;} + inline const ModeMap& getModeMap() const {return _modeMap;} + inline const OutputMap& getOutputMap() const {return _outputMap;} + inline const OutputList& getConnectedOutputList() const {return _connectedOutputList;} + + // Singleton + inline static Screen* inst() { + if (_instance == 0) _instance = new Screen(); + return _instance; + } + + private: + Screen(); + ~Screen(); + + static Screen * _instance; + Display* _display; + XRRScreenResources* _screenResources; + ModeMap _modeMap; + CrtcMap _crtcMap; + OutputMap _outputMap; + + OutputList _connectedOutputList; + }; + + /////////////////////////////////////////////////////////////////////////// + + + struct XElement + { + XElement(XID = 0); + XID _id; + bool _validity; + inline XID getID() const {return _id;} + inline XID isValid() const {return _validity;} + }; + + + /////////////////////////////////////////////////////////////////////////// + + + struct Mode : public XElement + { + Mode(XRRModeInfo* = NULL); + + // Xlib internal stuff + QSize _resolution; + unsigned long _dotClock; + unsigned int _hSyncStart; + unsigned int _hSyncEnd; + unsigned int _hTotal; + unsigned int _hSkew; + unsigned int _vSyncStart; + unsigned int _vSyncEnd; + unsigned int _vTotal; + QString _name; + XRRModeFlags _modeFlags; + }; + + + /////////////////////////////////////////////////////////////////////////// + + + class Output : public XElement + { + friend int Screen::applyChanges(); + friend void Screen::revertChanges(); + + typedef enum _State { + Connected = RR_Connected, + Disconnected = RR_Disconnected, + Unknown = RR_UnknownConnection + } State; + + public: + + Output(XID, Screen*); + + /** Public interface to modify output settings. + * This function is the only interface to the outside, which is able to + * change something in this object. + * @param active Indicates wheter the output shall be on or off. + * @param mode The mode wich is used for the output. + * @param position The position of the topleft corner on the screen. + * @return 0 if the config passed teh sanity checks. + */ + int changeConfiguration(bool active, XID mode, QPoint position); + + inline QString getName() const {return _name;} + inline ModeSet getModeSet() const {return _modes;} + inline RRMode getPreferred() const {return _preferred;} + inline bool isActive() const {return !_crtcs.isEmpty();} + inline bool isConnected() const {return _connection == Connected;} + inline bool isProjector() const {return _isProjector;} + inline bool hasReliableEDID() const {return _hasReliableEDID;} + + + private: + + Screen *_parent; + + // Indicates when the configuration was last set. + Time _timestamp; + + // The current source CRTC for video data, or Disabled if the + // output is not connected to any CRTC. + RRCrtc _crtc; + + // UTF-8 encoded string designed to be presented to the + // user to indicate which output this is. E.g. "S-Video" or "DVI". + QString _name; + + // 'widthInMillimeters' and 'heightInMillimeters' report the physical + // size of the displayed area. If unknown, or not really fixed (e.g., + // for a projector), these values are both zero. + QSize _metricDimension; + + // Indicates whether the hardware was able to detect a + // device connected to this output. If the hardware cannot determine + // whether something is connected, it will set this to + // UnknownConnection. + State _connection; + +// // Contains the resulting subpixel order of the +// // connected device to allow correct subpixel rendering. +// SubpixelOrder _subpixel_order; + + // The list of CRTCs that this output may be connected to. + // Attempting to connect this output to a different CRTC results in a + // Match error. + CrtcList _crtcs; + + // The list of outputs which may be simultaneously + // connected to the same CRTC along with this output. Attempting to + // connect this output with an output not in this list + // results in a Match error. + OutputList _clones; + + // The list of modes supported by this output. Attempting to + // connect this output to a CRTC not using one of these modes results + // in a Match error. + ModeSet _modes; + + // The first 'num-preferred' modes in 'modes' are preferred by the + // monitor in some way; for fixed-pixel devices, this would generally + // indicate which modes match the resolution of the output device. + RRMode _preferred; + + // Indicates wheter this is a beamer or not. + bool _isProjector; + + // Indicates wheter the output received reliable data over the DDC. + // The Display Data Channel, or DDC, is a collection of protocols for + // digital communication between a computer display and a graphics + // adapter that enable the display to communicate its supported display + // modes to the adapter and that enable the computer host to adjust + // monitor parameters, such as brightness and contrast. + // Extended display identification data (EDID) is a data structure + // provided by a digital display to describe its capabilities to a + // video source. + bool _hasReliableEDID; + }; + + + /////////////////////////////////////////////////////////////////////////// + + + class Crtc : public XElement + { + friend int Screen::applyChanges(); + friend void Screen::revertChanges(); + friend int Output::changeConfiguration(bool active, XID mode, QPoint position); + //friend int Output::changeConfiguration(bool active, XID mode, QPoint position); + + public: + + Crtc(XID, Screen*); + + // Getter + inline const OutputList & getConnectedOutputs( ) { return _outputs; } + inline const QRect getRect() { return _crtcRect; } + + // Setter + + + // Applies the changes made to this crtc +// int applyChanges(); +// void disable(); +// void connect(const Output *, Mode); + + private: + + Screen *_parent; + + // Indicates when the configuration was last set. + Time _timestamp; + + // 'x' and 'y' indicate the position of this CRTC within the screen + // region. They will be set to 0 when the CRTC is disabled. + // 'width' and 'height' indicate the size of the area within the screen + // presented by this CRTC. This may be different than the size of the + // mode due to rotation, the projective transform, and the Border + // property described below. + // They will be set to 0 when the CRTC is disabled. + QRect _crtcRect; + + // Indicates which mode is active, or None indicating that the + // CRTC has been disabled and is not displaying the screen contents. + RRMode _mode; + + // The list of outputs currently connected to this CRTC, + // is empty when the CRTC is disabled. + OutputList _outputs; + + // Lists all of the outputs which may be connected to this CRTC. + OutputList _possible; + + // The active rotation. Set to Rotate_0 when the CRTC is disabled. + Rotation _rotation; + // enum Rotation { + // Normal = RR_Rotate_0, + // Left = RR_Rotate_270, + // Right = RR_Rotate_90, + // UpsideDown = RR_Rotate_180 + // }; + + // contains the set of rotations and reflections supported by the CRTC + Rotation _rotations; + }; +} + +#endif // XRANDR_H -- cgit v1.2.3-55-g7522