diff options
Diffstat (limited to 'kmilo/thinkpad')
-rw-r--r-- | kmilo/thinkpad/Makefile.am | 36 | ||||
-rw-r--r-- | kmilo/thinkpad/README | 61 | ||||
-rw-r--r-- | kmilo/thinkpad/kcmthinkpad/Makefile.am | 15 | ||||
-rw-r--r-- | kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui | 307 | ||||
-rw-r--r-- | kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h | 36 | ||||
-rw-r--r-- | kmilo/thinkpad/kcmthinkpad/main.cpp | 189 | ||||
-rw-r--r-- | kmilo/thinkpad/kcmthinkpad/main.h | 49 | ||||
-rw-r--r-- | kmilo/thinkpad/kcmthinkpad/thinkpad.desktop | 145 | ||||
-rw-r--r-- | kmilo/thinkpad/kmilo_thinkpad.desktop | 101 | ||||
-rw-r--r-- | kmilo/thinkpad/thinkpad.cpp | 556 | ||||
-rw-r--r-- | kmilo/thinkpad/thinkpad.h | 208 |
11 files changed, 1703 insertions, 0 deletions
diff --git a/kmilo/thinkpad/Makefile.am b/kmilo/thinkpad/Makefile.am new file mode 100644 index 0000000..e82c26b --- /dev/null +++ b/kmilo/thinkpad/Makefile.am @@ -0,0 +1,36 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos <staikos@kde.org> + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library 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 +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +SUBDIRS = . kcmthinkpad + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_thinkpad.la + +kmilo_thinkpad_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_thinkpad_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) +kmilo_thinkpad_la_SOURCES = thinkpad.cpp +METASOURCES = AUTO + +noinst_HEADERS = thinkpad.h + +services_DATA = kmilo_thinkpad.desktop +servicesdir = $(kde_servicesdir)/kmilo + +messages: + $(XGETTEXT) $(kmilo_thinkpad_la_SOURCES) -o $(podir)/kmilo_thinkpad.pot diff --git a/kmilo/thinkpad/README b/kmilo/thinkpad/README new file mode 100644 index 0000000..56b5da0 --- /dev/null +++ b/kmilo/thinkpad/README @@ -0,0 +1,61 @@ +Thinkpad Buttons KMilo Plugin + +Jonathan Riddell jr@jriddell.org, January 2004 + +A port of tpb ( http://www.nongnu.org/tpb/ ) to KMilo. + +KMilo is a service for kded, the KDE daemon. KMilo is new to KDE 3.2. +It allows plugins which interact with the special buttons found on +some keyboards and laptops. + +This KMilo plugin reads the nvram used in IBM Thinkpads. You need the +Linux nvram module ('insmod nvram') and to create a device node +('mknod /dev/nvram c 10 144'). + +Thinkpad R30/R31 models do not have a hardware volume control and so +require software volume control. Other models need software volume +control only if you want a volume change step different from the +builtin value (14). This required write access to nvram ('chmod 666 +/dev/nvram') and could potentially damage the machine. + +A KControl Centre module is included to configure the values including +whether this service is run or not (by default it is not). + +INSTALL: + +Download kdeutils source for kde 3.2 or newer. Then compile as +usual starting from the kdeutils directory: + + make -f Makefile.cvs + ./configure + cd kmilo + make + sudo make install + +Restarting kded is probably needed: + + kdekillall kded + kded + +HISTORY: + +05 January 2004, Initial release, most things working + +21 January 2004, Bug fix, stop it crashing if starting without kmix + runningdisplay rounded min and max volume levels, pda icon for + KControl module + +24 January 2004, Stopped it start kmix on kded startup even when set not to run + +28 January 2004, Added to KDE CVS + +TODO: + + - Need a better icon for the KControl module + - Test on machines other than my R31, which only has volume, + brightness buttons, light and 'Thinkpad' buttons + - Add options for the 'Thinkpad' and other action buttons to do something (e.g. bring up Konqueror) + For this sort of thing we really want integration with KHotKeys but I'm not sure how + + + diff --git a/kmilo/thinkpad/kcmthinkpad/Makefile.am b/kmilo/thinkpad/kcmthinkpad/Makefile.am new file mode 100644 index 0000000..4e70c40 --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/Makefile.am @@ -0,0 +1,15 @@ +kde_module_LTLIBRARIES = kcm_thinkpad.la + +kcm_thinkpad_la_SOURCES = kcmthinkpad_general.ui main.cpp + +kcm_thinkpad_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kcm_thinkpad_la_LIBADD = $(LIB_KIO) + +INCLUDES= $(all_includes) -DKDE_BINDIR="\"$(bindir)\"" + +kcm_thinkpad_la_METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcmthinkpad.pot + +xdg_apps_DATA = thinkpad.desktop diff --git a/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui b/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui new file mode 100644 index 0000000..771b7bf --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui @@ -0,0 +1,307 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KCMThinkpadGeneral</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KCMThinkpadGeneral</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>559</width> + <height>548</height> + </rect> + </property> + <property name="caption"> + <string>KVaio: General Options</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>tlOff</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>Could not read /dev/nvram. If you have an IBM Thinkpad load the nvram Linux module <em>insmod nvram</em> and create the node <em>mknod /dev/nvram c 10 144</em> then make the device readable <em>chmod 664 /dev/nvram</em> or writable <em>chmod 666 /dev/nvram</em>.<p> nvram must be writable for software volume control required for R30/R31 models and for using a custom volume change step.</string> + </property> + </widget> + <widget class="QButtonGroup" row="1" column="0"> + <property name="name"> + <cstring>bgGeneral</cstring> + </property> + <property name="title"> + <string>Thinkpad Button Options</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>mCbRun</cstring> + </property> + <property name="text"> + <string>Run Thinkpad Buttons KMilo plugin</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>mCbSoftwareVolume</cstring> + </property> + <property name="text"> + <string>Change volume in software (required by R30/R31)</string> + </property> + </widget> + <widget class="QLayoutWidget" row="2" column="0"> + <property name="name"> + <cstring>layout27</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel2_5</cstring> + </property> + <property name="text"> + <string>Command for Mail button:</string> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>textLabel2_6</cstring> + </property> + <property name="text"> + <string>Command for FN-Zoom button:</string> + </property> + </widget> + <widget class="KURLRequester" row="2" column="1"> + <property name="name"> + <cstring>commandExecHome</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel2_4</cstring> + </property> + <property name="text"> + <string>Command for Search button:</string> + </property> + </widget> + <widget class="KURLRequester" row="1" column="1"> + <property name="name"> + <cstring>commandExec</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>volumeStepLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>Volume step (out of 100):</string> + </property> + </widget> + <widget class="KURLRequester" row="5" column="1"> + <property name="name"> + <cstring>commandExecZoom</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel2_3</cstring> + </property> + <property name="text"> + <string>Command for Home button:</string> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>mSpinboxVolumeStep</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxValue"> + <number>30</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <widget class="KURLRequester" row="3" column="1"> + <property name="name"> + <cstring>commandExecSearch</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Command for Thinkpad button:</string> + </property> + </widget> + <widget class="KURLRequester" row="4" column="1"> + <property name="name"> + <cstring>commandExecMail</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>mCbRun</sender> + <signal>toggled(bool)</signal> + <receiver>KCMThinkpadGeneral</receiver> + <slot>slotChanged()</slot> + </connection> + <connection> + <sender>mCbSoftwareVolume</sender> + <signal>toggled(bool)</signal> + <receiver>KCMThinkpadGeneral</receiver> + <slot>slotChanged()</slot> + </connection> + <connection> + <sender>mSpinboxVolumeStep</sender> + <signal>valueChanged(int)</signal> + <receiver>KCMThinkpadGeneral</receiver> + <slot>slotChanged()</slot> + </connection> + <connection> + <sender>commandExec</sender> + <signal>textChanged(const QString&)</signal> + <receiver>KCMThinkpadGeneral</receiver> + <slot>slotChanged()</slot> + </connection> + <connection> + <sender>commandExecHome</sender> + <signal>textChanged(const QString&)</signal> + <receiver>KCMThinkpadGeneral</receiver> + <slot>slotChanged()</slot> + </connection> + <connection> + <sender>commandExecMail</sender> + <signal>textChanged(const QString&)</signal> + <receiver>KCMThinkpadGeneral</receiver> + <slot>slotChanged()</slot> + </connection> + <connection> + <sender>commandExecSearch</sender> + <signal>textChanged(const QString&)</signal> + <receiver>KCMThinkpadGeneral</receiver> + <slot>slotChanged()</slot> + </connection> + <connection> + <sender>commandExecZoom</sender> + <signal>textChanged(const QString&)</signal> + <receiver>KCMThinkpadGeneral</receiver> + <slot>slotChanged()</slot> + </connection> +</connections> +<tabstops> + <tabstop>mCbRun</tabstop> + <tabstop>mCbSoftwareVolume</tabstop> + <tabstop>mSpinboxVolumeStep</tabstop> + <tabstop>commandExec</tabstop> + <tabstop>commandExecHome</tabstop> + <tabstop>commandExecSearch</tabstop> + <tabstop>commandExecMail</tabstop> +</tabstops> +<includes> + <include location="local" impldecl="in implementation">kcmthinkpad_general.ui.h</include> +</includes> +<signals> + <signal>changed();</signal> +</signals> +<slots> + <slot>slotChanged()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h b/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h new file mode 100644 index 0000000..6ccc675 --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h @@ -0,0 +1,36 @@ +/* + * kcmthinkpad_general.uih + * + * Copyright (C) 2004 Jonathan Riddell <jr@jriddell.org> + * + * 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 2 of the License, 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ +#include <kdialog.h> + +void KCMThinkpadGeneral::slotChanged() { + emit(changed()); +} + + + diff --git a/kmilo/thinkpad/kcmthinkpad/main.cpp b/kmilo/thinkpad/kcmthinkpad/main.cpp new file mode 100644 index 0000000..1b8b4bd --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/main.cpp @@ -0,0 +1,189 @@ +/* + * main.cpp + * + * Copyright (C) 2004 Jonathan Riddell <jr@jriddell.org> + * + * Based on kcm_kvaio + * Copyright (C) 2003 Mirko Boehm (mirko@kde.org) + * + * 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 2 of the License, 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <qlabel.h> +#include <qlayout.h> +#include <qcheckbox.h> +#include <qspinbox.h> +#include <qfile.h> +#include <qbuttongroup.h> + +#include <dcopclient.h> +#include <kgenericfactory.h> +#include <kaboutdata.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kurlrequester.h> +#include <kcmodule.h> + +#ifdef Q_OS_FREEBSD +#include <sys/types.h> +#include <sys/sysctl.h> +#endif + +#include "kcmthinkpad_general.h" + +#include <dcopclient.h> + +#include "main.h" +#include "main.moc" + +typedef KGenericFactory<KCMThinkpadModule, QWidget> KCMThinkpadModuleFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_thinkpad, KCMThinkpadModuleFactory("kcmthinkpad")) + +#define CONFIG_FILE "kmilodrc" + +KCMThinkpadModule::KCMThinkpadModule(QWidget* parent, const char* name, const QStringList&) + : KCModule(KCMThinkpadModuleFactory::instance(), parent, name) { + KAboutData* about = + new KAboutData(I18N_NOOP("kcmthinkpad"), + I18N_NOOP("KDE Control Module for IBM Thinkpad " + "Laptop Hardware"), + 0, 0, KAboutData::License_GPL, + "(c) 2004 Jonathan Riddell"); + + about->addAuthor("Jonathan Riddell", + I18N_NOOP("Original author"), + "jr@jriddell.org"); + setAboutData( about ); + + QVBoxLayout* layout = new QVBoxLayout(this); + m_KCMThinkpadGeneral = new KCMThinkpadGeneral(this); + layout->addWidget( m_KCMThinkpadGeneral ); + layout->addStretch(); + + load(); + + //try and open /dev/nvram + m_nvramReadable = false; + m_nvramWriteable = false; + +#ifdef Q_OS_FREEBSD + // Look if the sysctl tree of acpi_ibm is in place + u_int n = 0; + size_t len = sizeof(n); + if (m_nvramReadable = ( sysctlbyname("dev.acpi_ibm.0.volume", &n, &len, NULL, 0) != -1 )) + m_nvramWriteable = ( sysctlbyname("dev.acpi_ibm.0.volume", NULL, NULL, &n, len) != -1 ); + + if (!m_nvramReadable) { + setButtons(buttons() & ~Default); + m_KCMThinkpadGeneral->bgGeneral->setEnabled(false); + m_KCMThinkpadGeneral->tlOff->setText(i18n("In order to use the Thinkpad Buttons KMilo Plugin, " + "you have to load the acpi_ibm(4) driver.")); + } else if (!m_nvramWriteable) { + m_KCMThinkpadGeneral->tlOff->setText(i18n("Could not write to dev.acpi_ibm.0.volume. " + "Using software volume, required for " + "R30/R31 models, or using a custom volume " + "change step is disabled.")); +#else + QFile nvramFile(m_nvramFile); + if ( nvramFile.open(IO_ReadOnly) ) { + m_nvramReadable = true; + nvramFile.close(); + } + if ( nvramFile.open(IO_WriteOnly) ) { + m_nvramWriteable = true; + nvramFile.close(); + } + + if (!m_nvramReadable) { + setButtons(buttons() & ~Default); + m_KCMThinkpadGeneral->bgGeneral->setEnabled(false); + } else if (!m_nvramWriteable) { + m_KCMThinkpadGeneral->tlOff->setText(i18n("Could not write to %1. " + "To use the software volume, required for " + "R30/R31 models and to use a custom volume " + "change step, set the nvram device to world " + "writeable: <em>chmod 666 " + "/dev/nvram</em>").arg(m_nvramFile)); +#endif + } else { + m_KCMThinkpadGeneral->tlOff->setText(i18n("Thinkpad Buttons KMilo Plugin Ready For Configuration")); + } + + connect( m_KCMThinkpadGeneral, SIGNAL(changed()), SLOT(changed())); + +} + +void KCMThinkpadModule::save() { + if (!m_nvramReadable) { + return; + } + DCOPClient client; + + KConfig config(CONFIG_FILE); + config.setGroup("thinkpad"); + + config.writeEntry("run", m_KCMThinkpadGeneral->mCbRun->isChecked()); + config.writeEntry("softwareVolume", m_KCMThinkpadGeneral->mCbSoftwareVolume->isChecked()); + config.writeEntry("volumeStep", m_KCMThinkpadGeneral->mSpinboxVolumeStep->value()); + config.writeEntry("buttonThinkpad", m_KCMThinkpadGeneral->commandExec->url()); + config.writeEntry("buttonHome", m_KCMThinkpadGeneral->commandExecHome->url()); + config.writeEntry("buttonSearch", m_KCMThinkpadGeneral->commandExecSearch->url()); + config.writeEntry("buttonMail", m_KCMThinkpadGeneral->commandExecMail->url()); + config.writeEntry("buttonZoom", m_KCMThinkpadGeneral->commandExecZoom->url()); + config.sync(); + + if (client.attach()) { + QByteArray data, replyData; + QCString replyType; + + if (!client.call("kded", "kmilod", "reconfigure()", data, replyType, replyData)) { + kdDebug() << "KCMThinkpad::showTextMsg: " + << "there was an error using DCOP on kmilod::reconfigure()." << endl; + } + } else { + kdDebug() << "KCMThinkpadModule: cannot attach to DCOP server, " + << "no automatic config update." << endl; + } +} + +void KCMThinkpadModule::load() { + load( false ); +} + +void KCMThinkpadModule::load(bool useDefaults) { + KConfig config(CONFIG_FILE); + + config.setReadDefaults( useDefaults ); + + config.setGroup("thinkpad"); + + m_KCMThinkpadGeneral->mCbRun->setChecked(config.readBoolEntry("run", false)); + m_KCMThinkpadGeneral->mCbSoftwareVolume->setChecked(config.readBoolEntry("softwareVolume", true)); + m_KCMThinkpadGeneral->mSpinboxVolumeStep->setValue(config.readNumEntry("volumeStep", 14)); + m_KCMThinkpadGeneral->commandExec->setURL(config.readEntry("buttonThinkpad", KDE_BINDIR "/konsole")); + m_KCMThinkpadGeneral->commandExecHome->setURL(config.readEntry("buttonHome", KDE_BINDIR "/konqueror")); + m_KCMThinkpadGeneral->commandExecSearch->setURL(config.readEntry("buttonSearch", KDE_BINDIR "/kfind")); + m_KCMThinkpadGeneral->commandExecMail->setURL(config.readEntry("buttonMail", KDE_BINDIR "/kmail")); + m_KCMThinkpadGeneral->commandExecZoom->setURL(config.readEntry("buttonZoom", KDE_BINDIR "/ksnapshot")); + m_nvramFile = config.readEntry("nvram", "/dev/nvram"); + + emit changed( useDefaults ); +} + +void KCMThinkpadModule::defaults() { + load( true ); +} + diff --git a/kmilo/thinkpad/kcmthinkpad/main.h b/kmilo/thinkpad/kcmthinkpad/main.h new file mode 100644 index 0000000..53534ed --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/main.h @@ -0,0 +1,49 @@ +/* + * main.h + * + * Copyright (C) 2004 Jonathan Riddell <jr@jriddell.org> + * + * Based on kcm_kvaio + * Copyright (C) 2003 Mirko Boehm (mirko@kde.org) + * + * 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 2 of the License, 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef KCMTHINKPAD_MAIN_H +#define KCMTHINKPAD_MAIN_H + +#include <kcmodule.h> + +class KCMThinkPadGeneral; + +class KCMThinkpadModule : public KCModule { + Q_OBJECT + + public: + KCMThinkpadModule(QWidget* parent, const char* name, const QStringList&); + + void save(); + void load(); + void load(bool useDefaults); + void defaults(); + private: + KCMThinkpadGeneral* m_KCMThinkpadGeneral; + QString m_nvramFile; + bool m_nvramReadable; + bool m_nvramWriteable; +}; + +#endif diff --git a/kmilo/thinkpad/kcmthinkpad/thinkpad.desktop b/kmilo/thinkpad/kcmthinkpad/thinkpad.desktop new file mode 100644 index 0000000..720a69f --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/thinkpad.desktop @@ -0,0 +1,145 @@ +[Desktop Entry] +Type=Application +Exec=kcmshell thinkpad +Icon=laptop +DocPath=kcontrol/thinkpad/index.html + +X-KDE-Library=thinkpad +X-KDE-ParentApp=kcontrol + +Name=IBM Thinkpad Laptop +Name[ar]=حاسوب IBM Thinkpad المحمول +Name[bg]=Лаптоп IBM Thinkpad +Name[br]=Hezoug IBM Thinkpad +Name[bs]=IBM Thinkpad laptop +Name[ca]=Portàtil IBM Thinkpad +Name[cy]=Gliniadur IBM Thinkpad +Name[da]=IBM Thinkpad bærbar +Name[de]=IBM Thinkpad Notebook +Name[el]=Φορητός υπολογιστής IBM Thinkpad +Name[es]=Portátil IBM Thinkpad +Name[et]=IBM Thinkpadi sülearvuti +Name[eu]=IBM Thinkpad Magalekoa +Name[fa]=IBM Thinkpad رایانۀ کیفی +Name[fi]=IBM Thinkpad -kannettava +Name[fr]=Portable Thinkpad d'IBM +Name[ga]=Ríomhaire Glúine IBM Thinkpad +Name[he]=מחשב ברכיים מסוג IBM Thinkpad +Name[hu]=IBM Thinkpad noteszgép +Name[is]=IBM ferðavél +Name[it]=Portatile IBM Thinkpad +Name[ja]=IBM シンクパッド ラップトップ +Name[kk]=IBM Thinkpad ноутбугі +Name[km]=កុំព្យូទ័រយួរដៃ IBM Thinkpad +Name[mk]=Лаптоп IBM Thinkpad +Name[nb]=IBM Thinkpad Bærbar PC +Name[nds]=IBM Thinkpad-Klappreekner +Name[ne]=IBM थिङ्कप्याड ल्यापटप +Name[nn]=IBM Thinkpad-bærbar +Name[pa]=IBM Thinkpad ਲੈਪਟਾਪ +Name[pl]=Laptop IBM Thinkpad +Name[pt]=Portátil IBM Thinkpad +Name[pt_BR]=Laptop IBM Thinkpad +Name[ro]=Laptop IBM Thinkpad +Name[ru]=Ноутбук IBM Thinkpad +Name[sk]=IBM Thinkpad +Name[sl]=Prenosnik IBM Thinkpad +Name[sr]=IBM-ов Thinkpad лаптоп +Name[sr@Latn]=IBM-ov Thinkpad laptop +Name[sv]=IBM Thinkpad bärbar dator +Name[ta]=ஐபிஎம் திங்க்பாட் மடிக்கணினி +Name[tr]=IBM Thinkpad Dizüstü +Name[uk]=Лептоп IBM Thinkpad +Name[uz]=IBM Thinkpad laptopi +Name[uz@cyrillic]=IBM Thinkpad лаптопи +Name[zh_CN]=ThinkPad 便携电脑 +Name[zh_TW]=IBM Thinkpad 筆記型電腦 +Comment=Configure the KDE Interface to the IBM Thinkpad Special Controls +Comment[ar]=إعداد واجهة كدى لمُتَحكّمات IBM Thinkpad الخاصة +Comment[bg]=Настройване на IBM Thinkpad +Comment[bs]=Podesite KDE interfejs za IBM Thinkpad posebne kontrole +Comment[ca]=Configura la interfície entre KDE i els controls especials de IBM Thinkpad +Comment[cs]=Nastavení KDE rozhraní ovládání notebooků IBM Thinkpad +Comment[cy]=Ffurfweddu'r Rhyngwyneb KDE i'r Rheolau Arbennig IBM Thinkpad +Comment[da]=Indstil KDE's grænseflade til IBM Thinkpads specielle kontroller +Comment[de]=KDE Schnittstelle zu den Sonderfunktionen von IBM Thinkpads einrichten +Comment[el]=Ρυθμίστε το περιβάλλον χρήσης του KDE για τα ειδικά χειριστήρια του IBM Thinkpad +Comment[es]=Configurar la interfaz de KDE para los controles especiales del IBM Thinkpad +Comment[et]=KDE liides IBM Thinkpadi eriklahvide seadistamiseks +Comment[eu]=IBM Thinkpad-en Aginte Berezientzako KDE Interfazea Konfiguratu +Comment[fa]=پیکربندی واسط KDEدر کلیدهای مهار ویژۀ IBM Thinkpad +Comment[fi]=Aseta KDE:n liityntää IBM Thinkpadin ohjelmoitavalle keskeytysajurille +Comment[fr]=Configuration de l'interface KDE pour le paramètrage des Thinkpad d'IBM +Comment[ga]=Cumraigh comhéadan KDE do Rialtáin Speisialta IBM Thinkpad +Comment[he]=הגדר את המנשק של KDE להתאים למקשים המיוחדים של IBM Thinkpad +Comment[hu]=Az IBM Thinkpad noteszgépek speciális kezelőelemeinek beállítása +Comment[is]=Stilla viðmót KDE á IBM Thinkpad stýringuna +Comment[it]=Configura l'interfaccia KDE ai controlli speciali dei Thinkpad IBM +Comment[ja]=IBM シンクパッド特殊コントロールの KDE インターフェースを設定 +Comment[ka]= KDE ინტერფეისის IBM Thinkpad-ის სპეციალური კონტროლებისთვის კონფიგურაცია +Comment[kk]=IBM Thinkpad арнаулы тетіктерінің KDE интерфейсін баптау +Comment[km]=កំណត់រចនាសម្ព័ន្ធចំណុចប្រទាក់ KDE ទៅការត្រួតពិនិត្យ IBM Thinkpad ពិសេស +Comment[lt]=IBM Thinkpad ypatingiems valdymo moduliams KDE sąsaja +Comment[mk]=Го конфигурира интерфејсот на KDE за спец. контроли на IBM Thinkpad +Comment[nb]=Sett opp KDE-grensesnitt til IBM Thinkpad spesial kontroller +Comment[nds]=KDE-Koppelsteedinstellen för de IBM Thinkpad-Sünnerfunkschonenkuntrull +Comment[ne]=IBM थिङ्कप्याड विशेष नियन्त्रणका लागि KDE इन्टरफेस कन्फिगर गर्नुहोस् +Comment[nl]=Voor het instellen van KDE's communicatie met de IBM Thinkpad Special Controls +Comment[nn]=Set opp KDE-grensesnittet til spesialfunksjonar på IBM Thinkpad +Comment[pa]=IBM ਥਿੰਕਪੈਂਡ ਕੰਟਰੋਲਾਂ ਲਈ KDE ਇੰਟਰਫੇਸ ਸੰਰਚਨਾ +Comment[pl]=Konfiguracja specjalnych funkcji IBM Thinkpad +Comment[pt]=Configurar a Interface para o KDE dos Comandos Especiais do IBM Thinkpad +Comment[pt_BR]=Configura a Interface do KDE para os Controles Especiais do IBM Thinkpad +Comment[ro]=Configurează interfaţa KDE către laptop-uri IBM Thinkpad +Comment[ru]=Настройка интерфейса KDE для специальных клавиш ноутбука IBM Thinkpad +Comment[sk]=Nastavenie rozhrania KDE k špeciálnym ovládacím prvkom notebooku IBM Thinkpad +Comment[sl]=Nastavite vmesnik KDE za posebne kontrole IBM Thinkpada +Comment[sr]=Подесите KDE-ов интерфејс за посебне контроле IBM-ових Thinkpad-ова +Comment[sr@Latn]=Podesite KDE-ov interfejs za posebne kontrole IBM-ovih Thinkpad-ova +Comment[sv]=Anpassa KDE:s gränssnitt till IBM Thinkpads specialstyrning +Comment[ta]=ஐபிஎம் திங்க்பேட் விசேஷ கட்டுப்பாட்டிற்கு கேடிஇ இடைமுகத்தை வடிவமை +Comment[tr]=KDE Arayüzünü Sony IBM Thinkpad Özel Denetimlerine Ayarla +Comment[uk]=Налаштування інтерфейсу KDE до спеціальних функцій IBM Thinkpad +Comment[zh_CN]=配置 KDE 界面使用 ThinkPad 特殊控制 +Comment[zh_TW]=設定 IBM Thinkpad 特殊控制的 KDE 介面 +Keywords=IBM, Thinkpad, brightness, mute, Jog Dial +Keywords[bs]=IBM, Thinkpad, brightness, mute, Jog Dial, svjetlost +Keywords[ca]=IBM, Thinkpad, brillantor, silenci, Jog Dial +Keywords[cs]=IBM,Thinkpad,jas,ztlumení,Jog Dial +Keywords[cy]=IBM,Thinkpad,gloywder, mud, Jog Dial +Keywords[da]=IBM. Thinkpad, lysstyrke, stum, Jog Dial +Keywords[de]=IBM, Thinkpad, Helligkeit, Abschalten, Jog Dial +Keywords[el]=IBM, Thinkpad, φωτεινότητα, κλείσιμο ήχου, Jog Dial +Keywords[es]=IBM, Thinkpad, brillo, mute, Jog Dial +Keywords[et]=IDM, Thinkpad, heledus, tumm, Jog Dial +Keywords[eu]=IBM, Thinkpad, distira, mutu, Jog Dial +Keywords[fa]=IBM، Thinkpad، روشنایی، بدون صدا، Jog Dial +Keywords[fi]=IBM, Thinkpad, kirkkaus, vaimenna, Jog Dial +Keywords[fr]=IBM, Thinkpad, luminosité, sourdine, mute, Jog Dial +Keywords[ga]=IBM, Thinkpad, gile, gan fuaim, Jog Dial +Keywords[hu]=IBM,Thinkpad,fényerő,elnémítás,tárcsagomb +Keywords[it]=IBM,Thinkpad,luminosità,muto,Jog Dial +Keywords[ja]=IBM, シンクパッド, 明るさ, ミュート, ジョグダイアル +Keywords[mk]=IBM, Thinkpad, brightness, mute, Jog Dial, осветленост, пригушување +Keywords[nb]=IBM, Thinkpad, lysstyrke, dempet, Jog Dial +Keywords[nds]=IBM, Thinkpad, Helligkeit, stumm, Jog Dial +Keywords[ne]=IBM, थिङ्कप्याड, चम्किलोपना, चुप लाग्नु, जोग डायल +Keywords[nl]=IBM, Thinkpad, brightness, mute, Jog Dial, Helderheid, dempen +Keywords[nn]=IBM,Thinkpad,lysstyrke,demping,snurrehjul +Keywords[pa]=IBM, Thinkpad, brightness, mute, Jog Dial, ਲੈਪਟਾਪ +Keywords[pl]=IBM, Thinkpad, jasność, wycisz, Jog Dial +Keywords[pt]=IBM, Thinkpad, brilho, sem som, Jog Dial +Keywords[pt_BR]=IBM,Thinkpad,brilho, mudo, Jog Dial +Keywords[ro]=IBM,Thinkpad,strălucire,fără sunet,jog dial +Keywords[ru]=IBM, Thinkpad, brightness, mute, Jog Dial, яркость, звук +Keywords[sk]=IBM, Thinkpad,jas,potichu +Keywords[sl]=IBM, Thinkpad, svetlost, tiho, Jog Dial +Keywords[sr]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, светлина +Keywords[sr@Latn]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, svetlina +Keywords[sv]=IBM, Thinkpad, ljusstyrka, tyst, rullhjul +Keywords[ta]=ஐபிஎம், திங்க்பேட்,ஒளித்தன்மை,ஓசையற்ற,ஜோக் டையல் +Keywords[tr]=IBM, Thinkpad, parlaklık, sessiz, gösterme itmesi +Keywords[uk]=IBM, Thinkpad, яскравість, вимкнення звуку, Jog Dial +Keywords[zh_CN]=IBM, Lenovo, Thinkpad, brightness, mute, Jog Dial,亮度,静音,联想,导航键 + +Categories=Qt;KDE;X-KDE-settings-system; diff --git a/kmilo/thinkpad/kmilo_thinkpad.desktop b/kmilo/thinkpad/kmilo_thinkpad.desktop new file mode 100644 index 0000000..1d957c4 --- /dev/null +++ b/kmilo/thinkpad/kmilo_thinkpad.desktop @@ -0,0 +1,101 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Thinkpad Plugin +Name[ar]=ملحق Thinkpad +Name[br]=Lugent Thinkpad +Name[bs]=Thinkpad dodatak +Name[ca]=Connector Thinkpad +Name[cs]=Thinkpad modul +Name[cy]=Ategyn Thinkpad +Name[de]=Thinkpad-Plugin +Name[el]=Πρόσθετο Thinkpad +Name[eo]=Thinkpad-kromaĵo +Name[es]=Extensión para Thinkpad +Name[et]=Thinkpadi plugin +Name[eu]=Thikpad Plugina +Name[fa]=Thinkpad وصلۀ +Name[fi]=Thinkpad-liitännäinen +Name[fr]=Module externe pour les Thinkpad +Name[ga]=Breiseán Thinkpad +Name[he]=תוסף ל-Thinkpad +Name[hu]=Thinkpad bővítőmodul +Name[is]=Thinkpad íforrit +Name[it]=Plugin Thinkpad +Name[ja]=シンクパッド プラグイン +Name[ka]=Thinkpad-ის მოდული +Name[kk]=Thinkpad модулі +Name[km]=កម្មវិធីជំនួយ Thinkpad Plugin +Name[lt]=Thinkpad priedas +Name[mk]=Приклучок за Thinkpad +Name[nb]=Thinkpad tilleggs program +Name[nds]=Thinkpad-Moduul +Name[ne]=थिङ्कप्याड प्लगइन +Name[nn]=Programtillegg for Thinkpad +Name[pa]=Thinkpad ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka Thinkpad +Name[pt]='Plugin' para Thinkpad +Name[pt_BR]=Plugin do Thinkpad +Name[ro]=Modul Thinkpad +Name[ru]=Модуль Thinkpad +Name[sk]=Modul pre Thinkpad +Name[sl]=Vstavek za Thinkpad +Name[sr]=Прикључак за Thinkpad +Name[sr@Latn]=Priključak za Thinkpad +Name[sv]=Thinkpad-insticksprogram +Name[ta]=திங்க்பேட் செருகி +Name[tr]=Thinkpad Eklentisi +Name[uk]=Втулок Thinkpad +Name[uz]=Thinkpad plagini +Name[uz@cyrillic]=Thinkpad плагини +Name[zh_CN]=Thinkpad 插件 +Name[zh_TW]=Thinkpad 外掛程式 +Comment=Enables support for special Thinkpad keys +Comment[ar]=تمكّن الدعم لمفاتيح Thinkpad الخاصة +Comment[bg]=Тази приставка позволява поддръжката на специалните клавиши на IBM Thinkpad +Comment[bs]=Omogućuje podršku za posebne tipke na Thinkpadu +Comment[ca]=Habilita el funcionament per a tecles especials de Thinkpad +Comment[cs]=Umožňuje podporu speciálních kláves Thinkpadu +Comment[cy]=Yn galluogi cynhaliaeth ar gyfer bysyll arbennig Thinkpad +Comment[da]=Aktiverer støtte for specielle Thinkpad taster +Comment[de]=Dieses Plugin aktiviert die Unterstützung für Sondertasten von Thinkpad-Tastaturen +Comment[el]=Ενεργοποιεί την υποστήριξη για ειδικά πλήκτρα του Thinkpad +Comment[es]=Activa el soporte de las teclas especiales del Thinkpad +Comment[et]=See plugin võimaldab kasutada Thinkpadi eriklahve. +Comment[eu]=Thinkpad-en tekla berezientzako euskarria gaitzen du +Comment[fa]=فعالسازی پشتیبانی برای کلیدهای ویژۀ Thinkpad . +Comment[fi]=Tämä liitännäinen mahdollistaa erikoisnäppäinten tuen IBM Thinkpad kannettaville tietokoneille. +Comment[fr]=Ce module active la gestion des touches spéciales des Thinkpad. +Comment[ga]=Tacaigh le heochracha speisialta Thinkpad +Comment[he]=מאפשר תמיכה במקשים מיוחדים של Thinkpad +Comment[hu]=Ez a bővítőmodul lehetővé teszi az IBM Thinkpad noteszgépek speciális billentyűinek használatát +Comment[is]=Virkjar stuðning fyrir sérhnappa Thinkpad véla +Comment[it]=Abilita il supporto per i tasti speciali Thinkpad +Comment[ja]=シンクパッドの特殊キーをサポートします +Comment[ka]=რთავს Thinkpad-ის სპეციალური კლავიშების მხარდაჭერას +Comment[kk]=Thinkpad-тың арнаулы пернелерін қолдауы +Comment[km]=បើកការគាំទ្រសម្រាប់គ្រាប់ចុច Thinkpad ពិសេស +Comment[lt]=įgalina ypatingų Thinkpad raktų paramą +Comment[mk]=Овозможува поддршка за спец. копчиња на Thinkpad +Comment[nb]=Dette programtillegget muliggjør støtte for spesielle taster på alle tastatur og bærbare maskiner +Comment[nds]=Maakt de Sünnertasten-Ünnerstütten för Thinkpads an +Comment[ne]=विशेष थिङ्कप्याड कुञ्जीका लागि समर्थन सक्षम पार्दछ +Comment[nl]=Activeert de ondersteuning voor spciale Thinkpad-toetsen +Comment[nn]=Dette programtillegget gjer det mogleg å bruka spesialtastar på Thinkpad +Comment[pl]=Włącza obsługę specjalnych klawiszy Thinkpada +Comment[pt]=Activa o suporte a teclas especiais do Thinkpad +Comment[pt_BR]=Habilita suporte para teclas especiais no Thinkpad +Comment[ro]=Activează suportul pentru tastele speciale Thinkpad +Comment[ru]=Этот модуль поддерживает специальные клавиши Thinkpad +Comment[sk]=Zapína podporu pre špeciálne klávesy notebookov Thinkpad +Comment[sl]=Omogoči podporo posebnim tipkam Thinkpada +Comment[sr]=Подршку за посебне Thinkpad-ове тастере +Comment[sr@Latn]=Podršku za posebne Thinkpad-ove tastere +Comment[sv]=Aktiverar stöd för speciella Thinkpad-tangenter +Comment[ta]=விசேஷ திங்க்பேட் விசைகளுக்கான ஆதரவை செயல்படுத்துகிறது +Comment[tr]=Özel Thinkpad tuşları için desteği etkinleştirir +Comment[uk]=Уможливлює підтримку спеціальних клавіш для Thinkpad. +Comment[zh_CN]=此插件启用各种键盘和便携电脑的特殊按键 +Comment[zh_TW]=開啟特殊 Thinkpad 按鍵支援 +X-KDE-Library=kmilo_thinkpad diff --git a/kmilo/thinkpad/thinkpad.cpp b/kmilo/thinkpad/thinkpad.cpp new file mode 100644 index 0000000..74770cf --- /dev/null +++ b/kmilo/thinkpad/thinkpad.cpp @@ -0,0 +1,556 @@ +/* + This file is part of the KDE project + + Copyright (c) 2004 Jonathan Riddell <jr@jriddell.org> + + Based on Demo kmilo service by George Staikos + Copyright (c) 2003 George Staikos <staikos@kde.org> + + And tpb by Markus Braun + Copyright (C) 2002,2003 Markus Braun <markus.braun@krawel.de> + + FreeBSD support by Markus Brueffer + Copyright (C) 2005 Markus Brueffer <markus@FreeBSD.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include <kgenericfactory.h> +#include <kconfig.h> +#include <krun.h> +#include <kurl.h> +#include "kmilointerface.h" + +#ifdef Q_OS_FREEBSD +#include <sys/sysctl.h> +#endif + +#include "thinkpad.h" + +namespace KMilo { + +ThinkPadMonitor::ThinkPadMonitor(QObject* parent, const char* name, const QStringList& args): Monitor(parent, name, args) { + m_progress = 0; + m_volume = 50; //set in retrieveVolume() +} + +ThinkPadMonitor::~ThinkPadMonitor() { +} + +bool ThinkPadMonitor::init() { + + KConfig config("kmilodrc"); + reconfigure(&config); + + if (m_run) { + clearStruct(thinkpad_state); + clearStruct(last_thinkpad_state); + if ( getNvramState(&thinkpad_state) == false ) { + return false; + } + + if (m_softwareVolume || m_volumeStep != defaultVolumeStep) { + kmixClient = new DCOPRef("kmix", "Mixer0"); + kmixWindow = new DCOPRef("kmix", "kmix-mainwindow#1"); + retrieveVolume(); + setNvramVolume(); + } + } + + return m_run; +} + +Monitor::DisplayType ThinkPadMonitor::poll() { + + // save last state and get new one + memcpy(&last_thinkpad_state, &thinkpad_state, sizeof(thinkpad_state_struct)); + getNvramState(&thinkpad_state); + + Monitor::DisplayType pollResult = None; + + // determine the state of the mute button + if (thinkpad_state.mute_toggle != last_thinkpad_state.mute_toggle || + (thinkpad_state.volume_toggle != last_thinkpad_state.volume_toggle + && last_thinkpad_state.mute_toggle == 1)) { + + showToggleMessage(i18n("Mute on"), i18n("Mute off"), thinkpad_state.mute_toggle == 1); + if (m_softwareVolume || m_volumeStep != defaultVolumeStep) { + kmixClient->send("setMasterMute", thinkpad_state.mute_toggle == 1); + } + } + + // determine the state of the Thinkpad button + if (thinkpad_state.thinkpad_toggle != last_thinkpad_state.thinkpad_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + _interface->displayText(i18n("Thinkpad Button Pressed")); + + KURL url(m_buttonThinkpad); + (void) new KRun(url, 0, true, true); + } + + // determine the state of ThinkLight + if (thinkpad_state.thinklight_toggle != last_thinkpad_state.thinklight_toggle) { + showToggleMessage(i18n("ThinkLight is on"), i18n("ThinkLight is off"), thinkpad_state.thinklight_toggle == 1); + } + + // determine the state of the volume buttons + if (thinkpad_state.volume_level != last_thinkpad_state.volume_level) { + + pollResult = Volume; + + if (m_volumeStep == defaultVolumeStep && m_softwareVolume == false) { + //no need to write to nvram or set volume in software + m_progress = thinkpad_state.volume_level * 100 / defaultVolumeStep; + } else { + if (thinkpad_state.volume_level > last_thinkpad_state.volume_level) { + m_progress = m_volume + m_volumeStep; + } else { + m_progress = m_volume - m_volumeStep; + } + setVolume(m_progress); + } + + } + + // determine the state of the brightness buttons + if (thinkpad_state.brightness_level != last_thinkpad_state.brightness_level) { + pollResult = Brightness; + m_progress = thinkpad_state.brightness_level * 100 / 7; + } + + // Buttons below here are untested because they do not exist on my R31 + + // determine the state of zoom + if (thinkpad_state.zoom_toggle != last_thinkpad_state.zoom_toggle) { + // showToggleMessage(i18n("Zoom is on"), i18n("Zoom is off"), thinkpad_state.zoom_toggle == 1); + + // Use as button since an Zooming is implemented + _interface->displayText(i18n("Zoom button pressed")); + + KURL url(m_buttonZoom); + (void) new KRun(url, 0, true, true); + } + + // determine the state of the home button + if (thinkpad_state.home_toggle != last_thinkpad_state.home_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + _interface->displayText(i18n("Home button pressed")); + KURL url(m_buttonHome); + (void) new KRun(url, 0, true, true); + } + + // determine the state of the search button + if (thinkpad_state.search_toggle != last_thinkpad_state.search_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + _interface->displayText(i18n("Search button pressed")); + KURL url(m_buttonSearch); + (void) new KRun(url, 0, true, true); + } + + // determine the state of the mail button + if (thinkpad_state.mail_toggle != last_thinkpad_state.mail_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + _interface->displayText(i18n("Mail button pressed")); + KURL url(m_buttonMail); + (void) new KRun(url, 0, true, true); + } + + // determine the state of display + if (thinkpad_state.display_toggle != last_thinkpad_state.display_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + + // Some thinkpads have no hardware support to switch lcd/crt. They also + // don't reflect the current state in thinkpad_state.display_state. So, if + // thinkpad_state.display_toggle changes, but thinkpad_state.display_state does + // not change, simulate the display state. + + unsigned int display_state = 1; + if (thinkpad_state.display_state == last_thinkpad_state.display_state) { + display_state = display_state % 3 + 1; + } else { + display_state = thinkpad_state.display_state; + } + + switch (display_state & 0x03) { + case 0x1: + _interface->displayText(i18n("Display changed: LCD on, CRT off")); + break; + + case 0x2: + _interface->displayText(i18n("Display changed: LCD off, CRT on")); + break; + + case 0x3: + _interface->displayText(i18n("Display changed: LCD on, CRT on")); + break; + } + } + + // determine the state of hv expansion + if (thinkpad_state.expand_toggle != last_thinkpad_state.expand_toggle) { + showToggleMessage(i18n("HV Expansion is on"), i18n("HV Expansion is off"), (thinkpad_state.expand_toggle & 0x01) == 1); + } + + // determine power management mode AC + if (thinkpad_state.powermgt_ac != last_thinkpad_state.powermgt_ac) { + switch(thinkpad_state.powermgt_ac) { + case 0x4: + _interface->displayText(i18n("Power management mode AC changed: PM AC high")); + break; + + case 0x2: + _interface->displayText(i18n("Power management mode AC changed: PM AC auto")); + break; + + case 0x1: + _interface->displayText(i18n("Power management mode AC changed: PM AC manual")); + break; + + default: + _interface->displayText(i18n("Power management mode AC changed: PM AC unknown")); + break; + } + } + + // determine power management mode battery + if (thinkpad_state.powermgt_battery != last_thinkpad_state.powermgt_battery) { + switch(thinkpad_state.powermgt_battery) { + case 0x4: + _interface->displayText(i18n("Power management mode battery changed: PM battery high")); + break; + + case 0x2: + _interface->displayText(i18n("Power management mode battery changed: PM battery auto")); + break; + + case 0x1: + _interface->displayText(i18n("Power management mode battery changed: PM battery manual")); + break; + + default: + _interface->displayText(i18n("Power management mode battery changed: PM battery unknown")); + break; + } + } + + // determine the state of wireless lan + if (thinkpad_state.wireless_toggle != last_thinkpad_state.wireless_toggle) { + showToggleMessage(i18n("Wireless LAN is enabled"), i18n("Wireless LAN is disabled"), thinkpad_state.wireless_toggle == 1); + } + + // determine the state of bluetooth + if (thinkpad_state.bluetooth_toggle != last_thinkpad_state.bluetooth_toggle) { + showToggleMessage(i18n("Bluetooth is enabled"), i18n("Bluetooth is disabled"), thinkpad_state.bluetooth_toggle == 1); + } + + return pollResult; +} + + +int ThinkPadMonitor::progress() const { + return m_progress; +} + +QString ThinkPadMonitor::message() const { + //unused + //return i18n("yer maw!"); + return ""; +} + +bool ThinkPadMonitor::getNvramState(thinkpad_state_struct* thinkpad_state) { +#ifndef Q_OS_FREEBSD + int file; + unsigned char buffer[114]; + + // open nvram for reading + // must use open/close because seek is not supported by nvram + if ((file=open(m_nvramFile.latin1(), O_RDONLY|O_NONBLOCK)) == -1) { + kdError() << "Unable to open device: " << m_nvramFile << endl; + return false; + } + + // read nvram + if (read(file, buffer, sizeof(buffer)) != sizeof(buffer)) { + kdError() << "Unable to read from device: " << m_nvramFile << endl; + return false; + } + + // close nvram device + if (close(file) == -1) { + kdError() << "Unable to close device %s: " << m_nvramFile << endl; + return false; + } + + thinkpad_state->thinkpad_toggle + = (thinkpad_state->thinkpad_toggle & ~0x01) | (( buffer[0x57] & 0x08) >> 3); + thinkpad_state->zoom_toggle + = (thinkpad_state->zoom_toggle & ~0x01) | ((~buffer[0x57] & 0x20) >> 5); + thinkpad_state->display_toggle + = (thinkpad_state->display_toggle & ~0x01) | (( buffer[0x57] & 0x40) >> 6); + thinkpad_state->home_toggle + = (thinkpad_state->home_toggle & ~0x01) | (( buffer[0x56] & 0x01) ); + thinkpad_state->search_toggle + = (thinkpad_state->search_toggle & ~0x01) | (( buffer[0x56] & 0x02) >> 1); + thinkpad_state->mail_toggle + = (thinkpad_state->mail_toggle & ~0x01) | (( buffer[0x56] & 0x04) >> 2); + thinkpad_state->thinklight_toggle + = (thinkpad_state->thinklight_toggle & ~0x01) | (( buffer[0x58] & 0x10) >> 4); + thinkpad_state->hibernate_toggle + = (thinkpad_state->hibernate_toggle & ~0x01) | (( buffer[0x58] & 0x01) ); + thinkpad_state->display_state + = (( buffer[0x59] & 0x03) ); + thinkpad_state->expand_toggle + = (thinkpad_state->expand_toggle & ~0x01) | (( buffer[0x59] & 0x10) >> 4); + thinkpad_state->brightness_level + = (( buffer[0x5E] & 0x07) ); + thinkpad_state->brightness_toggle + = (thinkpad_state->brightness_toggle & ~0x01) | (( buffer[0x5E] & 0x20) >> 5); + thinkpad_state->volume_level + = (( buffer[0x60] & 0x0f) ); + thinkpad_state->volume_toggle + = (thinkpad_state->volume_toggle & ~0x01) | (( buffer[0x60] & 0x80) >> 7); + thinkpad_state->mute_toggle + = (thinkpad_state->mute_toggle & ~0x01) | (( buffer[0x60] & 0x40) >> 6); + thinkpad_state->powermgt_ac + = (( buffer[0x39] & 0x07) ); + thinkpad_state->powermgt_battery + = (( buffer[0x39] & 0x38) >> 3); +#else + u_int n = 0; + size_t len = sizeof(n); + + if ( sysctlbyname("dev.acpi_ibm.0.hotkey", &n, &len, NULL, 0) == -1 ) { + kdError() << "Unable to read sysctl: dev.acpi_ibm.0.hotkey" << endl; + return false; + } + + thinkpad_state->thinkpad_toggle + = (thinkpad_state->thinkpad_toggle & ~0x01) | (( n & (1<<3)) >> 3); + thinkpad_state->zoom_toggle + = (thinkpad_state->zoom_toggle & ~0x01) | (( n & (1<<4)) >> 4); + thinkpad_state->display_toggle + = (thinkpad_state->display_toggle & ~0x01) | (( n & (1<<6)) >> 6); + thinkpad_state->home_toggle + = (thinkpad_state->home_toggle & ~0x01) | (( n & (1<<0)) ); + thinkpad_state->search_toggle + = (thinkpad_state->search_toggle & ~0x01) | (( n & (1<<1)) >> 1); + thinkpad_state->mail_toggle + = (thinkpad_state->mail_toggle & ~0x01) | (( n & (1<<2)) >> 2); + thinkpad_state->hibernate_toggle + = (thinkpad_state->hibernate_toggle & ~0x01) | (( n & (1<<7)) >> 7); + thinkpad_state->expand_toggle + = (thinkpad_state->expand_toggle & ~0x01) | (( n & (1<<9)) >> 9); + thinkpad_state->brightness_toggle + = (thinkpad_state->brightness_toggle & ~0x01) | (( n & (1<<10)) >> 10); + thinkpad_state->volume_toggle + = (thinkpad_state->volume_toggle & ~0x01) | (( n & (1<<11)) >> 11); + + // Don't fail if the thinklight sysctl is not present. It is generated dynamically + if ( sysctlbyname("dev.acpi_ibm.0.thinklight", &n, &len, NULL, 0) != -1 ) + thinkpad_state->thinklight_toggle = n; + else + kdWarning() << "Unable to read sysctl: dev.acpi_ibm.0.thinklight" << endl; + + if ( sysctlbyname("dev.acpi_ibm.0.lcd_brightness", &n, &len, NULL, 0) == -1 ) { + kdError() << "Unable to read sysctl: dev.acpi_ibm.0.lcd_brightness" << endl; + return false; + } + thinkpad_state->brightness_level = n; + + if ( sysctlbyname("dev.acpi_ibm.0.volume", &n, &len, NULL, 0) == -1 ) { + kdError() << "Unable to read sysctl: dev.acpi_ibm.0.volume" << endl; + return false; + } + thinkpad_state->volume_level = n; + + if ( sysctlbyname("dev.acpi_ibm.0.mute", &n, &len, NULL, 0) == -1 ) { + kdError() << "Unable to read sysctl: dev.acpi_ibm.0.mute" << endl; + return false; + } + thinkpad_state->mute_toggle = n; + + // Don't fail if wlan or bluetooth sysctls are not present. They are generated dynamically + if ( sysctlbyname("dev.acpi_ibm.0.wlan", &n, &len, NULL, 0) != -1 ) + thinkpad_state->wireless_toggle = n; + else + kdWarning() << "Unable to read sysctl: dev.acpi_ibm.0.wlan" << endl; + + if ( sysctlbyname("dev.acpi_ibm.0.bluetooth", &n, &len, NULL, 0) != -1 ) + thinkpad_state->bluetooth_toggle = n; + else + kdWarning() << "Unable to read sysctl: dev.acpi_ibm.0.bluetooth" << endl; +#endif + return true; +} + +void ThinkPadMonitor::clearStruct(thinkpad_state_struct& thinkpad_state) { + thinkpad_state.thinkpad_toggle = 0; + thinkpad_state.zoom_toggle = 0; + thinkpad_state.display_toggle = 0; + thinkpad_state.home_toggle = 0; + thinkpad_state.search_toggle = 0; + thinkpad_state.mail_toggle = 0; + thinkpad_state.favorites_toggle = 0; + thinkpad_state.reload_toggle = 0; + thinkpad_state.abort_toggle = 0; + thinkpad_state.backward_toggle = 0; + thinkpad_state.forward_toggle = 0; + thinkpad_state.fn_toggle = 0; + thinkpad_state.thinklight_toggle = 0; + thinkpad_state.hibernate_toggle = 0; + thinkpad_state.display_state = 0; + thinkpad_state.expand_toggle = 0; + thinkpad_state.brightness_level = 0; + thinkpad_state.brightness_toggle = 0; + thinkpad_state.volume_level = 0; + thinkpad_state.volume_toggle = 0; + thinkpad_state.mute_toggle = 0; + thinkpad_state.ac_state = 0; + thinkpad_state.powermgt_ac = 0; + thinkpad_state.powermgt_battery = 0; + thinkpad_state.wireless_toggle = 0; + thinkpad_state.bluetooth_toggle = 0; +} + +void ThinkPadMonitor::showToggleMessage(QString onMessage, QString offMessage, bool state) { + QString message; + if (state) { + message = onMessage; + } else { + message = offMessage; + } + _interface->displayText(message); +} + +void ThinkPadMonitor::reconfigure(KConfig* config) { + config->setGroup("thinkpad"); + + m_nvramFile = config->readEntry("nvram", "/dev/nvram"); + m_softwareVolume = config->readBoolEntry("softwareVolume", true); + m_run = config->readBoolEntry("run", false); + m_volumeStep = config->readNumEntry("volumeStep", defaultVolumeStep); + m_buttonThinkpad = config->readEntry("buttonThinkpad", "/usr/bin/konsole"); + m_buttonHome = config->readEntry("buttonHome", "/usr/bin/konqueror"); + m_buttonSearch = config->readEntry("buttonSearch", "/usr/bin/kfind"); + m_buttonMail = config->readEntry("buttonMail", "/usr/bin/kmail"); + m_buttonZoom = config->readEntry("buttonZoom", "/usr/bin/ksnapshot"); +} + +bool ThinkPadMonitor::retrieveVolume() { + bool kmix_error = false; + + DCOPReply reply = kmixClient->call("masterVolume"); + if (reply.isValid()) { + m_volume = reply; + } else { + kmix_error = true; + } + + if (kmix_error) { // maybe the error occurred because kmix wasn't running + if (kapp->startServiceByDesktopName("kmix")==0) { // trying to start kmix + // trying again + reply = kmixClient->call("masterVolume"); + if (reply.isValid()) { + m_volume = reply; + kmix_error = false; + kmixWindow->send("hide"); + } + } + } + + if (kmix_error) { + kdError() << "KMilo: ThinkPadMonitor could not access kmix/Mixer0 via dcop" << endl; + return false; + } else { + return true; + } +} + +void ThinkPadMonitor::setVolume(int volume) { + if (!retrieveVolume()) { + return; + } + + if (volume > 100) { + m_volume = 100; + } else if (volume < 0) { + m_volume = 0; + } else { + m_volume = volume; + } + kmixClient->send("setMasterVolume", m_volume); + + //write back to nvram but only if volume steps is not default + if (m_volumeStep != defaultVolumeStep) { + setNvramVolume(); + } + m_progress = m_volume; +} + +void ThinkPadMonitor::setNvramVolume() { +#ifndef Q_OS_FREEBSD + int file; + char buffer; + + //open nvram + if ((file = open(m_nvramFile.latin1(), O_RDWR|O_NONBLOCK)) == -1) { + kdError() << "Unable to open device " << m_nvramFile << endl; + return; + } + + // jump to volume section + if (lseek(file, 0x60, SEEK_SET) == -1 ) { + kdError() << "Unable to seek device " << m_nvramFile << endl; + return; + } + + // read nvram + if (read(file, &buffer, sizeof(buffer)) != sizeof(buffer)) { + kdError() << "Unable to read from device " << m_nvramFile << endl; + return; + } + + // set volume_level to the value we write back to nvram + // taken from tpb, unfortunatly I'm not sure why it works + thinkpad_state.volume_level = 0x07; + buffer &= 0xf0; + buffer |= thinkpad_state.volume_level; + + // jump to volume section + if (lseek(file, 0x60, SEEK_SET) == -1 ) { + kdError() << "Unable to seek device " << m_nvramFile << endl; + return; + } + + // write std value for volume + if (write(file, &buffer, sizeof(buffer)) != sizeof(buffer)) { + kdError() << "Unable to write to device " << m_nvramFile << endl; + return; + } + + close(file); +#else + u_int n = thinkpad_state.volume_level; + + if (sysctlbyname("dev.acpi_ibm.0.volume", NULL, NULL, &n, sizeof(n))) + kdError() << "Unable to write sysctl: dev.acpi_ibm.0.volume" << endl; +#endif +} + +} + +K_EXPORT_COMPONENT_FACTORY(kmilo_thinkpad, KGenericFactory<KMilo::ThinkPadMonitor>("kmilo_thinkpad")) diff --git a/kmilo/thinkpad/thinkpad.h b/kmilo/thinkpad/thinkpad.h new file mode 100644 index 0000000..f195b2e --- /dev/null +++ b/kmilo/thinkpad/thinkpad.h @@ -0,0 +1,208 @@ +/* + This file is part of the KDE project + + Copyright (c) 2004 Jonathan Riddell <jr@jriddell.org> + + Based on Demo kmilo service by George Staikos + Copyright (c) 2003 George Staikos <staikos@kde.org> + + And tpb by Markus Braun http://www.nongnu.org/tpb/ + Copyright (C) 2002,2003 Markus Braun <markus.braun@krawel.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _THINKPAD_H_ +#define _THINKPAD_H_ + +#include <fcntl.h> +#include <unistd.h> + +#include <kapplication.h> +#include <dcopref.h> + +#include "monitor.h" + +namespace KMilo { + + +const int defaultVolumeStep = 14; + +// all nvram toggle values are stored in bit 0 +// all xevents toggle values are stored in bit 1 +// xevent and apm toggles are not used, kept for compatibility with tpb +typedef struct { + unsigned int thinkpad_toggle; // ThinkPad button + unsigned int zoom_toggle; // zoom toggle + unsigned int display_toggle; // display toggle + unsigned int home_toggle; // Home button + unsigned int search_toggle; // Search button + unsigned int mail_toggle; // Mail button + unsigned int favorites_toggle; // Favorites button (xevent) + unsigned int reload_toggle; // Reload button (xevent) + unsigned int abort_toggle; // Abort button (xevent) + unsigned int backward_toggle; // Backward button (xevent) + unsigned int forward_toggle; // Forward button (xevent) + unsigned int fn_toggle; // Fn button (xevent) + unsigned int thinklight_toggle; // ThinkLight + unsigned int hibernate_toggle; // hibernation/suspend toggle + unsigned int display_state; // display state + unsigned int expand_toggle; // hv expansion state + unsigned int brightness_level; // brightness level + unsigned int brightness_toggle; // brightness toggle + unsigned int volume_level; // volume level + unsigned int volume_toggle; // volume toggle + unsigned int mute_toggle; // mute toggle + unsigned int ac_state; // ac connected (apm) + unsigned int powermgt_ac; // power management mode ac + unsigned int powermgt_battery; // power management mode battery + unsigned int wireless_toggle; // wireless lan toggle + unsigned int bluetooth_toggle; // bluetooth toggle +} thinkpad_state_struct; + +/** + * KMilo plugin for IBM Thinkpads + * Requires read access of nvram: insmod nvram; mknod /dev/nvram c 10 144; chmod 664 /dev/nvram + * + * Models R31 and R30 do not have hardware mixers, other models + * probably want a smaller volume change than thinkpad's default, for + * this you need write access to nvram: chmod 666 /dev/nvram + */ +class ThinkPadMonitor : public Monitor { + public: + ThinkPadMonitor(QObject *parent, const char *name, const QStringList&); + virtual ~ThinkPadMonitor(); + + /** + * Reimplemented from KMilo::Monitor. + * Loads configuration, clears struct, sets volume if necessary. + */ + virtual bool init(); + + /** + * Reimplemented from KMilo::Monitor. + * Called by KMilo, this checks the nvram and acts on any changes + */ + virtual DisplayType poll(); + + /** + * Reimplemented from KMilo::Monitor. + * Called by KMilo if poll() returns a volume or brightness change. + * Returns the new volume or brightness percentage. + */ + virtual int progress() const; + + /** + * Reimplemented from KMilo::Monitor. + * Not used, we just set the message ourselves using _interface->displayText() + */ + virtual QString message() const; + protected: + /** + * Reimplemented from KMilo::Monitor. + * Loads configuration from kmilorc + */ + virtual void reconfigure(KConfig*); + private: + /** + * get the current state from the nvram + */ + bool getNvramState(thinkpad_state_struct* thinkpad_state); + + /** + * get the current state from the nvram + */ + void setNvramVolume(); + + /** + * set all values of thinkpad_state to zero + */ + void clearStruct(thinkpad_state_struct& thinkpad_state); + + /** + * Displays paramater message followed by 'on' or + * 'off' depending on state + */ + void showToggleMessage(QString onMessage, QString offMessage, bool state); + + /** + * Returned by progress() + */ + int m_progress; + + /** + * The file to read data from, default is /dev/nvram + */ + QString m_nvramFile; + + /** + * Some thinkpads change volume in hardware, others we + * have to do it ourselves + */ + bool m_softwareVolume; + + /** + * Config variable determines if this kmilo service is run or not + */ + bool m_run; + + /** + * Amount to change volume by each time, default is 14 + * (as builtin to thinkpads) + */ + int m_volumeStep; + + /** + * Thinkpad button + */ + QString m_buttonThinkpad; + + /** + * Home button + */ + QString m_buttonHome; + + /** + * Search button + */ + QString m_buttonSearch; + + /** + * Mail button + */ + QString m_buttonMail; + + /** + * Zoom button + */ + QString m_buttonZoom; + + /** + * Used for changing the volume if m_softwareVolume is true + */ + void setVolume(int volume); + DCOPRef* kmixClient; + DCOPRef* kmixWindow; + bool retrieveVolume(); + int m_volume, m_oldVolume; + + thinkpad_state_struct thinkpad_state; + thinkpad_state_struct last_thinkpad_state; +}; + +} //close namespace + +#endif |