gizmod/GizmoDaemon.cpp

Go to the documentation of this file.
00001 
00012 /*
00013   
00014   Copyright (c) 2007, Tim Burrell
00015   Licensed under the Apache License, Version 2.0 (the "License");
00016   you may not use this file except in compliance with the License.
00017   You may obtain a copy of the License at 
00018 
00019         http://www.apache.org/licenses/LICENSE-2.0
00020 
00021   Unless required by applicable law or agreed to in writing, software
00022   distributed under the License is distributed on an "AS IS" BASIS,
00023   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00024   See the License for the specific language governing permissions and 
00025   limitations under the License. 
00026   
00027 */
00028 
00029 #include "GizmoDaemon.hpp"
00030 #include "GizmoDaemonDefs.hpp"
00031 #include "../libGizmod/GizmodThread.hpp"
00032 #include "../libGizmod/GizmodTimer.hpp"
00033 #include "../libGizmod/GizmoEventATIX10.hpp"
00034 #include "../libGizmod/GizmoEventCPUUsage.hpp"
00035 #include "../libGizmod/GizmoEventLIRC.hpp"
00036 #include "../libGizmod/GizmoEventPowermate.hpp"
00037 #include "../libGizmod/GizmoEventSoundCard.hpp"
00038 #include "../libGizmod/GizmoEventStandard.hpp"
00039 #include "../libGizmod/GizmoEventSoundCard.hpp"
00040 #include "../libGizmod/GizmoEventSoundVisualization.hpp"
00041 #include "../libGizmod/GizmoEventWindowFocus.hpp"
00042 #include "../libGizmod/GizmoATIX10.hpp"
00043 #include "../libGizmod/GizmoLIRC.hpp"
00044 #include "../libGizmod/GizmoPowermate.hpp"
00045 #include "../libGizmod/GizmoStandard.hpp"
00046 #include "../libH/Debug.hpp"
00047 #include "../libH/Exception.hpp"
00048 #include "../libH/Util.hpp"
00049 #include "../libH/UtilFile.hpp"
00050 #include "../libH/SocketException.hpp"
00051 #include <cstdlib>
00052 #include <iostream>
00053 #include <sstream>
00054 #include <fstream>
00055 #include <list>
00056 #include <boost/program_options.hpp>
00057 #include <boost/format.hpp>
00058 #include <boost/python.hpp>
00059 #include <boost/filesystem/operations.hpp>
00060 #include <boost/filesystem/exception.hpp>
00061 #include <boost/algorithm/string/replace.hpp>
00062 #include <boost/algorithm/string/trim.hpp>
00063 #include <boost/archive/text_iarchive.hpp>
00064 #include <boost/archive/text_oarchive.hpp>
00065 #include <boost/serialization/base_object.hpp>
00066 #include <boost/serialization/utility.hpp>
00067 #include <boost/serialization/list.hpp>
00068 #include <boost/tokenizer.hpp>
00069 #include <fcntl.h>
00070 #include <pystate.h>
00071 
00072 using namespace std;
00073 using namespace boost;
00074 using namespace boost::program_options;
00075 using namespace boost::python;
00076 using namespace boost::filesystem;
00077 using namespace H;
00078 
00080 // Type Defs / defines
00082 
00087 #define CONFIG_FILE             PACKAGE ".conf"
00088 
00093 #define SCRIPT_DIR              SYSCONFDIR "/gizmod/"
00094 
00099 #define HOME_SCRIPT_DIR         "~/.gizmod/"
00100 
00105 #define CONFIG_FILE_PATH        HOME_SCRIPT_DIR PACKAGE ".conf"
00106 
00111 #define USER_SCRIPT_DIR         "modules.d"
00112 
00117 #define SCRIPT_DISPATCHER       "GizmodDispatcher.py"
00118 
00123 #define SCRIPT_USER             "GizmodUser.py"
00124 
00129 #define EVENT_NODE_DIR          "/dev/input"
00130 
00135 #define LIRC_DEV                "/dev/lircd"
00136 
00141 #define NO_GETTER               python::object()
00142 
00147 #define DEFAULT_PORT            30303
00148 
00153 #define DEFAULT_PORT_STR        "30303"
00154 
00156 // C++ -> Python Exposures
00158 
00163 struct GizmodEventHandlerInterfaceWrap : public GizmodEventHandlerInterface {
00165         GizmodEventHandlerInterfaceWrap(PyObject * self_) : self(self_) {}
00166 
00167         bool            getInitialized() { return python::call_method<bool>(self, "getInitialized"); }
00168         void            initialize()     { return python::call_method<void>(self, "initialize"); }
00169         void            onDeregisterDevice(GizmoATIX10 const * Device) { return python::call_method<void>(self, "onDeregisterDevice", ptr(Device)); }
00170         void            onDeregisterDevice(GizmoLIRC const * Device) { return python::call_method<void>(self, "onDeregisterDevice", ptr(Device)); }
00171         void            onDeregisterDevice(GizmoPowermate const * Device) { return python::call_method<void>(self, "onDeregisterDevice", ptr(Device)); }
00172         void            onDeregisterDevice(GizmoStandard const * Device) { return python::call_method<void>(self, "onDeregisterDevice", ptr(Device)); }
00173         void            onEvent(GizmoEventATIX10 const * Event, GizmoATIX10 const * Device) { return python::call_method<void>(self, "onEvent", ptr(Event), ptr(Device)); }
00174         void            onEvent(GizmoEventCPUUsage const * Event) { return python::call_method<void>(self, "onEvent", ptr(Event)); }
00175         void            onEvent(GizmoEventLIRC const * Event, GizmoLIRC const * Device) { return python::call_method<void>(self, "onEvent", ptr(Event), ptr(Device)); }
00176         void            onEvent(GizmoEventPowermate const * Event, GizmoPowermate const * Device) { return python::call_method<void>(self, "onEvent", ptr(Event), ptr(Device)); }
00177         void            onEvent(GizmoEventSoundCard const * Event) { return python::call_method<void>(self, "onEvent", ptr(Event)); }
00178         void            onEvent(GizmoEventSoundVisualization const * Event) { return python::call_method<void>(self, "onEvent", ptr(Event)); }
00179         void            onEvent(GizmoEventStandard const * Event, GizmoStandard const * Device) { return python::call_method<void>(self, "onEvent", ptr(Event), ptr(Device)); }
00180         void            onEvent(GizmoEventWindowFocus const * Event) { return python::call_method<void>(self, "onEvent", ptr(Event)); }
00181         GizmoClass      onQueryDeviceClass(DeviceInfo DeviceInformation) { return python::call_method<GizmoClass>(self, "onQueryDeviceClass", DeviceInformation); };
00182         void            onRegisterDevice(GizmoATIX10 const * Device) { return python::call_method<void>(self, "onRegisterDevice", ptr(Device)); }
00183         void            onRegisterDevice(GizmoLIRC const * Device) { return python::call_method<void>(self, "onRegisterDevice", ptr(Device)); }
00184         void            onRegisterDevice(GizmoPowermate const * Device) { return python::call_method<void>(self, "onRegisterDevice", ptr(Device)); }
00185         void            onRegisterDevice(GizmoStandard const * Device) { return python::call_method<void>(self, "onRegisterDevice", ptr(Device)); }
00186 
00187         PyObject *      self;                   
00188 };
00189 
00193 BOOST_PYTHON_MODULE(GizmoDaemon) {
00195         // Enum exports
00197         
00199         enum_<AlsaEventType>("AlsaEventType")
00200                 .value("Error",                 ALSAEVENT_ERROR)
00201                 .value("SoundCardAttach",       ALSAEVENT_SOUNDCARD_ATTACH)
00202                 .value("SoundCardDetach",       ALSAEVENT_SOUNDCARD_DETACH)
00203                 .value("MixerElementAttach",    ALSAEVENT_MIXERELEMENT_ATTACH)
00204                 .value("MixerElementChange",    ALSAEVENT_MIXERELEMENT_CHANGE)
00205                 .value("MixerElementDetach",    ALSAEVENT_MIXERELEMENT_DETACH)
00206                 ;
00207         
00209         enum_<GizmoClass>("GizmoClass")
00210                 .value("ATIX10",                GIZMO_CLASS_ATIX10)
00211                 .value("LIRC",                  GIZMO_CLASS_LIRC)
00212                 .value("Powermate",             GIZMO_CLASS_POWERMATE)
00213                 .value("Standard",              GIZMO_CLASS_STANDARD)
00214                 ;
00215         
00217         enum_<GizmoEventClass>("GizmoEventClass")
00218                 .value("ATIX10",                GIZMO_EVENTCLASS_ATIX10)
00219                 .value("CPUUsage",              GIZMO_EVENTCLASS_CPUUSAGE)
00220                 .value("LIRC",                  GIZMO_EVENTCLASS_LIRC)
00221                 .value("Powermate",             GIZMO_EVENTCLASS_POWERMATE)
00222                 .value("SoundCard",             GIZMO_EVENTCLASS_SOUNDCARD)
00223                 .value("SoundVisualization",    GIZMO_EVENTCLASS_SOUNDVISUALIZATION)
00224                 .value("Standard",              GIZMO_EVENTCLASS_STANDARD)
00225                 .value("WindowFocus",           GIZMO_EVENTCLASS_WINDOWFOCUS)
00226                 ;       
00227         
00229         enum_<SoundVisualizationEventType>("SoundVisualizationEventType")
00230                 .value("Connect",               SOUNDVISUALIZATION_CONNECT)
00231                 .value("Disconnect",            SOUNDVISUALIZATION_DISCONNECT)
00232                 .value("Render",                SOUNDVISUALIZATION_RENDER)
00233                 ;
00234         
00236         enum_<X11FocusEventType>("X11FocusEventType")
00237                 .value("FocusIn",               X11FOCUSEVENT_IN)
00238                 .value("FocusOut",              X11FOCUSEVENT_OUT)
00239                 ;
00240         
00242         #include "GizmoKeyDefPythonExposures.hpp"       
00243         
00245         // General Class exports
00247                                         
00249         class_<AlsaInterface>("AlsaInterface")
00250                 ;
00251                  
00253         class_<AlsaMixerElements>("AlsaMixerElements")
00254                 .def_readonly("IsActive", &AlsaMixerElements::IsActive)
00255                 .def_readonly("HasCommonVolume", &AlsaMixerElements::HasCommonVolume)
00256                 .def_readonly("HasPlaybackVolume", &AlsaMixerElements::HasPlaybackVolume)
00257                 .def_readonly("HasPlaybackVolumeJoined", &AlsaMixerElements::HasPlaybackVolumeJoined)
00258                 .def_readonly("HasCaptureVolume", &AlsaMixerElements::HasCaptureVolume)
00259                 .def_readonly("HasCaptureVolumeJoined", &AlsaMixerElements::HasCaptureVolumeJoined)
00260                 .def_readonly("HasCommonSwitch", &AlsaMixerElements::HasCommonSwitch)
00261                 .def_readonly("HasPlaybackSwitch", &AlsaMixerElements::HasPlaybackSwitch)
00262                 .def_readonly("HasPlaybackSwitchJoined", &AlsaMixerElements::HasPlaybackSwitchJoined)
00263                 .def_readonly("HasCaptureSwitch", &AlsaMixerElements::HasCaptureSwitch)
00264                 .def_readonly("HasCaptureSwitchJoined", &AlsaMixerElements::HasCaptureSwitchJoined)
00265                 .def_readonly("HasCaptureSwitchExclusive", &AlsaMixerElements::HasCaptureSwitchExclusive)
00266                 .def_readonly("VolumeCapture", &AlsaMixerElements::VolumeCapture)
00267                 .def_readonly("VolumeCaptureMin", &AlsaMixerElements::VolumeCaptureMin)
00268                 .def_readonly("VolumeCaptureMax", &AlsaMixerElements::VolumeCaptureMax)
00269                 .def_readonly("VolumeCapturePercent", &AlsaMixerElements::VolumeCapturePercent) 
00270                 .def_readonly("VolumePlayback", &AlsaMixerElements::VolumePlayback)
00271                 .def_readonly("VolumePlaybackMin", &AlsaMixerElements::VolumePlaybackMin)
00272                 .def_readonly("VolumePlaybackMax", &AlsaMixerElements::VolumePlaybackMax)
00273                 .def_readonly("VolumePlaybackPercent", &AlsaMixerElements::VolumePlaybackPercent)       
00274                 .def_readonly("SwitchPlayback", &AlsaMixerElements::SwitchPlayback)
00275                 .def_readonly("SwitchCapture", &AlsaMixerElements::SwitchCapture)
00276                 ;
00277                  
00279         class_< AlsaMixer, bases<AlsaMixerElements> >("AlsaMixer")
00280                 .def("getName", &AlsaMixer::getName)
00281                 .add_property("Name", &AlsaMixer::getName)
00282                 .def("getNameShort", &AlsaMixer::getNameShort)
00283                 .add_property("NameShort", &AlsaMixer::getNameShort)
00284                 .def("setSwitchCapture", &AlsaMixer::setSwitchCapture)
00285                 .add_property("SwitchCapture", &AlsaMixer::SwitchCapture, &AlsaMixer::setSwitchCapture)
00286                 .def("setSwitchPlayback", &AlsaMixer::setSwitchPlayback)
00287                 .add_property("SwitchPlayback", &AlsaMixer::SwitchPlayback, &AlsaMixer::setSwitchPlayback)
00288                 .def("setVolumeCapture", &AlsaMixer::setVolumeCapture)
00289                 .add_property("VolumeCapture", &AlsaMixer::VolumeCapture, &AlsaMixer::setVolumeCapture)
00290                 .def("setVolumeCapturePercent", &AlsaMixer::setVolumeCapturePercent)
00291                 .add_property("VolumeCapturePercent", &AlsaMixer::VolumeCapturePercent, &AlsaMixer::setVolumeCapturePercent)
00292                 .def("setVolumePlayback", &AlsaMixer::setVolumePlayback)
00293                 .add_property("VolumePlayback", &AlsaMixer::VolumePlayback, &AlsaMixer::setVolumePlayback)
00294                 .def("setVolumePlaybackPercent", &AlsaMixer::setVolumePlaybackPercent)
00295                 .add_property("VolumePlaybackPercent", &AlsaMixer::VolumePlaybackPercent, &AlsaMixer::setVolumePlaybackPercent)
00296                 ;
00297                  
00299         class_<AlsaSoundCard>("AlsaSoundCard", init<AlsaInterface *, int>())
00300                 .def("getCardHardwareID", &AlsaSoundCard::getCardHardwareID)
00301                 .add_property("CardHardwareID", &AlsaSoundCard::getCardHardwareID)
00302                 .def("getCardID", &AlsaSoundCard::getCardID)
00303                 .add_property("CardID", &AlsaSoundCard::getCardID)
00304                 .def("getCardNameLong", &AlsaSoundCard::getCardNameLong)
00305                 .add_property("CardNameLong", &AlsaSoundCard::getCardNameLong)
00306                 .def("getCardName", &AlsaSoundCard::getCardName)
00307                 .add_property("CardName", &AlsaSoundCard::getCardName)          
00308                 .def("getMixer", &AlsaSoundCard::getMixer, return_internal_reference<>())
00309                 .def("getNumMixers", &AlsaSoundCard::getNumMixers)
00310                 .def("setAllPlaybackSwitches", &AlsaSoundCard::setAllPlaybackSwitches)
00311                 ;
00312         
00314         class_<Alsa>("Alsa")
00315                 .def("getDefaultMixerSwitch", &Alsa::getDefaultMixerSwitch, return_internal_reference<>())                      
00316                 .add_property("DefaultMixerSwitch", make_function(&Alsa::getDefaultMixerSwitch, return_internal_reference<>()))
00317                 .def("getDefaultMixerVolume", &Alsa::getDefaultMixerVolume, return_internal_reference<>())
00318                 .add_property("DefaultMixerVolume", make_function(&Alsa::getDefaultMixerVolume, return_internal_reference<>()))
00319                 .def("getSoundCard", &Alsa::getSoundCard, return_internal_reference<>())
00320                 .def("getNumSoundCards", &Alsa::getNumSoundCards)
00321                 .def("registerDefaultMixerPriority", &Alsa::registerDefaultMixerPriority)
00322                 .def("toggleMuteAllCards", &Alsa::toggleMuteAllCards)
00323                 ;
00324                                  
00326         class_<DeviceInfo>("GizmoDeviceInfo")
00327                 .def_readonly("DeviceName", &DeviceInfo::DeviceName)
00328                 .def_readonly("DeviceIDBusType", &DeviceInfo::DeviceIDBusType)
00329                 .def_readonly("DeviceIDVendor", &DeviceInfo::DeviceIDVendor)
00330                 .def_readonly("DeviceIDProduct", &DeviceInfo::DeviceIDProduct)
00331                 .def_readonly("DeviceIDVersion", &DeviceInfo::DeviceIDVersion)
00332                 .def_readonly("FileName", &DeviceInfo::FileName)
00333                 ;
00334         
00336         class_< Gizmo, bases<DeviceInfo> >("Gizmo", init<GizmoClass, const DeviceInfo &, int, int>())
00337                 .def("getClass", &Gizmo::getClass)
00338                 .add_property("Class", &Gizmo::getClass)                                
00339                 .def("getDeviceID", &Gizmo::getDeviceID)
00340                 .add_property("DeviceID", &Gizmo::getDeviceID)
00341                 .def("getDeviceClassID", &Gizmo::getDeviceClassID)
00342                 .add_property("DeviceClassID", &Gizmo::getDeviceClassID)
00343                 .def("getKeyState", &Gizmo::getKeyState)
00344                 .def("getType", &Gizmo::getType)
00345                 .add_property("Type", &Gizmo::getType)
00346                 .def("setKeyState", &Gizmo::setKeyState)
00347                 ;
00348                         
00350         class_<CPUUsage>("CPUUsage")
00351                 .def("getNumCPUs", &CPUUsage::getNumCPUs)
00352                 .def("setTimeBetweenUpdates", &CPUUsage::setTimeBetweenUpdates)
00353                 ;                       
00354         
00356         class_<Processes>("Processes")
00357                 .def("isProcessRunning", &Processes::isProcessRunning)
00358                         .staticmethod("isProcessRunning")
00359                 .def("setTimeBetweenUpdates", &Processes::setTimeBetweenUpdates)
00360                         .staticmethod("setTimeBetweenUpdates")
00361                 .def("updateProcessTree", &Processes::updateProcessTree)
00362                         .staticmethod("updateProcessTree")
00363                 ;               
00364         
00366         class_<X11FocusWatcher>("X11FocusWatcher")
00367                 .def("isApplicationRunning", &X11FocusWatcher::isApplicationRunning)
00368                 .def("setInputFocus", &X11FocusWatcher::setInputFocus)
00369                 ;               
00370         
00372         class_<GizmoUtils>("GizmoUtils")
00373                 .def("bitDifference", &GizmoUtils::bitDifference)
00374                         .staticmethod("bitDifference")
00375                 ;               
00376         
00378         class_<GizmoDaemon, bases<Alsa, X11FocusWatcher, Processes, CPUUsage, GizmoUtils> >("PyGizmoDaemon")
00379                 .def("checkVersion", &GizmoDaemon::checkVersion)
00380                 .def("getCurrentFocus", &GizmoDaemon::getCurrentFocus)
00381                 .add_property("CurrentFocus", &GizmoDaemon::getCurrentFocus)
00382                 .def("getDebugEnabled", &GizmoDaemon::getDebugEnabled)
00383                 .add_property("DebugEnabled", &GizmoDaemon::getDebugEnabled)
00384                 .def("getNumGizmosByClass", &GizmoDaemon::getNumGizmosByClass)
00385                 .def("getUseKeyboardLEDs", &GizmoDaemon::getUseKeyboardLEDs)
00386                 .add_property("UseKeyboardLEDs", &GizmoDaemon::getUseKeyboardLEDs)
00387                 .def("getUseRemoteControl", &GizmoDaemon::getUseRemoteControl)
00388                 .add_property("UseRemoteControl", &GizmoDaemon::getUseRemoteControl)
00389                 .def("getVersion", &GizmoDaemon::getVersion)
00390                 .add_property("Version", &GizmoDaemon::getVersion)
00391                 .def("printNiceScriptInit", &GizmoDaemon::printNiceScriptInit)
00392                 .def("printNiceScriptRegister", &GizmoDaemon::printNiceScriptRegister)
00393                 .def("signalShutdown", &GizmoDaemon::signalShutdown)
00394                 ;
00395                         
00397         class_<GizmoTimeVal>("GizmoTimeVal")
00398                 .def_readonly("Seconds", &GizmoTimeVal::Seconds)
00399                 .def_readonly("MicroSeconds", &GizmoTimeVal::MicroSeconds)
00400                 ;
00401                 
00403         // Event class exports
00405         
00407         class_<AlsaEvent>("AlsaEvent")
00408                 .def_readonly("Type", &AlsaEvent::Type)
00409                 .def_readonly("Mask", &AlsaEvent::Mask)         
00410                 .def_readonly("IsActiveChanged", &AlsaEvent::IsActiveChanged)
00411                 .def_readonly("ElementsChanged", &AlsaEvent::ElementsChanged)
00412                 .def_readonly("VolumePlaybackChanged", &AlsaEvent::VolumePlaybackChanged)
00413                 .def_readonly("VolumeCaptureChanged", &AlsaEvent::VolumeCaptureChanged)
00414                 .def_readonly("SwitchPlaybackChanged", &AlsaEvent::SwitchPlaybackChanged)
00415                 .def_readonly("SwitchCaptureChanged", &AlsaEvent::SwitchCaptureChanged)
00416                 ;
00417         
00419         class_<GizmodEventHandlerInterface, GizmodEventHandlerInterfaceWrap, boost::noncopyable>("GizmodEventHandler")
00420                 ;
00421         
00423         class_<GizmodThread>("GizmodThread", init<boost::python::object>())
00424                 .def("create", &GizmodThread::create)
00425                 ;       
00426 
00428         class_<GizmodTimer>("GizmodTimer", init<float, boost::python::object>())
00429                 .def(init<float, boost::python::object, boost::python::object>())
00430                 .def(init<float, boost::python::object, int, boost::python::object>())
00431                 .def("start", &GizmodTimer::start)
00432                 .def("setUserData", &GizmodTimer::setUserData)
00433                 .def("setTime", &GizmodTimer::setTime)
00434                 .def("resetTimer", &GizmodTimer::resetTimer)
00435                 .def("cancel", &GizmodTimer::cancel)
00436                 ;       
00437         
00439         class_<GizmoEvent>("GizmoEvent", init<GizmoEventClass, bool>())
00440                 .def("getClass", &GizmoEvent::getClass)
00441                 .add_property("Class", &GizmoEvent::getClass)
00442                 .def("isRemote", &GizmoEvent::isRemote)
00443                 .add_property("Remote", &GizmoEvent::isRemote)
00444                 ;
00445                 
00447         class_< GizmoEventCPUUsage, bases<GizmoEvent> >("GizmoEventCPUUsage")
00448                 .def("getCPUUsage", &GizmoEventCPUUsage::getCPUUsage)           
00449                 .def("getCPUUsageAvg", &GizmoEventCPUUsage::getCPUUsageAvg)
00450                 .def("getNumCPUs", &GizmoEventCPUUsage::getNumCPUs)
00451                 .add_property("NumCPUs", &GizmoEventCPUUsage::getNumCPUs)
00452                 ;
00453                         
00455         class_< GizmoEventLIRC, bases<GizmoEvent> >("GizmoEventLIRC")
00456                 .def_readonly("Code", &GizmoEventLIRC::Code)
00457                 .def_readonly("Repeat", &GizmoEventLIRC::Repeat)
00458                 .def_readonly("Button", &GizmoEventLIRC::Button)
00459                 .def_readonly("Remote", &GizmoEventLIRC::Remote)
00460                 ;
00461                 
00463         class_<GizmoLinuxInputDevice>("GizmoLinuxInputDevice", init<const DeviceInfo &>())
00464                 .def("createEventRaw", &GizmoLinuxInputDevice::createEventRaw)
00465                 .def("createEventPress", &GizmoLinuxInputDevice::createEventPress)
00466                 .def("createEvent", &GizmoLinuxInputDevice::createEventPress)
00467                 .def("createEventPressMod", &GizmoLinuxInputDevice::createEventPressMod)
00468                 .def("createEventPress", &GizmoLinuxInputDevice::createEventPressMod)
00469                 .def("createEvent", &GizmoLinuxInputDevice::createEventPressMod)
00470                 .def("createEvents", &GizmoLinuxInputDevice::createEvents)
00471                 .def("grabExclusiveAccess", &GizmoLinuxInputDevice::grabExclusiveAccess)
00472                 .def("remapKey", &GizmoLinuxInputDevice::remapKey)
00473                 .def("setMinimumTimeBetweenEvents", &GizmoLIRC::setMinimumTimeBetweenEvents)
00474                 ;
00475         
00477         class_<GizmoLinuxInputEvent>("GizmoLinuxInputEvent")
00478                 .def_readonly("RawCode", &GizmoLinuxInputEvent::RawCode)
00479                 .def_readonly("RawType", &GizmoLinuxInputEvent::RawType)
00480                 .def_readonly("Value", &GizmoLinuxInputEvent::Value)
00481                 .def_readonly("TimeStamp", &GizmoLinuxInputEvent::TimeStamp)
00482                 .def_readonly("Code", &GizmoLinuxInputEvent::Code)
00483                 .def_readonly("Type", &GizmoLinuxInputEvent::Type)
00484                 ;
00485         
00487         class_< GizmoEventATIX10, bases<GizmoEvent, GizmoLinuxInputEvent> >("GizmoEventATIX10")
00488                 ;
00489         
00491         class_< GizmoEventPowermate, bases<GizmoEvent, GizmoLinuxInputEvent> >("GizmoEventPowermate")
00492                 .def_readonly("ClickTime", &GizmoEventPowermate::ClickTime)
00493                 ;
00494 
00496         class_< GizmoEventStandard, bases<GizmoEvent, GizmoLinuxInputEvent> >("GizmoEventStandard")
00497                 ;
00498 
00500         class_< GizmoEventSoundCard, bases<AlsaEvent, GizmoEvent> >("GizmoEventSoundCard", init<AlsaEvent const &, AlsaSoundCard const &, AlsaMixer const &>())
00501                 .def("getMixer", &GizmoEventSoundCard::getMixer, return_internal_reference<>())
00502                 .add_property("Mixer", make_function(&GizmoEventSoundCard::getMixer, return_internal_reference<>()))
00503                 .def("getSoundCard", &GizmoEventSoundCard::getSoundCard, return_internal_reference<>())
00504                 .add_property("SoundCard", make_function(&GizmoEventSoundCard::getSoundCard, return_internal_reference<>()))
00505                 ;
00506 
00508         class_< GizmoEventSoundVisualization, bases<GizmoEvent> >("GizmoEventSoundVisualization")
00509                 .def("getVULeft", &GizmoEventSoundVisualization::getVULeft)
00510                 .add_property("VULeft", &GizmoEventSoundVisualization::getVULeft)
00511                 .def("getVURight", &GizmoEventSoundVisualization::getVURight)
00512                 .add_property("VURight", &GizmoEventSoundVisualization::getVURight)
00513                 .def("getVUCombined", &GizmoEventSoundVisualization::getVUCombined)
00514                 .add_property("VUCombined", &GizmoEventSoundVisualization::getVUCombined)
00515                 .def("getType", &GizmoEventSoundVisualization::getType)
00516                 .add_property("Type", &GizmoEventSoundVisualization::getType)
00517                 ;
00518                 
00520         class_<X11FocusEvent>("X11FocusEvent", init<X11FocusEvent const &>())
00521                 .def_readonly("WindowEventType", &X11FocusEvent::EventType)
00522                 .def_readonly("WindowClass", &X11FocusEvent::WindowClass)
00523                 .def_readonly("WindowName", &X11FocusEvent::WindowName)
00524                 .def_readonly("WindowNameFormal", &X11FocusEvent::WindowNameFormal)
00525                 ;
00526                 
00528         class_< GizmoEventWindowFocus, bases<X11FocusEvent, GizmoEvent> >("GizmoEventWindowFocus", init<X11FocusEvent const &>())
00529                 ;
00530                 
00532         // Device class exports
00534         
00536         class_< GizmoATIX10, bases<Gizmo, GizmoLinuxInputDevice> >("GizmoATIX10", init<const DeviceInfo &, int, int>())
00537                 ;
00538 
00540         class_< GizmoLIRC, bases<Gizmo> >("GizmoLIRC", init<const DeviceInfo &, int, int>())
00541                 .def("setDisableFirstRepeats", &GizmoLIRC::setDisableFirstRepeats)
00542                 .def("setMinimumTimeBetweenEvents", &GizmoLIRC::setMinimumTimeBetweenEvents)
00543                 ;
00544         
00546         class_< GizmoPowermate, bases<Gizmo, GizmoLinuxInputDevice> >("GizmoPowermate", init<const DeviceInfo &, int, int>())
00547                 .def("changeLEDState", &GizmoPowermate::changeLEDState)
00548                 .def("getLED", &GizmoPowermate::getLED)
00549                 .def("getLEDPercent", &GizmoPowermate::getLEDPercent)           
00550                 .def("getLEDPulseAsleep", &GizmoPowermate::getLEDPulseAsleep)
00551                 .def("getRotated", &GizmoPowermate::getRotated)
00552                 .def("pulseLED", &GizmoPowermate::pulseLED)
00553                 .def("setLED", &GizmoPowermate::setLED)
00554                 .def("setLEDPercent", &GizmoPowermate::setLEDPercent)
00555                 .def("setLEDPulseAsleep", &GizmoPowermate::setLEDPulseAsleep)
00556                 .def("setRotateSensitivity", &GizmoPowermate::setRotateSensitivity)
00557                 .add_property("LED", &GizmoPowermate::getLED, &GizmoPowermate::setLED)
00558                 .add_property("LEDPercent", &GizmoPowermate::getLEDPercent, &GizmoPowermate::setLEDPercent)
00559                 .add_property("LEDPulseAsleep", &GizmoPowermate::getLEDPulseAsleep, &GizmoPowermate::setLEDPulseAsleep)
00560                 .add_property("Rotated", &GizmoPowermate::getRotated)
00561                 .add_property("RotateSensitivity", &GizmoPowermate::setRotateSensitivity)
00562                 ;
00563 
00565         class_< GizmoStandard, bases<Gizmo, GizmoLinuxInputDevice> >("GizmoStandard", init<const DeviceInfo &, int, int>())
00566                 ;
00567 }
00568 
00570 // Construction
00572 
00576 GizmoDaemon::GizmoDaemon() {
00577         cout << getProps();
00578         
00579         setConfigDir();
00580         mClientHost = "";
00581         mClientPort = DEFAULT_PORT;
00582         mDisabledALSA = false;
00583         mDisabledCPUUsage = false;
00584         mDisabledX11 = false;
00585         mDisableShutdownMessage = false;
00586         mEventsDir = EVENT_NODE_DIR;
00587         mInitialized = false;
00588         mLircDev = LIRC_DEV;
00589         mLocalDisabled = false;
00590         mpPyDispatcher = NULL;
00591         mReloadConfig = false;
00592         mServerPort = DEFAULT_PORT;
00593         mServerEnabled = false;
00594         mShuttingDown = false;
00595         mUseKeyboardLEDs = false;
00596         mUseRemoteControl = false;
00597         mVersion = 0.0;
00598         setVersionInfo();
00599 }
00600 
00604 GizmoDaemon::~GizmoDaemon() {
00605         if (!mDisableShutdownMessage)
00606                 cout << "GizmoDaemon Shutting Down... ";
00607         mShuttingDown = true;   
00608                                         if (!mDisableShutdownMessage) cout << "|"; flush(cout);
00609         X11FocusWatcher::shutdown();    if (!mDisableShutdownMessage) cout << "\b/"; flush(cout);
00610         Alsa::shutdown();               if (!mDisableShutdownMessage) cout << "\b-"; flush(cout);
00611         CPUUsage::shutdown();           if (!mDisableShutdownMessage) cout << "\b\\"; flush(cout);
00612         SocketServer::shutdown();       if (!mDisableShutdownMessage) cout << "\b|"; flush(cout);
00613         Py_Finalize();
00614         Py_Initialize();
00615         if (!mDisableShutdownMessage) 
00616                 cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b Down.                  " << endl << endl;
00617 }
00618 
00620 // Class Body
00622 
00629 bool GizmoDaemon::checkVersion(double Version, bool Strict) {
00630         double VersionDiff = fabs(Version - mVersion);
00631         if (Strict) {
00632                 return VersionDiff < 0.1;
00633         } else {
00634                 if (Version - 0.05 <= mVersion)
00635                         return true;
00636                 else
00637                         return false;
00638         }
00639 }
00640 
00645 void GizmoDaemon::deleteGizmo(std::string FileName) {
00646         if (mShuttingDown)
00647                 return;
00648         
00649         // remove from map
00650         if (!mGizmos.count(FileName)) {
00651                 // not found -- unusual, but whatever
00652                 cdbg << "Tried to delete non-existent Gizmo [" << FileName << "]" << endl;
00653                 return; 
00654         }
00655                 
00656         // get the Gizmo
00657         shared_ptr<Gizmo> pGizmo = mGizmos[FileName];
00658         
00659         // signal python script
00660         try {
00661                 mutex::scoped_lock lock(mMutexScript);
00662                 switch (pGizmo->getClass()) {
00663                 case GIZMO_CLASS_ATIX10:
00664                         mpPyDispatcher->onDeregisterDevice(static_cast<GizmoATIX10 const *>(pGizmo.get()));
00665                         break;
00666                 case GIZMO_CLASS_LIRC:
00667                         mpPyDispatcher->onDeregisterDevice(static_cast<GizmoLIRC const *>(pGizmo.get()));
00668                         break;
00669                 case GIZMO_CLASS_POWERMATE: 
00670                         mpPyDispatcher->onDeregisterDevice(static_cast<GizmoPowermate const *>(pGizmo.get()));
00671                         break; 
00672                 case GIZMO_CLASS_STANDARD:
00673                         mpPyDispatcher->onDeregisterDevice(static_cast<GizmoStandard const *>(pGizmo.get()));
00674                         break;
00675                 }               
00676         } catch (error_already_set) {
00677                 PyErr_Print();
00678                 throw H::Exception("Failed to call GizmodDispatcher.onEvent for deleteGizmo", __FILE__, __FUNCTION__, __LINE__);
00679         }
00680                 
00681         // remove the gizmo
00682         mGizmos.erase(FileName);
00683         cdbg2 << "Deleted Gizmo [" << FileName << "]" << endl;
00684 }
00685 
00691 void GizmoDaemon::deserializeMessage(GizmoEventClass EventClass, std::string const & Message) { 
00692         switch (EventClass) {
00693         case GIZMO_EVENTCLASS_ATIX10:
00694                 deserializeMessageATIX10(Message);
00695                 break;
00696         case GIZMO_EVENTCLASS_CPUUSAGE:
00697                 deserializeMessageCPUUsage(Message);
00698                 break;
00699         case GIZMO_EVENTCLASS_LIRC:
00700                 deserializeMessageLIRC(Message);
00701                 break;
00702         case GIZMO_EVENTCLASS_POWERMATE:
00703                 deserializeMessagePowermate(Message);
00704                 break;
00705         case GIZMO_EVENTCLASS_SOUNDCARD:
00706                 deserializeMessageSoundcard(Message);
00707                 break;
00708         case GIZMO_EVENTCLASS_SOUNDVISUALIZATION:
00709                 deserializeMessageSoundVisualization(Message);
00710                 break;
00711         case GIZMO_EVENTCLASS_STANDARD:
00712                 deserializeMessageStandard(Message);
00713                 break;
00714         case GIZMO_EVENTCLASS_WINDOWFOCUS:
00715                 deserializeMessageWindowFocus(Message);
00716                 break;
00717         }
00718 }
00719 
00724 void GizmoDaemon::deserializeMessageATIX10(std::string const & Message) {       
00725         // separate the two components of the message
00726         size_t SepPos = Message.find("|");
00727         if (SepPos == string::npos) {
00728                 cdbg << "Could not deserialize LIRC message -- invalid format" << endl;
00729                 return;
00730         }
00731         string MessageEvent = Message.substr(0, SepPos);
00732         string MessageDevice = Message.substr(SepPos + 1);
00733 
00734         // deserialize
00735         stringstream InStreamEvent(MessageEvent);
00736         archive::text_iarchive InArchiveEvent(InStreamEvent);
00737         GizmoEventATIX10 Event;
00738         InArchiveEvent >> Event;
00739         Event.setIsRemote(true);
00740         
00741         stringstream InStreamDevice(MessageDevice);
00742         archive::text_iarchive InArchiveDevice(InStreamDevice);
00743         GizmoATIX10 Gizmo;
00744         InArchiveDevice >> Gizmo;
00745         
00746         // process the remote event             
00747         if (!mLocalDisabled) {
00748                 try {
00749                         mutex::scoped_lock lock(mMutexScript);
00750                         mpPyDispatcher->onEvent(&Event, &Gizmo);
00751                 } catch (error_already_set) {
00752                         PyErr_Print();
00753                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
00754                 }
00755         }
00756 }
00757 
00762 void GizmoDaemon::deserializeMessageCPUUsage(std::string const & Message) {     
00763         // deserialize
00764         stringstream InStream(Message);
00765         archive::text_iarchive InArchive(InStream);
00766         GizmoEventCPUUsage Event;
00767         InArchive >> Event;
00768         Event.setIsRemote(true);
00769         
00770         // process the remote event             
00771         if (!mLocalDisabled) {
00772                 try {
00773                         mutex::scoped_lock lock(mMutexScript);
00774                         mpPyDispatcher->onEvent(&Event);
00775                 } catch (error_already_set) {
00776                         PyErr_Print();
00777                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
00778                 }
00779         }
00780 }
00781 
00786 void GizmoDaemon::deserializeMessageLIRC(std::string const & Message) { 
00787         // separate the two components of the message
00788         size_t SepPos = Message.find("|");
00789         if (SepPos == string::npos) {
00790                 cdbg << "Could not deserialize LIRC message -- invalid format" << endl;
00791                 return;
00792         }
00793         string MessageEvent = Message.substr(0, SepPos);
00794         string MessageDevice = Message.substr(SepPos + 1);
00795 
00796         // deserialize
00797         stringstream InStreamEvent(MessageEvent);
00798         archive::text_iarchive InArchiveEvent(InStreamEvent);
00799         GizmoEventLIRC Event;
00800         InArchiveEvent >> Event;
00801         Event.setIsRemote(true);
00802         
00803         stringstream InStreamDevice(MessageDevice);
00804         archive::text_iarchive InArchiveDevice(InStreamDevice);
00805         GizmoLIRC Gizmo;
00806         InArchiveDevice >> Gizmo;
00807         
00808         // process the remote event             
00809         if (!mLocalDisabled) {
00810                 try {
00811                         mutex::scoped_lock lock(mMutexScript);
00812                         mpPyDispatcher->onEvent(&Event, &Gizmo);
00813                 } catch (error_already_set) {
00814                         PyErr_Print();
00815                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
00816                 }
00817         }
00818 }
00819 
00824 void GizmoDaemon::deserializeMessagePowermate(std::string const & Message) {    
00825         // separate the two components of the message
00826         size_t SepPos = Message.find("|");
00827         if (SepPos == string::npos) {
00828                 cdbg << "Could not deserialize LIRC message -- invalid format" << endl;
00829                 return;
00830         }
00831         string MessageEvent = Message.substr(0, SepPos);
00832         string MessageDevice = Message.substr(SepPos + 1);
00833 
00834         // deserialize
00835         stringstream InStreamEvent(MessageEvent);
00836         archive::text_iarchive InArchiveEvent(InStreamEvent);
00837         GizmoEventPowermate Event;
00838         InArchiveEvent >> Event;
00839         Event.setIsRemote(true);
00840         
00841         stringstream InStreamDevice(MessageDevice);
00842         archive::text_iarchive InArchiveDevice(InStreamDevice);
00843         GizmoPowermate Gizmo;
00844         InArchiveDevice >> Gizmo;
00845         
00846         // process the remote event             
00847         if (!mLocalDisabled) {
00848                 try {
00849                         mutex::scoped_lock lock(mMutexScript);
00850                         mpPyDispatcher->onEvent(&Event, &Gizmo);
00851                 } catch (error_already_set) {
00852                         PyErr_Print();
00853                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
00854                 }
00855         }
00856 }
00857 
00862 void GizmoDaemon::deserializeMessageSoundcard(std::string const & Message) {    
00863         // deserialize
00864         stringstream InStream(Message);
00865         archive::text_iarchive InArchive(InStream);
00866         GizmoEventSoundCard Event;
00867         InArchive >> Event;
00868         Event.setIsRemote(true);
00869         
00870         // process the remote event             
00871         if (!mLocalDisabled) {
00872                 try {
00873                         mutex::scoped_lock lock(mMutexScript);
00874                         mpPyDispatcher->onEvent(&Event);
00875                 } catch (error_already_set) {
00876                         PyErr_Print();
00877                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
00878                 }
00879         }
00880 }
00881 
00886 void GizmoDaemon::deserializeMessageSoundVisualization(std::string const & Message) {   
00887         // deserialize
00888         stringstream InStream(Message);
00889         archive::text_iarchive InArchive(InStream);
00890         GizmoEventSoundVisualization Event;
00891         InArchive >> Event;
00892         Event.setIsRemote(true);
00893         
00894         // process the remote event             
00895         if (!mLocalDisabled) {
00896                 try {
00897                         mutex::scoped_lock lock(mMutexScript);
00898                         mpPyDispatcher->onEvent(&Event);
00899                 } catch (error_already_set) {
00900                         PyErr_Print();
00901                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
00902                 }
00903         }
00904 }
00905 
00910 void GizmoDaemon::deserializeMessageStandard(std::string const & Message) {     
00911         // separate the two components of the message
00912         size_t SepPos = Message.find("|");
00913         if (SepPos == string::npos) {
00914                 cdbg << "Could not deserialize LIRC message -- invalid format" << endl;
00915                 return;
00916         }
00917         string MessageEvent = Message.substr(0, SepPos);
00918         string MessageDevice = Message.substr(SepPos + 1);
00919 
00920         // deserialize
00921         stringstream InStreamEvent(MessageEvent);
00922         archive::text_iarchive InArchiveEvent(InStreamEvent);
00923         GizmoEventStandard Event;
00924         InArchiveEvent >> Event;
00925         Event.setIsRemote(true);
00926         
00927         stringstream InStreamDevice(MessageDevice);
00928         archive::text_iarchive InArchiveDevice(InStreamDevice);
00929         GizmoStandard Gizmo;
00930         InArchiveDevice >> Gizmo;
00931         
00932         // process the remote event             
00933         if (!mLocalDisabled) {
00934                 try {
00935                         mutex::scoped_lock lock(mMutexScript);
00936                         mpPyDispatcher->onEvent(&Event, &Gizmo);
00937                 } catch (error_already_set) {
00938                         PyErr_Print();
00939                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
00940                 }
00941         }
00942 }
00943 
00948 void GizmoDaemon::deserializeMessageWindowFocus(std::string const & Message) {  
00949         // deserialize
00950         stringstream InStream(Message);
00951         archive::text_iarchive InArchive(InStream);
00952         GizmoEventWindowFocus Event;
00953         InArchive >> Event;
00954         Event.setIsRemote(true);
00955         
00956         // process the remote event             
00957         if (!mLocalDisabled) {
00958                 try {
00959                         mutex::scoped_lock lock(mMutexScript);
00960                         mpPyDispatcher->onEvent(&Event);
00961                 } catch (error_already_set) {
00962                         PyErr_Print();
00963                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
00964                 }
00965         }
00966 }
00967 
00971 void GizmoDaemon::enterLoop() {
00972         if (mShuttingDown)
00973                 return;
00974         if (!mInitialized)
00975                 throw H::Exception("You must initialize GizmoDaemon first!", __FILE__, __FUNCTION__, __LINE__);
00976         
00977         watchForFileEvents();
00978 }
00979 
00987 X11FocusEvent GizmoDaemon::getCurrentFocus() {
00988         return mCurrentFocus;
00989 }
00990 
00998 bool GizmoDaemon::getDebugEnabled() {
00999         return Debug::getEnabled();
01000 }
01001 
01006 GizmodEventHandlerInterface * GizmoDaemon::getDispatcher() {
01007         return mpPyDispatcher;
01008 }
01009 
01015 boost::shared_ptr<Gizmo> GizmoDaemon::getGizmoByFileName(std::string FileName) {
01016         return mGizmos[FileName];
01017 }
01018 
01024 int GizmoDaemon::getNumGizmosByClass(GizmoClass Class) {
01025         int Count = 0;
01026         for (map< string, shared_ptr<Gizmo> >::iterator iter = mGizmos.begin(); iter != mGizmos.end(); iter ++) {
01027                 shared_ptr<Gizmo> pGizmo = iter->second;
01028                 if ( (pGizmo.get() != NULL) && (pGizmo->getClass() == Class) )
01029                         Count ++;
01030         }
01031         return Count;
01032 }
01033 
01039 int GizmoDaemon::getGizmoClassID(GizmoClass Class) {
01040         vector<bool> IDs;
01041         int tot = getNumGizmosByClass(Class);
01042         IDs.resize(tot + 1, false);
01043         
01044         for (map< string, shared_ptr<Gizmo> >::iterator iter = mGizmos.begin(); iter != mGizmos.end(); iter ++) {
01045                 shared_ptr<Gizmo> pGizmo = iter->second;
01046                 if ( (pGizmo.get() != NULL) && (pGizmo->getClass() == Class) )
01047                         IDs[pGizmo->getDeviceClassID()] = true;
01048         }
01049         
01050         for (size_t lp = 0; lp < IDs.size(); lp ++) {           
01051                 if (!IDs[lp])
01052                         return lp;
01053         }
01054 
01055         return tot;
01056 }
01057 
01061 string GizmoDaemon::getProps() {
01062         return "\nGizmoDaemon v" VERSION " -=- (c) 2007, Tim Burrell <tim.burrell@gmail.com>\n=---------=\n";
01063 }
01064 
01069 bool GizmoDaemon::getReloadConfig() {
01070         return mReloadConfig;
01071 }
01072 
01077 bool GizmoDaemon::getUseKeyboardLEDs() {
01078         return mUseKeyboardLEDs;
01079 }
01080 
01085 bool GizmoDaemon::getUseRemoteControl() {
01086         return mUseRemoteControl;
01087 }
01088 
01096 std::string GizmoDaemon::getUserScriptDirPaths() {
01097         string ret;
01098         string UserScriptDir = mConfigDir + USER_SCRIPT_DIR;
01099         cdbg1 << "Adding [" << UserScriptDir << "] to the System Path" << endl;
01100         path UserScriptPath(UserScriptDir);
01101         if (!filesystem::exists(UserScriptPath))
01102                 throw H::Exception("User Script dir [" + UserScriptDir + "] does NOT exist or permissions are wrong!", __FILE__, __FUNCTION__, __LINE__);
01103                 
01104         // now register the event nodes
01105         // get a file listing
01106         directory_iterator endItr;
01107         for (directory_iterator iter(UserScriptDir); iter != endItr; iter ++) {
01108                 if (filesystem::is_directory(*iter))
01109                         ret += "sys.path.insert(0, \"" + iter->string() + "\")\n";
01110         }
01111         
01112         return ret;
01113 }
01114 
01121 double GizmoDaemon::getVersion() {
01122         return mVersion;
01123 }
01124 
01130 void GizmoDaemon::handleFileEventReadATIX10(GizmoATIX10 & Gizmo, DynamicBuffer<char> const & ReadBuffer) {
01131         std::vector< boost::shared_ptr<GizmoEventATIX10> > EventVector;
01132         GizmoEventATIX10::buildEventsVectorFromBuffer(EventVector, ReadBuffer, Gizmo.getSendNullEvents());
01133         for (size_t lp = 0; lp < EventVector.size(); lp ++) {
01134                 if (Gizmo.processEvent(EventVector[lp].get()))
01135                         if (!mLocalDisabled) {
01136                                 try {
01137                                         mutex::scoped_lock lock(mMutexScript);
01138                                         mpPyDispatcher->onEvent(EventVector[lp].get(), &Gizmo);
01139                                 } catch (error_already_set) {
01140                                         PyErr_Print();
01141                                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
01142                                 }
01143                         }
01144         
01145                         // try to send the remote event
01146                         try {
01147                                 sendEventATIX10(static_cast<GizmoEventATIX10 const &>(*EventVector[lp]), static_cast<GizmoATIX10 const &>(Gizmo));
01148                         } catch (SocketException const & e) {
01149                                 cdbg << "Failed to send LIRC Message to Server -- " << e.getExceptionMessage() << endl;
01150                         }
01151         }
01152 }
01153 
01159 void GizmoDaemon::handleFileEventReadLIRC(GizmoLIRC & Gizmo, DynamicBuffer<char> const & ReadBuffer) {
01160         std::vector< boost::shared_ptr<GizmoEventLIRC> > EventVector;
01161         GizmoEventLIRC::buildEventsVectorFromBuffer(EventVector, ReadBuffer);
01162         for (size_t lp = 0; lp < EventVector.size(); lp ++) {
01163                 if (Gizmo.processEvent(EventVector[lp].get())) {
01164                         // process the local event
01165                         if (!mLocalDisabled) {
01166                                 try {
01167                                         mutex::scoped_lock lock(mMutexScript);
01168                                         mpPyDispatcher->onEvent(EventVector[lp].get(), &Gizmo);
01169                                 } catch (error_already_set) {
01170                                         PyErr_Print();
01171                                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
01172                                 }
01173                         }
01174                         
01175                         // try to send the remote event
01176                         try {
01177                                 sendEventLIRC(static_cast<GizmoEventLIRC const &>(*EventVector[lp]), static_cast<GizmoLIRC const &>(Gizmo));
01178                         } catch (SocketException const & e) {
01179                                 cdbg << "Failed to send LIRC Message to Server -- " << e.getExceptionMessage() << endl;
01180                         }
01181                 }
01182         }
01183 }
01184 
01190 void GizmoDaemon::handleFileEventReadPowermate(GizmoPowermate & Gizmo, DynamicBuffer<char> const & ReadBuffer) {
01191         std::vector< boost::shared_ptr<GizmoEventPowermate> > EventVector;
01192         GizmoEventPowermate::buildEventsVectorFromBuffer(EventVector, ReadBuffer, Gizmo.getSendNullEvents());
01193         for (size_t lp = 0; lp < EventVector.size(); lp ++) {
01194                 if (Gizmo.processEvent(EventVector[lp].get()))
01195                         if (!mLocalDisabled) {
01196                                 try {
01197                                         mutex::scoped_lock lock(mMutexScript);
01198                                         mpPyDispatcher->onEvent(EventVector[lp].get(), &Gizmo);
01199                                 } catch (error_already_set) {
01200                                         PyErr_Print();
01201                                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
01202                                 }
01203                         }
01204         
01205                         // try to send the remote event
01206                         try {
01207                                 sendEventPowermate(static_cast<GizmoEventPowermate const &>(*EventVector[lp]), static_cast<GizmoPowermate const &>(Gizmo));
01208                         } catch (SocketException const & e) {
01209                                 cdbg << "Failed to send LIRC Message to Server -- " << e.getExceptionMessage() << endl;
01210                         }
01211         }
01212 }
01213 
01219 void GizmoDaemon::handleFileEventReadStandard(GizmoStandard & Gizmo, DynamicBuffer<char> const & ReadBuffer) {
01220         std::vector< boost::shared_ptr<GizmoEventStandard> > EventVector;
01221         GizmoEventStandard::buildEventsVectorFromBuffer(EventVector, ReadBuffer, Gizmo.getSendNullEvents());
01222         for (size_t lp = 0; lp < EventVector.size(); lp ++) {
01223                 if (Gizmo.processEvent(EventVector[lp].get()))
01224                         if (!mLocalDisabled) {
01225                                 try {
01226                                         mutex::scoped_lock lock(mMutexScript);
01227                                         mpPyDispatcher->onEvent(EventVector[lp].get(), &Gizmo);
01228                                 } catch (error_already_set) {
01229                                         PyErr_Print();
01230                                         cerr << "Failed to call GizmodDispatcher.onEvent for deserializeMessage" << endl;
01231                                 }
01232                         }
01233                 
01234                         // try to send the remote event
01235                         try {
01236                                 sendEventStandard(static_cast<GizmoEventStandard const &>(*EventVector[lp]), static_cast<GizmoStandard const &>(Gizmo));
01237                         } catch (SocketException const & e) {
01238                                 cdbg << "Failed to send LIRC Message to Server -- " << e.getExceptionMessage() << endl;
01239                         }
01240         }
01241 }
01242 
01248 void GizmoDaemon::initGizmod() {
01249         if (mInitialized)
01250                 return;
01251         
01252         // initialize signals
01253         initSignals();
01254                 
01255         // init python
01256         try {
01257                 initPython();
01258                 if (mShuttingDown)
01259                         return;
01260         } catch (H::Exception & e) {
01261                 throw e;
01262         } catch (exception & e) {
01263                 throw H::Exception("Failed to Initialize Python!", __FILE__, __FUNCTION__, __LINE__);
01264         }
01265         
01266         // initialize the client
01267         if (mClientHost != "") {
01268                 try {
01269                         cout << "Connecting to [" << mClientHost << "] at Port [" << mClientPort << "]..." << endl;
01270                         connectToServer(mClientHost, mClientPort);
01271                         if (mShuttingDown)
01272                                 return;
01273                 } catch (SocketException const & e) {
01274                         throw H::Exception(e.getExceptionMessage(), __FILE__, __FUNCTION__, __LINE__);
01275                 }
01276         }
01277         
01278         // register all the devices
01279         try {
01280                 registerDevices();
01281                 if (mShuttingDown)
01282                         return;
01283         } catch (H::Exception & e) {
01284                 throw e;
01285         }
01286         
01287         // load the user scripts
01288         try {
01289                 loadUserScripts();
01290                 if (mShuttingDown)
01291                         return;
01292         } catch (H::Exception & e) {
01293                 throw e;
01294         }
01295         
01296         // initialize the server
01297         if (mServerEnabled) {
01298                 try {
01299                         acceptConnections(mServerPort);
01300                 } catch (SocketException const & e) {
01301                         throw H::Exception("Failed to Start Server -- " + e.getExceptionMessage(), __FILE__, __FUNCTION__, __LINE__);
01302                 }
01303         }
01304                                 
01305         // init the X11FocusWatcher
01306         if (!mDisabledX11)
01307                 X11FocusWatcher::init();
01308         
01309         // init the CPU Usage watcher
01310         if (!mDisabledCPUUsage)
01311                 CPUUsage::init();
01312         
01313         // init Alsa
01314         if (!mDisabledALSA) {
01315                 try {
01316                         Alsa::init();
01317                 } catch (H::Exception & e) {
01318                         cerr << e.getExceptionMessage() << endl;
01319                 }
01320         }
01321                 
01322         // success
01323         mInitialized = true;
01324 }
01325 
01329 void GizmoDaemon::initPython() {
01330         try {
01331                 cdbg1 << "Embedding Python Interpreter..." << endl;
01332                 PyImport_AppendInittab("GizmoDaemon", &initGizmoDaemon);
01333                 
01334                 // initialize python and threads
01335                 Py_Initialize();
01336                 
01337                 cdbg1 << "Initializing Python Environment..." << endl;
01338                 mPyMainModule = object((handle<>(borrowed(PyImport_AddModule("__main__")))));
01339                 mPyMainNamespace = mPyMainModule.attr("__dict__");
01340                 
01341                 // add Gizmo Daemon module automatically to the namespace
01342                 object GizmoDaemonModule( (handle<>(PyImport_ImportModule("GizmoDaemon"))) );
01343                 mPyMainNamespace["GizmoDaemon"] = GizmoDaemonModule;
01344                 
01345                 // create a new object so the script can access this object
01346                 scope(GizmoDaemonModule).attr("Gizmod") = ptr(this);
01347                 
01348                 // Modify the PYTHONPATH so import's work
01349                 string PathInsertion = 
01350                         "import sys\nsys.path.insert(0, \"" + mConfigDir + "\")\n" +
01351                         "sys.path.insert(0, \"" + mConfigDir + USER_SCRIPT_DIR + "/\")\n" +
01352                         getUserScriptDirPaths();
01353                 cdbg1 << "Modifying PYTHONPATH:\n" << PathInsertion << endl;
01354                 handle<> ignore_path_exec((PyRun_String(
01355                         PathInsertion.c_str(),
01356                         Py_file_input, mPyMainNamespace.ptr(), mPyMainNamespace.ptr())));
01357                 
01358                 // execute the main script code
01359                 string ScriptFile = mConfigDir + SCRIPT_DISPATCHER;
01360                 cdbg1 << "Executing Dispatcher Python Script [" << ScriptFile << "]..." << endl;
01361                 FILE * ifScript = fopen(ScriptFile.c_str(), "r");
01362                 if (!ifScript)
01363                         throw H::Exception("Failed to Open Python Script [" + ScriptFile + "] for Reading", __FILE__, __FUNCTION__, __LINE__);
01364                 PyRun_SimpleFile(ifScript, ScriptFile.c_str());
01365                 fclose(ifScript);
01366                 
01367                 // Create the event dispatcher object so we can interact with it
01368                 cdbg1 << "Creating Dispatcher Object" << endl;
01369                 handle<> ignore_dispatcher_exec((PyRun_String(
01370                         "Dispatcher = GizmodDispatcher()\nGizmod.Dispatcher = Dispatcher\n",
01371                         Py_file_input, mPyMainNamespace.ptr(), mPyMainNamespace.ptr())));
01372                 
01373                 // Grab the event dispatcher object so we can interact with it
01374                 mpPyDispatcher = extract<GizmodEventHandlerInterface*>(mPyMainNamespace["Dispatcher"]);
01375                 
01376                 // Initialize the dispatcher object
01377                 mpPyDispatcher->initialize();
01378                                                         
01379                 // execute the user script code
01380                 ScriptFile = mConfigDir + SCRIPT_USER;
01381                 cdbg1 << "Executing User Python Script [" << ScriptFile << "]..." << endl;
01382                 ifScript = fopen(ScriptFile.c_str(), "r");
01383                 if (!ifScript)
01384                         throw H::Exception("Failed to Open Python Script [" + ScriptFile + "] for Reading", __FILE__, __FUNCTION__, __LINE__);
01385                 PyRun_SimpleFile(ifScript, ScriptFile.c_str());
01386                 fclose(ifScript);
01387         } catch (error_already_set) {
01388                 PyErr_Print();
01389                 throw H::Exception("Failed to Execute Python Script!", __FILE__, __FUNCTION__, __LINE__);
01390         }
01391 }
01392 
01401 bool GizmoDaemon::initialize(int argc, char ** argv) {
01402         // generic options
01403         options_description GenericOptions("Generic Options");
01404         GenericOptions.add_options()
01405                 ("debug,g",                                     "Enable debug mode")
01406                 ("help,h",                                      "Display informative help message")
01407                 ("verbosity,V",         value<int>(),           "Set debug vebosity level (0-5) [Default = 0]")
01408                 ("version,v",                                   "Print version information")
01409                 ;
01410                                 
01411         // config file options that can be loaded via command line as well
01412         options_description ConfigurationOptions("Configuration Options");
01413         ConfigurationOptions.add_options()
01414                 ("client-host,c",       value<string>(),        "Enable event forwarding to a remote host")
01415                 ("client-port,P",       value<int>(),           "Port to forward events to (default: " DEFAULT_PORT_STR ")")
01416                 ("config-dir,C",        value<string>(),        "Set config scripts directory") 
01417                 ("events-dir,e",        value<string>(),        "Set event node directory (default: " EVENT_NODE_DIR ")")
01418                 ("keyboard-leds,k",                             "Allow Gizmod to Visualize on the Keyboard LEDs")
01419                 ("lirc-dev,l",          value<string>(),        "Set LIRC device node (default: " LIRC_DEV ")")
01420                 ("no-alsa,A",                                   "Disable ALSA support")
01421                 ("no-cpuusage,U",                               "Disable CPU Usage reporting")
01422                 ("no-local,N",                                  "Disable local processing of events")
01423                 ("no-x11,X",                                    "Disable X11 support")
01424                 ("remote-control,r",                            "Enable Remote Control mode")
01425                 ("server,s",                                    "Enable server (default: not enabled)")
01426                 ("server-port,p",       value<int>(),           "Port to start Gizmod server on (default: " DEFAULT_PORT_STR ")")
01427                 ;
01428         
01429         // hiGizmoDaemonn options
01430         options_description HiddenOptions("Hidden Options");
01431         HiddenOptions.add_options();
01432        
01433         // create command line options group
01434         options_description CommandLineOptions;
01435         CommandLineOptions.add(GenericOptions).add(ConfigurationOptions).add(HiddenOptions);
01436 
01437         // create config file options group
01438         options_description ConfigFileOptions;
01439         ConfigFileOptions.add(ConfigurationOptions).add(HiddenOptions);
01440         
01441         // create a visible options group for help display
01442         options_description VisibleOptions("");
01443         VisibleOptions.add(GenericOptions).add(ConfigurationOptions);
01444         
01445         // create the variables map
01446         variables_map VarMap;
01447         
01448         // try parsing the command line
01449         try {
01450                 store(parse_command_line(argc, argv, CommandLineOptions), VarMap);
01451         } catch (exception & e) {
01452                 cout << VisibleOptions;
01453                 throw H::Exception("Invalid Command Line Argument(s)");
01454         }
01455 
01456         // try parsing the config file
01457         try {
01458                 string ConfigFile = CONFIG_FILE_PATH;
01459                 UtilFile::relativeToAbsolute(ConfigFile);
01460                 ifstream ifs(ConfigFile.c_str());
01461                 if (ifs.is_open())
01462                         store(parse_config_file(ifs, ConfigFileOptions), VarMap);
01463         } catch (exception & e) {
01464                 cout << VisibleOptions;
01465                 throw H::Exception("Invalid Configuration File");
01466         }
01467         
01468         // build the option map
01469         notify(VarMap);
01470 
01471         // check for options
01472         if (VarMap.count("help")) {
01473                 cout << VisibleOptions << endl;
01474                 mDisableShutdownMessage = true;
01475                 return false;
01476         }
01477         if (VarMap.count("version")) {
01478                 cout << endl;
01479                 mDisableShutdownMessage = true;
01480                 return false;
01481         }
01482         if (VarMap.count("debug")) {
01483                 Debug::setEnabled(true);        
01484                 cdbg << "Debug Mode Enabled" << endl;
01485         }
01486         if (VarMap.count("verbosity")) {
01487                 Debug::setVerbosity(VarMap["verbosity"].as<int>());
01488                 cdbg << "Debug Verbosity set to [" << VarMap["verbosity"].as<int>() << "]" << endl;
01489         }
01490         if (VarMap.count("client-host")) {
01491                 mClientHost = VarMap["client-host"].as<string>();
01492                 cdbg << "Client Forwarding to [" << mClientHost << "]" << endl;
01493         }
01494         if (VarMap.count("client-port")) {
01495                 mClientPort = VarMap["client-port"].as<int>();
01496                 cdbg << "Client port set to [" << mClientPort << "]" << endl;
01497         }
01498         if (VarMap.count("config-dir")) {
01499                 mConfigDir = VarMap["config-dir"].as<string>();
01500                 if (mConfigDir[mConfigDir.length() - 1] != '/')
01501                         mConfigDir += "/";
01502                 cdbg << "Config Scripts Directory set to [" << mConfigDir << "]" << endl;
01503         }
01504         if (VarMap.count("events-dir")) {
01505                 mEventsDir = VarMap["events-dir"].as<string>();
01506                 if (mEventsDir[mEventsDir.length() - 1] != '/')
01507                         mEventsDir += "/";
01508                 cdbg << "Event Node Directory set to [" << mEventsDir << "]" << endl;
01509         }
01510         if (VarMap.count("keyboard-leds")) {
01511                 cdbg << "Allowing takeover of Keyboard LEDs" << endl;
01512                 mUseKeyboardLEDs = true;
01513         }       
01514         if (VarMap.count("lirc-dev")) {
01515                 mLircDev = VarMap["lirc-dev"].as<string>();
01516                 cdbg << "LIRC Device Node set to [" << mLircDev << "]" << endl;
01517         }
01518         if (VarMap.count("no-alsa")) {
01519                 mDisabledALSA = true;
01520                 cdbg << "ALSA Support Disabled" << endl;
01521         }
01522         if (VarMap.count("no-cpuusage")) {
01523                 mDisabledCPUUsage = true;
01524                 cdbg << "CPU Usage Reporting Disabled" << endl;
01525         }
01526         if (VarMap.count("no-local")) {
01527                 mLocalDisabled = true;
01528                 cdbg << "Local Event Processing Disabled" << endl;
01529         }
01530         if (VarMap.count("no-x11")) {
01531                 mDisabledX11 = true;
01532                 cdbg << "X11 Support Disabled" << endl;
01533         }
01534         if (VarMap.count("remote-control")) {
01535                 mUseRemoteControl = true;
01536                 cdbg << "Remote Control Mode Enabled" << endl;
01537         }
01538         if (VarMap.count("server")) {
01539                 mServerEnabled = !mServerEnabled;
01540                 cdbg << "Gizmod Server Enabled" << endl;
01541         }
01542         if (VarMap.count("server-port")) {
01543                 mServerPort = VarMap["server-port"].as<int>();
01544                 cdbg << "Sever port set to [" << mServerPort << "]" << endl;
01545         }
01546 
01547         cout << endl;
01548         return true;
01549 }
01550 
01554 void GizmoDaemon::loadUserScripts() {
01555         cout << "Loading User Scripts:" << endl << endl;
01556         
01557         path UserScriptPath(mConfigDir + USER_SCRIPT_DIR);
01558         if (!filesystem::exists(UserScriptPath))
01559                 throw H::Exception("User script directory [" + mConfigDir + USER_SCRIPT_DIR + "] does NOT exist or permissions are wrong!", __FILE__, __FUNCTION__, __LINE__);
01560                 
01561         // now register the event nodes
01562         // get a file listing
01563         std::vector<string> UserScripts;
01564         directory_iterator endItr;
01565         for (directory_iterator iter(mConfigDir + USER_SCRIPT_DIR); iter != endItr; iter ++) {
01566                 if ( (!filesystem::is_directory(*iter)) && (!filesystem::symbolic_link_exists(*iter)) ) {
01567                         UserScripts.push_back(iter->leaf());
01568                 }
01569         }
01570         
01571         // sort the list of input event nodes
01572         sort_all(UserScripts);
01573         
01574         // load the user scripts (and lock the mutex)
01575         mutex::scoped_lock lock(mMutexScript);
01576         apply_func(UserScripts, &GizmoDaemon::loadUserScriptsFunctor, this);
01577         cout << endl;
01578 }
01579 
01584 void GizmoDaemon::loadUserScriptsFunctor(std::string UserScript) {
01585         // Note: Mutex is already locked!
01586         
01587         // make sure it's a python script, and remove extension
01588         size_t dotPos = UserScript.rfind(".py");
01589         if ( (dotPos == string::npos) || (dotPos != UserScript.length() - 3) )
01590                 return;
01591         UserScript = UserScript.substr(0, dotPos);
01592         cdbg1 << "Importing User Script [" << UserScript << "]" << endl;
01593         
01594         // Import the module
01595         try {
01596                 string ImportModuleString = "__import__(\"" + UserScript + "\")\n";
01597                 cdbg2 << "Executing Python Code: " << ImportModuleString << endl;
01598                 handle<> ignore_path_exec((PyRun_String(
01599                         ImportModuleString.c_str(),
01600                         Py_file_input, mPyMainNamespace.ptr(), mPyMainNamespace.ptr())));
01601         } catch (error_already_set) {
01602                 PyErr_Print();
01603                 throw H::Exception("Failed to Load User Script [" + UserScript + "]", __FILE__, __FUNCTION__, __LINE__);
01604         }
01605 }
01606 
01614 void GizmoDaemon::printNiceScriptInit(int Width, std::string Text1, std::string Text2, std::string Text3) {
01615         replace_all(Text1, "\n", ""); 
01616         replace_all(Text2, "\n", ""); 
01617         replace_all(Text3, "\n", "");
01618         trim(Text1); 
01619         trim(Text2); 
01620         trim(Text3);
01621         switch (Width) {
01622         case 0:
01623                 Width = 12;
01624                 break;
01625         case 1:
01626                 Width = 22;
01627                 break;
01628         }
01629         int StartPos = Width - Text1.length();
01630         for (int lp = 0; lp < StartPos; lp ++)
01631                 cout << " ";
01632         cout << Text1;
01633         if (Text2 != "")
01634                 cout << " - " << Text2;
01635         if (Text3 != "")
01636                 cout << " [" << Text3 << "]";
01637         cout << endl;
01638 }
01639 
01649 void GizmoDaemon::printNiceScriptRegister(int Width, std::string Text1, std::string Text2, std::string Text3, std::string Text4, std::string Text5) {
01650         replace_all(Text1, "\n", ""); 
01651         replace_all(Text2, "\n", ""); 
01652         replace_all(Text3, "\n", "");
01653         replace_all(Text4, "\n", ""); 
01654         replace_all(Text5, "\n", "");
01655         trim(Text1); 
01656         trim(Text2); 
01657         trim(Text3);
01658         trim(Text4);
01659         trim(Text5);
01660         switch (Width) {
01661         case 0:
01662                 Width = 12;
01663                 break;
01664         case 1:
01665                 Width = 22;
01666                 break;
01667         }
01668         int StartPos = Width - Text1.length();
01669         for (int lp = 0; lp < StartPos; lp ++)
01670                 cout << " ";
01671         cout << Text1;
01672         if (Text2 != "")
01673                 cout << " - " << Text2;
01674         if (Text3 != "") {
01675                 size_t lastSPos = Text3.rfind("/");
01676                 if (lastSPos != string::npos)
01677                         Text3 = Text3.substr(lastSPos + 1);
01678                 cout << " [" << Text3 << "]";
01679         }
01680         if ( (Text4 != "") && (Text4 != "-0x1") && (Text4 != "0xffff") )
01681                 cout << " vId: " << Text4;
01682         if ( (Text4 != "") && (Text5 != "-0x1") && (Text5 != "0xffff") )
01683                 cout << " pId: " << Text5;
01684         cout << endl;
01685 }
01686 
01693 void GizmoDaemon::onAlsaEventMixerElementAttach(AlsaEvent const & Event, AlsaSoundCard const & SoundCard, AlsaMixer const & Mixer) {
01694         if (mShuttingDown)
01695                 return;
01696         
01697         cdbg1 << "Mixer Element Attached [" << Mixer.getName() << "] on Sound Card [" << SoundCard.getCardName() << "]" << endl;
01698         try {
01699                 mutex::scoped_lock lock(mMutexScript);
01700                 GizmoEventSoundCard EventSoundCard(Event, SoundCard, Mixer);
01701                 
01702                 if (!mLocalDisabled)
01703                         mpPyDispatcher->onEvent(&EventSoundCard);
01704         } catch (error_already_set) {
01705                 PyErr_Print();
01706                 cerr << "Failed to call GizmodDispatcher.onEvent for onAlsaEventMixerElementAttach" << endl;
01707         }
01708 }
01709 
01716 void GizmoDaemon::onAlsaEventMixerElementChange(AlsaEvent const & Event, AlsaSoundCard const & SoundCard, AlsaMixer const & Mixer) {
01717         if (mShuttingDown)
01718                 return;
01719         
01720         if (Event.Type == ALSAEVENT_MIXERELEMENT_CHANGE) 
01721                 cdbg2 << "Mixer Element Changed [" << Mixer.getName() << "] with Mask [" << Event.IsActiveChanged << Event.ElementsChanged << Event.VolumePlaybackChanged << "] on Sound Card [" << SoundCard.getCardName() << "] " << Mixer.VolumePlaybackPercent << endl;
01722         else
01723                 cdbg2 << "Mixer Element Changed [" << Mixer.getName() << "] with Mask [" << Event.Mask << "] on Sound Card [" << SoundCard.getCardName() << "]" << endl;
01724         
01725         try {
01726                 mutex::scoped_lock lock(mMutexScript);
01727                 GizmoEventSoundCard EventSoundCard(Event, SoundCard, Mixer);
01728                 
01729                 if (!mLocalDisabled)
01730                         mpPyDispatcher->onEvent(&EventSoundCard);
01731         } catch (error_already_set) {
01732                 PyErr_Print();
01733                 cerr << "Failed to call GizmodDispatcher.onEvent for onAlsaEventMixerElementChange" << endl;
01734         }
01735 }
01736 
01743 void GizmoDaemon::onAlsaEventMixerElementDetach(AlsaEvent const & Event, AlsaSoundCard const & SoundCard, AlsaMixer const & Mixer) {
01744         if (mShuttingDown)
01745                 return;
01746         
01747         cdbg3 << "Mixer Element Detached [" << Mixer.getName() << "] on Sound Card [" << SoundCard.getCardName() << "]" << endl;        
01748         try {
01749                 mutex::scoped_lock lock(mMutexScript);
01750                 GizmoEventSoundCard EventSoundCard(Event, SoundCard, Mixer);
01751                 
01752                 if (!mLocalDisabled)
01753                         mpPyDispatcher->onEvent(&EventSoundCard);
01754         } catch (error_already_set) {
01755                 PyErr_Print();
01756                 cerr << "Failed to call GizmodDispatcher.onEvent for onAlsaEventMixerElementDetach" << endl;
01757         }
01758 }
01759 
01765 void GizmoDaemon::onAlsaEventSoundCardAttach(AlsaEvent const & Event, AlsaSoundCard const & SoundCard) {
01766         if (mShuttingDown)
01767                 return;
01768         
01769         cdbg << "Attached to Sound Card [" << SoundCard.getCardHardwareID() << "] -- " << SoundCard.getCardName() << endl;
01770         try {
01771                 mutex::scoped_lock lock(mMutexScript);
01772                 GizmoEventSoundCard EventSoundCard(Event, SoundCard);
01773                 
01774                 if (!mLocalDisabled)
01775                         mpPyDispatcher->onEvent(&EventSoundCard);
01776         } catch (error_already_set) {
01777                 PyErr_Print();
01778                 cerr << "Failed to call GizmodDispatcher.onEvent for onAlsaEventSoundCardAttach" << endl;
01779         }
01780 }
01781 
01787 void GizmoDaemon::onAlsaEventSoundCardDetach(AlsaEvent const & Event, AlsaSoundCard const & SoundCard) {
01788         if (mShuttingDown)
01789                 return;
01790         
01791         cdbg1 << "Sound Card Detached [" << SoundCard.getCardHardwareID() << "] -- " << SoundCard.getCardName() << endl;
01792         try {
01793                 mutex::scoped_lock lock(mMutexScript);
01794                 GizmoEventSoundCard EventSoundCard(Event, SoundCard);
01795                 
01796                 if (!mLocalDisabled)
01797                         mpPyDispatcher->onEvent(&EventSoundCard);
01798         } catch (error_already_set) {
01799                 PyErr_Print();
01800                 cerr << "Failed to call GizmodDispatcher.onEvent for onAlsaEventSoundCardDetach" << endl;
01801         }
01802 }
01803 
01808 void GizmoDaemon::onCPUUsage(std::vector< boost::shared_ptr<CPUUsageInfo> > const & Event) {    
01809         if (mShuttingDown)
01810                 return;
01811         
01812         try {
01813                 mutex::scoped_lock lock(mMutexScript);
01814                 GizmoEventCPUUsage const EventCPUUsage(Event);
01815                 
01816                 // process the local event
01817                 if (!mLocalDisabled)
01818                         mpPyDispatcher->onEvent(&EventCPUUsage);
01819                 
01820                 // process the remote event
01821                 try {
01822                         sendEventCPUUsage(Event);
01823                 } catch (SocketException const & e) {
01824                         cdbg << "Failed to send CPUUsage Message to Server -- " << e.getExceptionMessage() << endl;
01825                 }               
01826         } catch (error_already_set) {
01827                 PyErr_Print();
01828                 cerr << "Failed to call GizmodDispatcher.onEvent for onCPUUsage" << endl; 
01829         }       
01830 }
01831 
01838 void GizmoDaemon::onFileEventCreate(boost::shared_ptr<H::FileWatchee> pWatchee, std::string FullPath, std::string FileName) {
01839         if (FileName.find("event") != 0) {
01840                 cout << "onFileEventCreate [" << FullPath << "]" << endl;
01841                 return;
01842         }
01843         addFileToWatch(FullPath, WATCH_INOUT);
01844 }
01845 
01852 void GizmoDaemon::onFileEventDelete(boost::shared_ptr<H::FileWatchee> pWatchee, std::string FullPath, std::string FileName) {
01853         cdbg5 << "onFileEventDelete [" << FullPath << "] -- " << pWatchee->FileName << endl;
01854         deleteGizmo(pWatchee->FileName);
01855 }
01856 
01861 void GizmoDaemon::onFileEventDisconnect(boost::shared_ptr<H::FileWatchee> pWatchee) {
01862         cdbg5 << "onFileEventDisconnect [" << pWatchee->FileName << "]: " << pWatchee->DeviceName << endl;
01863         deleteGizmo(pWatchee->FileName);
01864 }
01865 
01871 void GizmoDaemon::onFileEventRead(boost::shared_ptr<H::FileWatchee> pWatchee, DynamicBuffer<char> const & ReadBuffer) {
01872         if (mShuttingDown)
01873                 return;
01874         
01875         // make sure the gizmo exists
01876         shared_ptr<Gizmo> pUnknownGizmo = mGizmos[pWatchee->FileName];
01877         if (!pUnknownGizmo) {
01878                 cdbg << "Unknown Event Detected on Device [" << pWatchee->DeviceName << "] of Length [" << (int) ReadBuffer.length() << "]" << endl;
01879                 return;
01880         }
01881                                 
01882         // create the event and dispatch it
01883         try {
01884                 switch (pUnknownGizmo->getClass()) {
01885                 case GIZMO_CLASS_ATIX10:
01886                         handleFileEventReadATIX10(static_cast<GizmoATIX10 &>(*pUnknownGizmo), ReadBuffer);
01887                         break;
01888                 case GIZMO_CLASS_LIRC:
01889                         handleFileEventReadLIRC(static_cast<GizmoLIRC &>(*pUnknownGizmo), ReadBuffer);
01890                         break;
01891                 case GIZMO_CLASS_POWERMATE:
01892                         handleFileEventReadPowermate(static_cast<GizmoPowermate &>(*pUnknownGizmo), ReadBuffer);
01893                         break;                  
01894                 case GIZMO_CLASS_STANDARD: 
01895                         handleFileEventReadStandard(static_cast<GizmoStandard &>(*pUnknownGizmo), ReadBuffer);
01896                         break;                  
01897                 }
01898         } catch (error_already_set) {
01899                 PyErr_Print();
01900                 cerr << "Failed to call GizmodDispatcher.onEvent for onFileEventRead" << endl;
01901         }
01902 }
01903 
01908 void GizmoDaemon::onFileEventRegister(boost::shared_ptr<H::FileWatchee> pWatchee) {
01909         if (mShuttingDown)
01910                 return;
01911         
01912         cdbg1 << "New Device Detected [" << pWatchee->FileName << "]: " << pWatchee->DeviceName << endl;
01913         try {
01914                 mutex::scoped_lock lock(mMutexScript);
01915                 GizmoClass Class = mpPyDispatcher->onQueryDeviceClass(*pWatchee);
01916                 switch (Class) {
01917                 case GIZMO_CLASS_ATIX10: {
01918                         shared_ptr<GizmoATIX10> pGizmo(new GizmoATIX10(*pWatchee, mGizmos.size(), getGizmoClassID(GIZMO_CLASS_ATIX10)));
01919                         mGizmos.insert(make_pair(pWatchee->FileName, pGizmo));
01920                         mpPyDispatcher->onRegisterDevice(pGizmo.get());
01921                         break; }
01922                 case GIZMO_CLASS_LIRC: {
01923                         shared_ptr<GizmoLIRC> pGizmo(new GizmoLIRC(*pWatchee, mGizmos.size(), getGizmoClassID(GIZMO_CLASS_LIRC)));
01924                         mGizmos.insert(make_pair(pWatchee->FileName, pGizmo));
01925                         mpPyDispatcher->onRegisterDevice(pGizmo.get());
01926                         break; }
01927                 case GIZMO_CLASS_POWERMATE: {
01928                         shared_ptr<GizmoPowermate> pGizmo(new GizmoPowermate(*pWatchee, mGizmos.size(), getGizmoClassID(GIZMO_CLASS_POWERMATE)));
01929                         mGizmos.insert(make_pair(pWatchee->FileName, pGizmo));
01930                         mpPyDispatcher->onRegisterDevice(pGizmo.get());
01931                         break; }
01932                 case GIZMO_CLASS_STANDARD: {
01933                         shared_ptr<GizmoStandard> pGizmo(new GizmoStandard(*pWatchee, mGizmos.size(), getGizmoClassID(GIZMO_CLASS_STANDARD)));
01934                         mGizmos.insert(make_pair(pWatchee->FileName, pGizmo));
01935                         mpPyDispatcher->onRegisterDevice(pGizmo.get());
01936                         break; }
01937                 }
01938         } catch (error_already_set) {
01939                 PyErr_Print();
01940                 throw H::Exception("Failed to call GizmodDispatcher.onRegisterDevice for onFileEventRegister", __FILE__, __FUNCTION__, __LINE__);
01941         }
01942 }
01943 
01947 void GizmoDaemon::onFileEventWatchBegin() {
01948 }
01949 
01953 void GizmoDaemon::onFileEventWatchEnd() {
01954 }
01955 
01960 void GizmoDaemon::onFocusIn(X11FocusEvent const & Event) {
01961         if (mShuttingDown)
01962                 return;
01963         
01964         //cdbg << "Current Focus: " << Event.WindowName << " [" << Event.WindowNameFormal << "] <" << Event.WindowClass << ">" << endl;
01965         try {
01966                 mutex::scoped_lock lock(mMutexScript);
01967                 mCurrentFocus = Event;
01968                 GizmoEventWindowFocus FocusEvent(Event);
01969                 if (!mLocalDisabled)
01970                         mpPyDispatcher->onEvent(&FocusEvent);
01971         } catch (error_already_set) {
01972                 PyErr_Print();
01973                 cerr << "Failed to call GizmodDispatcher.onEvent for onFocusIn" << endl;
01974         }
01975 }
01976 
01981 void GizmoDaemon::onFocusOut(X11FocusEvent const & Event) {
01982         if (mShuttingDown)
01983                 return;
01984         
01985         //cdbg << "Leaving Focus: " << Event.WindowName << " [" << Event.WindowNameFormal << "] <" << Event.WindowClass << ">" << endl;
01986         try {
01987                 mutex::scoped_lock lock(mMutexScript);
01988                 GizmoEventWindowFocus FocusEvent(Event);
01989                 if (!mLocalDisabled)
01990                         mpPyDispatcher->onEvent(&FocusEvent);
01991         } catch (error_already_set) {
01992                 PyErr_Print();
01993                 cerr << "Failed to call GizmodDispatcher.onEvent for onFocusOut" << endl;
01994         }
01995 }
01996 
02000 void GizmoDaemon::onSignalSegv() {
02001         cerr << "Segmentation Fault Detected" << endl;
02002         signalShutdown();
02003 }
02004 
02008 void GizmoDaemon::onSignalInt() {
02009         cdbg << "Keyboard Interrupt Received..." << endl;
02010         signalShutdown();
02011 }
02012 
02016 void GizmoDaemon::onSignalHup() {
02017         cout << "HUP signal received, reloading config..." << endl;
02018         mReloadConfig = true;
02019         signalShutdown();
02020 }
02021 
02025 void GizmoDaemon::onSignalQuit() {
02026         cdbg << "Request to Quit Received..." << endl;
02027         signalShutdown();
02028 }
02029 
02033 void GizmoDaemon::onSignalKill() {
02034         cdbg << "Kill signal Received..." << endl;
02035         signalShutdown();
02036 }
02037 
02041 void GizmoDaemon::onSignalTerm() {
02042         cdbg << "Request to Terminate Received..." << endl;
02043         signalShutdown();
02044 }
02045 
02049 void GizmoDaemon::onSignalStop() {
02050         cdbg << "Request to Stop Received..." << endl;
02051         signalShutdown();
02052 }
02053 
02057 void GizmoDaemon::onSignalUnknown(int Signal) {
02058         cerr << "Unhandled Unknown Signal" << endl;
02059 }
02060 
02065 void GizmoDaemon::onSocketClientConnect(Socket const & socket) {
02066         cdbg << "Successfully Connected to [" << mClientHost << "] at Port [" << mClientPort << "]" << endl;
02067 }
02068 
02073 void GizmoDaemon::onSocketClientDisconnect(Socket const & socket) {
02074         cdbg << "Disconnected from Server" << endl;
02075 }
02076 
02082 void GizmoDaemon::onSocketClientMessage(Socket const & socket, std::string const & Message) {
02083         cdbg << "Client Socket Message [" << Message.length() << "] Bytes -- " << Message << endl;
02084 }
02085 
02091 void GizmoDaemon::onSocketClientRead(Socket const & socket, DynamicBuffer<char> & ReadBuffer) {
02092         cdbg << "Client Socket Read [" << ReadBuffer.length() << "] Bytes" << endl;
02093 }
02094 
02099 void GizmoDaemon::onSocketServerConnect(boost::shared_ptr<Socket> pSocket) {
02100         cdbg << "Client Connection from [" << pSocket->getAddress() << "]" << endl;
02101 }
02102 
02107 void GizmoDaemon::onSocketServerDisconnect(Socket const & socket) {
02108         cdbg << "Client Disconnected [" << socket.getAddress() << "]" << endl;
02109 }
02110 
02116 void GizmoDaemon::onSocketServerMessage(Socket const & socket, std::string const & Message) {
02117         if (mShuttingDown)
02118                 return;
02119         
02120         //cdbg << "Socket Message [" << Message.length() << "] Bytes -- " << Message << endl;
02121         size_t dPos = Message.find("|");
02122         if (dPos == string::npos) {
02123                 cdbg << "Invalid Message Received from Client [" << socket.getAddress() << "]" << endl;
02124                 return;
02125         }
02126         
02127         int MessageType;
02128         try {
02129                  MessageType = lexical_cast<int>(Message.substr(0, dPos));
02130         } catch (bad_lexical_cast const & e) {
02131                 cdbg << "Invalid Message Type Received from Client [" << socket.getAddress() << "]" << endl;
02132                 return;
02133         }
02134         
02135         // make sure event class isn't all wacky
02136         if ( (MessageType < 0) || (MessageType > GIZMO_EVENTCLASS_MAX) ) {
02137                 cdbg << "Improper Message Type Received from Client [" << socket.getAddress() << "]" << endl;
02138                 return;
02139         }
02140         
02141         // everything is okay, let's deserialize
02142         deserializeMessage(static_cast<GizmoEventClass>(MessageType), Message.substr(dPos + 1));
02143 }
02144 
02150 void GizmoDaemon::onSocketServerRead(Socket const & socket, DynamicBuffer<char> & ReadBuffer) {
02151         //cdbg4 << "Socket Read [" << ReadBuffer.length() << "] Bytes" << endl;
02152 }
02153 
02160 void GizmoDaemon::registerDevices() {
02161         cout << "Registering Devices:" << endl << endl;
02162         
02163         // register input event devices
02164         registerInputEventDevices();
02165         
02166         // register the LIRC device
02167         registerLircDevice();
02168         
02169         // aesthetics
02170         cout << endl;
02171 }
02172 
02176 void GizmoDaemon::registerInputEventDevices() {
02177         cdbg1 << "Registering Input Event Devices in [" << mEventsDir << "]" << endl;
02178         path EventsDirPath(mEventsDir);
02179         if (!filesystem::exists(EventsDirPath))
02180                 throw H::Exception("Input Event dir [" + mEventsDir + "] does NOT exist or permissions are wrong!", __FILE__, __FUNCTION__, __LINE__);
02181         
02182         // register the directory itself
02183         addFileToWatch(mEventsDir, WATCH_INOUT);
02184         
02185         // now register the event nodes
02186         // get a file listing
02187         std::vector<string> eventsFiles;
02188         directory_iterator endItr;
02189         for (directory_iterator iter(mEventsDir); iter != endItr; iter ++) {
02190                 if ( (!filesystem::is_directory(*iter)) && (!filesystem::symbolic_link_exists(*iter)) ) {
02191                         if (iter->leaf().find("event") != 0)
02192                                 continue;
02193                         eventsFiles.push_back(mEventsDir + "/" + iter->leaf());
02194                 }
02195         }
02196         
02197         // sort the list of input event nodes
02198         sort_all(eventsFiles);
02199         apply_func_args(eventsFiles, &FileEventWatcher::addFileToWatch, this, WATCH_INOUT, "Unknown");
02200 }
02201 
02205 void GizmoDaemon::registerLircDevice() {
02206         cdbg1 << "Registering LIRC device node [" << mLircDev << "]" << endl;
02207         path LircDevPath(mLircDev);
02208         if (!filesystem::exists(LircDevPath)) {
02209                 cdbg << "LIRC device node [" + mLircDev + "] does not exist -- disabling LIRC support" << endl;
02210                 return;
02211         }
02212         
02213         boost::shared_ptr<FileWatchee> pWatchee = addUnixSocketToWatch(mLircDev, "LIRC");
02214         if (!pWatchee) {
02215                 cdbg << "Could not connect to LIRC device node [" + mLircDev + "] -- disabling LIRC support" << endl;
02216                 cdbg << "    - Check permissions" << endl;
02217                 cdbg << "    - Ensure lircd is running" << endl;
02218                 return;
02219         }
02220 }
02221 
02225 void GizmoDaemon::setConfigDir() {
02226         // get the hoome directory
02227         string HomeScriptDir = HOME_SCRIPT_DIR;
02228         char * EnvHome = getenv("HOME");
02229         if (EnvHome)
02230                 replace_all(HomeScriptDir, "~", EnvHome);
02231         
02232         // make sure it's okay
02233         bool PathsOkay;
02234         try {
02235                 path HomeScriptPath(HomeScriptDir);
02236                 PathsOkay = true;
02237         } catch (filesystem_error const & e) {
02238                 PathsOkay = false;
02239         }
02240         
02241         // set the path
02242         if ( PathsOkay && filesystem::exists(HomeScriptDir) && filesystem::exists(HomeScriptDir + USER_SCRIPT_DIR) ) {
02243                 mConfigDir = HomeScriptDir;
02244         } else {
02245                 mConfigDir = SCRIPT_DIR;
02246                 replace_all(mConfigDir, "${prefix}", PREFIX);
02247         }
02248 }
02249 
02253 void GizmoDaemon::setVersionInfo() {
02254         string Version = VERSION;
02255         size_t cPos = Version.find(":");
02256         if (cPos == string::npos)
02257                 cPos = Version.find(".");
02258         if (cPos == string::npos) {
02259                 mVersionMajor = 0;
02260                 mVersionMinor = 0;
02261         } else {
02262                 try {
02263                         mVersionMajor = lexical_cast<int>(Version.substr(0, cPos));
02264                         mVersionMinor = lexical_cast<int>(Version.substr(cPos + 1));
02265                 } catch (bad_lexical_cast const & e) {
02266                         mVersionMajor = 0;
02267                         mVersionMinor = 0;
02268                         return;
02269                 }
02270         }
02271         
02272         mVersion = double(mVersionMajor) + (double(mVersionMinor) / 10.0);
02273 }
02274 
02278 void GizmoDaemon::signalShutdown() {
02279         mShuttingDown = true;
02280         FileEventWatcher::shutdown();
02281 }

Generated on Wed Nov 7 10:04:16 2007 for gizmod by  doxygen 1.5.3