Ignore:
Timestamp:
01/26/13 04:24:01 (11 years ago)
Author:
Nicholas Riley
Message:

AudioDevicemodule.c: Register callback for when default output device
changes.

StreamVision.py: Turn on/off the stereo when the current output device
changes to/from AirPlay.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/StreamVision/AudioDevicemodule.c

    r653 r654  
    22#include <AudioToolbox/AudioServices.h>
    33
    4 static PyObject
    5 *AudioDevice_default_output_device_is_airplay(PyObject *self, PyObject *args) {
     4static PyObject *
     5AudioDevice_default_output_device_is_airplay(PyObject *self, PyObject *args) {
    66  AudioObjectPropertyAddress propertyAddress;
    77  propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
     
    4040}
    4141
    42 // XXX device changed notifications:
    43 // http://stackoverflow.com/questions/9674666/
     42static PyObject *default_output_device_changed_callback = NULL;
     43
     44OSStatus
     45output_device_changed_listener(AudioObjectID inObjectID,
     46                               UInt32 inNumberAddresses,
     47                               const AudioObjectPropertyAddress inAddresses[],
     48                               void *inClientData) {
     49  PyGILState_STATE gstate = PyGILState_Ensure();
     50  PyObject_CallObject(default_output_device_changed_callback, NULL);
     51  PyGILState_Release(gstate);
     52
     53  return noErr;
     54}
     55
     56static PyObject *
     57AudioDevice_set_default_output_device_changed_callback(PyObject *self,
     58                                                       PyObject *args) {
     59  PyObject *new_callback;
     60  if (!PyArg_ParseTuple(args, "O", &new_callback))
     61    return NULL;
     62
     63  if (!PyCallable_Check(new_callback)) {
     64    PyErr_SetString(PyExc_TypeError, "parameter must be callable");
     65    return NULL;
     66  }
     67  Py_INCREF(new_callback);
     68  if (default_output_device_changed_callback == NULL) {
     69    AudioObjectPropertyAddress propertyAddress;
     70    propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
     71    propertyAddress.mElement = kAudioObjectPropertyElementMaster;
     72    propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
     73
     74    OSStatus err;
     75    err = AudioObjectAddPropertyListener(kAudioObjectSystemObject,
     76                                         &propertyAddress,
     77                                         &output_device_changed_listener,
     78                                         NULL);
     79    if (err != noErr)
     80      return PyErr_Format(PyExc_OSError,
     81                          "AudioObjectAddPropertyListener failed (%ld)",
     82                          (long)err);
     83  } else {
     84    Py_DECREF(default_output_device_changed_callback);
     85  }
     86  default_output_device_changed_callback = new_callback;
     87 
     88  Py_RETURN_NONE;
     89}
    4490
    4591static PyMethodDef AudioDevicemodule_methods[] = {
     
    4894   "default_output_device() -> bool or None\n\n"
    4995   "Return whether the default CoreAudio output device is an AirPlay device."},
     96  {"set_default_output_device_changed_callback",
     97   AudioDevice_set_default_output_device_changed_callback, METH_VARARGS,
     98   "set_default_output_device_changed_callback(callable)\n\n"
     99   "Set a callback invoked when the default CoreAudio output device changes."},
    50100  {NULL, NULL, 0, NULL}
    51101};
Note: See TracChangeset for help on using the changeset viewer.