/* -*- C++ -*- This file implements the KVaio class. $ Author: Mirko Boehm $ $ Copyright: (C) 1996-2003, Mirko Boehm $ $ Contact: mirko@kde.org http://www.kde.org http://www.hackerbuero.org $ $ License: LGPL with the following explicit clarification: This code may be linked against any version of the TQt toolkit from Troll Tech, Norway. $ $Id$ * Portions of this code are * (C) 2001-2002 Stelian Pop and * (C) 2001-2002 Alcove . * Thanks to Stelian for the implementation of the sonypi driver. * Modified by Toan Nguyen * to include support for * Fn+F2,F3,F4 (Volume) * Fn+F5,F6 (Brightness) * Fn+F1 (blankscreen) * Fn+F12 (suspend to disk) */ #include #include "kvaio.h" #include "kmilointerface.h" #include #include #include #include #include #include #include #include #include #include extern "C" { #include #include #include #include #include #include #include #include "./sonypi.h" } KVaio::KVaio(KMiloKVaio *parent, const char* name) : TQObject(parent, name), mDisp(0), mTimer (new TQTimer (this) ) { myparent = parent; mDriver = new KVaioDriverInterface(this); if(!mDriver->connectToDriver()) { delete mDriver; mDriver = 0L; kdDebug() << "KVaio: Cannot connect to driver." << endl; } else { kdDebug() << "KVaio: Connected to SonyPI driver." << endl; connect(mDriver, TQT_SIGNAL(vaioEvent(int)), TQT_SLOT(slotVaioEvent(int))); connect (mTimer, TQT_SIGNAL (timeout ()), TQT_SLOT (slotTimeout() ) ); mTimer->start (10000, true); } mDisp = XOpenDisplay(NULL); if(!mDisp) { kdDebug() << "KVaio ctor: Failed to open display. Very strange." << endl; } if(!mClient.attach()) { kdDebug() << "KVaio ctor: cannot attach to DCOP server." << endl; } KConfig config("kmilodrc"); loadConfiguration(&config); m_mute = false; m_progress = 0; m_minVolume = 0; m_maxVolume = 100; m_volume = 50; m_VolumeStep = 10; m_brightness = 128; m_minBright = 0; m_maxBright = 255; m_BrightnessStep = 16; kmixClient = new DCOPRef("kmix", "Mixer0"); kmixWindow = new DCOPRef("kmix", "kmix-mainwindow#1"); // retrieveVolume(); // retrieveMute(); } KVaio::~KVaio() { kdDebug() << "KVaio dtor: shutting down." << endl; if(mDriver!=0) { mDriver->disconnectFromDriver(); } if(mClient.isAttached()) { mClient.detach(); } } void KVaio::slotVaioEvent(int event) { TQString text; TQTextStream stream(text, IO_WriteOnly); switch(event) { case SONYPI_EVENT_FNKEY_RELEASED: break; case SONYPI_EVENT_FNKEY_F1: blankScreen(); break; case SONYPI_EVENT_FNKEY_F2: mute(); break; case SONYPI_EVENT_FNKEY_F3: VolumeDown(m_VolumeStep); break; case SONYPI_EVENT_FNKEY_F4: VolumeUp(m_VolumeStep); break; case SONYPI_EVENT_FNKEY_F5: BrightnessDown(m_BrightnessStep); break; case SONYPI_EVENT_FNKEY_F6: BrightnessUp(m_BrightnessStep); break; case SONYPI_EVENT_FNKEY_F12: suspendToDisk(); break; case SONYPI_EVENT_MEMORYSTICK_INSERT: showTextMsg( i18n ("Memory Stick inserted") ); break; case SONYPI_EVENT_MEMORYSTICK_EJECT: showTextMsg( i18n ("Memory Stick ejected") ); break; case SONYPI_EVENT_BACK_PRESSED: if (mShowPowerStatusOnBackButton) { showBatterytqStatus (true); } break; default: stream << i18n("Unhandled event: ") << event; if(mReportUnknownEvents) showTextMsg(text); kdDebug() << "KVaio::slotVaioEvent: event not handled." << endl; } } bool KVaio::showTextMsg(const TQString& msg) { return myparent->showTextMsg(msg); } bool KVaio::showProgressMsg(const TQString& msg, int value) { m_progress = value; return myparent->showProgressMsg(msg,value); } void KVaio::blankScreen() { bool blankonly; if (isKScreensaverAvailable()) { TQByteArray data, replyData; TQDataStream arg(data, IO_WriteOnly); TQCString replyType; /* Set the screensave to BlankOnly mode */ blankonly = true; arg << blankonly; mClient.call("kdesktop","KScreensaverIface","setBlankOnly(bool)", data, replyType, replyData) ; /* Save the screen */ if ( !mClient.call("kdesktop", "KScreensaverIface", "save()", data, replyType, replyData) ) { kdDebug() << "KVaio::blankScreen: there was some error " << "using DCOP." << endl; } /* Set the screensave to its original mode */ blankonly = false; arg << blankonly; mClient.call("kdesktop","KScreensaverIface","setBlankOnly(bool)", data, replyType, replyData) ; } } void KVaio::suspendToDisk() { TQByteArray data, replyData; TQDataStream arg(data, IO_WriteOnly); TQCString replyType; mClient.call("kpowersave","KPowersaveIface","do_suspendToDisk()", data, replyType, replyData) ; } bool KVaio::isKScreensaverAvailable() { if(mClient.isAttached()) { // kdDebug() << "KVaio::showTextMsg: attached to DCOP server." << endl; if(mClient.isApplicationRegistered("kdesktop")) { QCStringList objects; // kdDebug() << "KVaio::showTextMsg: kded is registered at dcop server." // << endl; objects = mClient.remoteObjects("kdesktop"); if(objects.contains("KScreensaverIface")) { // kdDebug() << "KVaio::showTextMsg: kmilod is available at kded." // << endl; return true; } else { kdDebug() << "KVaio::isKScreensaverAvailable: " << "KScreensaverIface is NOT available at kdesktop." << endl; return false; } } else { kdDebug() << "KVaio::isKScreensaverAvailable: " << "kdesktop is NOT registered at dcop server." << endl; return false; } } else { kdDebug() << "KVaio::isKScreensaverAvailable: " << "kdesktop is NOT registered at dcop server." << endl; return false; } } bool KVaio::isKMiloDAvailable() { if(mClient.isAttached()) { // kdDebug() << "KVaio::showTextMsg: attached to DCOP server." << endl; if(mClient.isApplicationRegistered("kded")) { QCStringList objects; // kdDebug() << "KVaio::showTextMsg: kded is registered at dcop server." // << endl; objects = mClient.remoteObjects("kded"); if(objects.contains("kmilod")) { // kdDebug() << "KVaio::showTextMsg: kmilod is available at kded." // << endl; return true; } else { kdDebug() << "KVaio::isKMiloDAvailable: " << "kmilod is NOT available at kded." << endl; return false; } } else { kdDebug() << "KVaio::isKMiloDAvailable: " << "kded is NOT registered at dcop server." << endl; return false; } } else { kdDebug() << "KVaio::isKMiloDAvailable: " << "kded is NOT registered at dcop server." << endl; return false; } } void KVaio::loadConfiguration(KConfig *k) { k->setGroup("KVaio"); mReportUnknownEvents = k->readBoolEntry("Report_Unknown_Events", false); mReportPowertqStatus = k->readBoolEntry("PeriodicallyReportPowertqStatus", false); mShowPowerStatusOnBackButton = k->readBoolEntry("PowerStatusOnBackButton", true); kdDebug() << "KVaio::loadConfiguration: " << endl << " mReportUnknownEvents: " << mReportUnknownEvents << endl << " mReportPowertqStatus: " << mReportPowertqStatus << endl << "mShowPowerStatusOnBackButton: " << mShowPowerStatusOnBackButton << endl; } const KVaioDriverInterface* KVaio::driver() { return mDriver; } void KVaio::slotTimeout () { showBatterytqStatus (); mTimer->start (4000, true); } bool KVaio::showBatterytqStatus ( bool force ) { static bool acConnectedCache = false; static int previousChargeCache = -1; bool bat1Avail = false, bat2Avail = false, acConnected = false; int bat1Remaining = 0, bat1Max = 0, bat2Remaining = 0, bat2Max = 0; bool displayBatteryMsg = false; bool displayACtqStatus = false; TQString text, acMsg; TQTextStream stream(text, IO_WriteOnly); // ----- // only display on startup if mReportPowertqStatus is true: if (mReportPowertqStatus==false || !force) { return true; } // query all necessary information: (void) mDriver->getBatterytqStatus(bat1Avail, bat1Remaining, bat1Max, bat2Avail, bat2Remaining, bat2Max, acConnected); int remaining; if ( bat1Avail || bat2Avail ) remaining = (int)(100.0*(bat1Remaining+bat2Remaining) / (bat1Max+bat2Max)); else remaining = -1; // no battery available if (acConnectedCache != acConnected || force) { displayACtqStatus = true; acConnectedCache = acConnected; } displayBatteryMsg = ( previousChargeCache * 100 / remaining > 1000 ) || ( previousChargeCache * 100 / remaining > 200 && remaining < 10 ) || force; if (displayBatteryMsg) { previousChargeCache = remaining; } // ----- prepare text messages if (displayACtqStatus || displayBatteryMsg) { if (displayACtqStatus) { acMsg = acConnected ? i18n ("AC Connected") : i18n ("AC Disconnected"); } switch (remaining) { case 100: stream << i18n("Battery is Fully Charged. "); break; case 5: case 4: case 3: case 2: case 1: stream << i18n("Caution: Battery is Almost Empty (%1% remaining).").tqarg(remaining); break; case 0: stream << i18n("Alert: Battery is Empty!"); break; case -1: stream << i18n("No Battery Inserted."); break; default: stream << i18n("Remaining Battery Capacity: %1%").tqarg( remaining ); }; // show a message if the battery status changed by more then 10% or on startup if (displayACtqStatus) { stream << endl << acMsg; } return showTextMsg (text); } else { return true; } } void KVaio::BrightnessUp(int step) { m_brightness = mDriver->brightness(); m_brightness += step; if(m_brightness > m_maxBright) { m_brightness = m_maxBright; } mDriver->setBrightness(m_brightness); showProgressMsg( i18n("Brightness"), m_brightness*100/255); } void KVaio::BrightnessDown(int step) { m_brightness = mDriver->brightness(); m_brightness -= step; if(m_brightness < m_minBright) { m_brightness = m_minBright; } mDriver->setBrightness(m_brightness); showProgressMsg( i18n("Brightness"), m_brightness*100/255); } void KVaio::displayVolume() { // _interface->displayProgress(i18n("Volume"), m_volume); showProgressMsg(i18n("Volume"), m_volume); // If we got this far, the DCOP communication with kmix works, // so we don't have to test the result. kmixClient->send("setMasterVolume", m_volume); // if mute then unmute if (m_mute) { m_mute = false; kmixClient->send("setMasterMute", m_mute); } } bool KVaio::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 { // _interface->displayText showTextMsg(i18n("Starting KMix...")); 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) { kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" << endl; //_interface->displayText showTextMsg(i18n("It seems that KMix is not running.")); return false; } else { return true; } } void KVaio::VolumeUp(int step) { if (!retrieveVolume()) return; // FIXME if the mixer doesn't support steps of the specified size it // could get stuck at one position m_volume += step; if (m_volume > m_maxVolume) m_volume = m_maxVolume; displayVolume(); } void KVaio::VolumeDown(int step) { if (!retrieveVolume()) return; m_volume -= step; if (m_volume < m_minVolume) m_volume = m_minVolume; displayVolume(); } bool KVaio::retrieveMute() { bool kmix_error = false; DCOPReply reply = kmixClient->call("masterMute"); if (reply.isValid()) m_volume = reply; else kmix_error = true; if (kmix_error) { // maybe the error occurred because kmix wasn't running //_interface->displayText showTextMsg(i18n("Starting KMix...")); if (kapp->startServiceByDesktopName("kmix")==0) // trying to start kmix { // trying again reply = kmixClient->call("masterMute"); if (reply.isValid()) { m_mute = reply; kmix_error = false; kmixWindow->send("hide"); } } else { kmixWindow->send("hide"); kmix_error = true; } } if (kmix_error) { kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" << endl; //_interface->displayText showTextMsg(i18n("It seems that KMix is not running.")); return false; } else { return true; } } void KVaio::mute() { if (!retrieveMute()) return; m_mute = !m_mute; int newVolume; TQString muteText; if (m_mute) { m_oldVolume = m_volume; newVolume = 0; muteText = i18n("Mute on"); } else { newVolume = m_oldVolume; muteText = i18n("Mute off"); } kmixClient->send("setMasterMute", m_mute); //_interface->displayText(muteText); showTextMsg(muteText); } #include "kvaio.moc"