[Pythonmac-SIG] Measuring the users idle time

Nicholas Riley njriley at uiuc.edu
Thu Sep 9 17:04:40 CEST 2004


On Tue, Sep 07, 2004 at 11:37:31PM +0200, Gabriel Birke wrote:
> Is there any way to measure the the time the user was idle?

There is, but unfortunately I have not been able to figure out a way
to exclude the effects of application-generated calls to
UpdateSystemActivity(), which resets the idle time to 0.
UpdateSystemActivity is used by most audio/video players to stop
displays from blanking, and so forth.

Here's the code.  I ripped it out of a larger module, so there might
be a few syntax errors that cause it not to compile as is.

/* compile with distutils as:

setup( # ...
    ext_modules=[Extension('_watch',
                            sources=['_watchmodule.c'],
                            extra_link_args=['-framework', 'ApplicationServices',
                                             '-framework', 'IOKit'])] */

#include "Python.h"
#include "pymactoolbox.h"

#include <ApplicationServices/ApplicationServices.h>
#include <IOKit/IOKitLib.h>

static PyObject *
  watch_idleseconds(PyObject *self, PyObject *args) {
  io_registry_entry_t hidSystemService;

  hidSystemService =
    IOServiceGetMatchingService(kIOMasterPortDefault,
				IOServiceMatching("IOHIDSystem"));

  if (hidSystemService == NULL) {
    PyErr_SetString(PyExc_OSError,
		    "Couldn't get IORegistry entry for IOHIDSystem");
    return NULL;
  }
  
  CFMutableDictionaryRef propertyDict = NULL;
  IOReturn result =
    IORegistryEntryCreateCFProperties(hidSystemService, &propertyDict,
				      kCFAllocatorDefault, 0);
  IOObjectRelease(hidSystemService);

  if (result != KERN_SUCCESS || propertyDict == NULL) {
    PyErr_SetString(PyExc_OSError, "Couldn't get properties for IOHIDSystem");
    return NULL;
  }

  PyObject *pyIdleSeconds = NULL;
  CFTypeRef idleTime = CFDictionaryGetValue(propertyDict, CFSTR("HIDIdleTime"));
  
  if (idleTime == NULL) {
    PyErr_SetString(PyExc_OSError, "IOHIDSystem had no HIDIdleTime property\n");
    goto cleanup;
  }
  CFTypeID idleType = CFGetTypeID(idleTime);
  int64_t idleNanoseconds;

  if (idleType == CFDataGetTypeID()) // Jaguar
    CFDataGetBytes((CFDataRef)idleTime,
		   CFRangeMake(0, sizeof(idleNanoseconds)),
		   (UInt8*) &idleNanoseconds);
  else if (idleType == CFNumberGetTypeID()) // Panther and later
    CFNumberGetValue((CFNumberRef)idleTime, kCFNumberSInt64Type,
		     &idleNanoseconds);
  else {
    PyErr_SetString(PyExc_OSError,
		    "Couldn't understand idle time (not CFData or CFNumber)");
    goto cleanup;
  }
  pyIdleSeconds = PyLong_FromLongLong(idleNanoseconds / kSecondScale);

  cleanup:
  CFRelease(propertyDict);

  return pyIdleSeconds;
}

static PyMethodDef _watch_methods[] = {
  {"idleseconds", watch_idleseconds, METH_NOARGS,
   "idleseconds() -> long integer\n\n"
   "Return the number of seconds since a keyboard/mouse movement."},
  {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
init_watch(void) {
  (void)Py_InitModule("_watch", _watch_methods);
}

-- 
=Nicholas Riley <njriley at uiuc.edu> | <http://www.uiuc.edu/ph/www/njriley>


More information about the Pythonmac-SIG mailing list