Skip to content

Commit

Permalink
Add support for opening some subset of the three Kinect devices (moto…
Browse files Browse the repository at this point in the history
…r, camera, audio).

This allows libfreenect to be used alongside other Kinect drivers more easily,
as well as allows different processes to use libfreenect for different
subdevices.  Examples of things you can do now that you couldn't do before:

1) use libfreenect's audio and motor support alongside OpenNI's camera support
2) use libfreenect's video support in one process while processing audio with
another process

Signed-off-by: Drew Fisher <drew.m.fisher@gmail.com> (zarvox)
  • Loading branch information
zarvox committed Jul 17, 2011
1 parent 726d82f commit cdea8fd
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 27 deletions.
1 change: 1 addition & 0 deletions examples/glview.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ int main(int argc, char **argv)
}

freenect_set_log_level(f_ctx, FREENECT_LOG_DEBUG);
freenect_select_subdevices(f_ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA));

int nr_devices = freenect_num_devices (f_ctx);
printf ("Number of devices found: %d\n", nr_devices);
Expand Down
1 change: 1 addition & 0 deletions examples/hiview.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ int main(int argc, char **argv)
}

freenect_set_log_level(f_ctx, FREENECT_LOG_DEBUG);
freenect_select_subdevices(f_ctx, FREENECT_DEVICE_CAMERA);

int nr_devices = freenect_num_devices (f_ctx);
printf ("Number of devices found: %d\n", nr_devices);
Expand Down
1 change: 1 addition & 0 deletions examples/micview.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ int main(int argc, char** argv) {
return 1;
}
freenect_set_log_level(f_ctx, FREENECT_LOG_INFO);
freenect_select_subdevices(f_ctx, FREENECT_DEVICE_AUDIO);

int nr_devices = freenect_num_devices (f_ctx);
printf ("Number of devices found: %d\n", nr_devices);
Expand Down
1 change: 1 addition & 0 deletions examples/wavrecord.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ int main(int argc, char** argv) {
return 1;
}
freenect_set_log_level(f_ctx, FREENECT_LOG_SPEW);
freenect_select_subdevices(f_ctx, FREENECT_DEVICE_AUDIO);

int nr_devices = freenect_num_devices (f_ctx);
printf ("Number of devices found: %d\n", nr_devices);
Expand Down
5 changes: 5 additions & 0 deletions fakenect/fakenect.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,11 @@ int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx)
return 0;
}

void freenect_select_subdevices(freenect_context *ctx, freenect_device_flags subdevs) {
// Ideally, we'd actually check for MOTOR and CAMERA and AUDIO, but for now
// we just ignore them and provide all captured data.
}

int freenect_set_depth_buffer(freenect_device *dev, void *buf)
{
depth_buffer = buf;
Expand Down
3 changes: 3 additions & 0 deletions fakenect/record.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ void init()
return;
}

// fakenect doesn't support audio yet, so don't bother claiming the device
freenect_select_subdevices(ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA));

if (freenect_open_device(ctx, &dev, 0)) {
printf("Error: Cannot get device\n");
return;
Expand Down
23 changes: 23 additions & 0 deletions include/libfreenect.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ extern "C" {

#define FREENECT_COUNTS_PER_G 819 /**< Ticks per G for accelerometer as set per http://www.kionix.com/Product%20Sheets/KXSD9%20Product%20Brief.pdf */

/// Flags representing devices to open when freenect_open_device() is called.
/// In particular, this allows libfreenect to grab only a subset of the devices
/// in the Kinect, so you could (for instance) use libfreenect to handle audio
/// and motor support while letting OpenNI have access to the cameras.
/// If a device is not supported on a particular platform, its flag will be ignored.
typedef enum {
FREENECT_DEVICE_MOTOR = 0x01,
FREENECT_DEVICE_CAMERA = 0x02,
FREENECT_DEVICE_AUDIO = 0x04,
} freenect_device_flags;

/// Enumeration of available resolutions.
/// Not all available resolutions are actually supported for all video formats.
/// Frame modes may not perfectly match resolutions. For instance,
Expand Down Expand Up @@ -219,6 +230,18 @@ FREENECTAPI int freenect_process_events(freenect_context *ctx);
*/
FREENECTAPI int freenect_num_devices(freenect_context *ctx);

/**
* Set which subdevices any subsequent calls to freenect_open_device()
* should open. This will not affect devices which have already been
* opened. The default behavior, should you choose not to call this
* function at all, is to open all supported subdevices - motor, cameras,
* and audio, if supported on the platform.
*
* @param ctx Context to set future subdevice selection for
* @param subdevs Flags representing the subdevices to select
*/
FREENECTAPI void freenect_select_subdevices(freenect_context *ctx, freenect_device_flags subdevs);

/**
* Opens a kinect device via a context. Index specifies the index of
* the device on the current state of the bus. Bus resets may cause
Expand Down
53 changes: 32 additions & 21 deletions src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ FREENECTAPI int freenect_init(freenect_context **ctx, freenect_usb_context *usb_
memset(*ctx, 0, sizeof(freenect_context));

(*ctx)->log_level = LL_WARNING;
(*ctx)->enabled_subdevices = (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA | FREENECT_DEVICE_AUDIO);
return fnusb_init(&(*ctx)->usb, usb_ctx);
}

Expand All @@ -70,6 +71,14 @@ FREENECTAPI int freenect_num_devices(freenect_context *ctx)
return fnusb_num_devices(&ctx->usb);
}

FREENECTAPI void freenect_select_subdevices(freenect_context *ctx, freenect_device_flags subdevs) {
ctx->enabled_subdevices = subdevs & (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA
#ifdef BUILD_AUDIO
| FREENECT_DEVICE_AUDIO
#endif
);
}

FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index)
{
int res;
Expand All @@ -87,27 +96,29 @@ FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **de
return res;
}
#ifdef BUILD_AUDIO
res = fnusb_num_interfaces(&pdev->usb_audio);
if (res == 1) {
// Upload audio firmware, release devices, and reopen them
res = upload_firmware(&pdev->usb_audio);
if (res < 0) {
FN_ERROR("upload_firmware failed: %d\n", res);
free(pdev);
return res;
}

res = fnusb_close_subdevices(pdev);
if (res < 0) {
FN_ERROR("fnusb_close_subdevices failed: %d\n", res);
free(pdev);
return res;
}
sleep(1); // Give time for the device to reenumerate before trying to open it
res = fnusb_open_subdevices(pdev, index);
if (res < 0) {
free(pdev);
return res;
if (pdev->usb_audio.dev) {
res = fnusb_num_interfaces(&pdev->usb_audio);
if (res == 1) {
// Upload audio firmware, release devices, and reopen them
res = upload_firmware(&pdev->usb_audio);
if (res < 0) {
FN_ERROR("upload_firmware failed: %d\n", res);
free(pdev);
return res;
}

res = fnusb_close_subdevices(pdev);
if (res < 0) {
FN_ERROR("fnusb_close_subdevices failed: %d\n", res);
free(pdev);
return res;
}
sleep(1); // Give time for the device to reenumerate before trying to open it
res = fnusb_open_subdevices(pdev, index);
if (res < 0) {
free(pdev);
return res;
}
}
}
#endif
Expand Down
1 change: 1 addition & 0 deletions src/freenect_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct _freenect_context {
freenect_loglevel log_level;
freenect_log_cb log_cb;
fnusb_ctx usb;
freenect_device_flags enabled_subdevices;
freenect_device *first;
};

Expand Down
14 changes: 8 additions & 6 deletions src/usb_libusb10.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ int fnusb_open_subdevices(freenect_device *dev, int index)
continue;

// Search for the camera
if (!dev->usb_cam.dev && desc.idProduct == PID_NUI_CAMERA) {
if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && desc.idProduct == PID_NUI_CAMERA) {
// If the index given by the user matches our camera index
if (nr_cam == index) {
res = libusb_open (devs[i], &dev->usb_cam.dev);
Expand Down Expand Up @@ -159,7 +159,7 @@ int fnusb_open_subdevices(freenect_device *dev, int index)
}

// Search for the motor
if (!dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) {
if ((ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR) && !dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) {
// If the index given by the user matches our camera index
if (nr_mot == index) {
res = libusb_open (devs[i], &dev->usb_motor.dev);
Expand All @@ -183,7 +183,7 @@ int fnusb_open_subdevices(freenect_device *dev, int index)
#ifdef BUILD_AUDIO
// TODO: check that the firmware has already been loaded; if not, upload firmware.
// Search for the audio
if (!dev->usb_audio.dev && desc.idProduct == PID_NUI_AUDIO) {
if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && desc.idProduct == PID_NUI_AUDIO) {
// If the index given by the user matches our audio index
if (nr_audio == index) {
res = libusb_open (devs[i], &dev->usb_audio.dev);
Expand All @@ -209,11 +209,13 @@ int fnusb_open_subdevices(freenect_device *dev, int index)

libusb_free_device_list (devs, 1); // free the list, unref the devices in it

// Check that each subdevice is either opened or not enabled.
if ( (dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA))
&& (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR))
#ifdef BUILD_AUDIO
if (dev->usb_cam.dev && dev->usb_motor.dev && dev->usb_audio.dev) {
#else
if (dev->usb_cam.dev && dev->usb_motor.dev) {
&& (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO))
#endif
) {
return 0;
} else {
if (dev->usb_cam.dev) {
Expand Down
4 changes: 4 additions & 0 deletions wrappers/c_sync/libfreenect_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ static void init_thread(void)
{
thread_running = 1;
freenect_init(&ctx, 0);
// We claim both the motor and the camera, because we can't know in advance
// which devices the caller will want, and the c_sync interface doesn't
// support audio, so there's no reason to claim the device needlessly.
freenect_select_subdevices(ctx, (freenect_device_flags)(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA));
pthread_create(&thread, NULL, init, NULL);
}

Expand Down
3 changes: 3 additions & 0 deletions wrappers/cpp/libfreenect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ namespace Freenect {
public:
Freenect() : m_stop(false) {
if(freenect_init(&m_ctx, NULL) < 0) throw std::runtime_error("Cannot initialize freenect library");
// We claim both the motor and camera devices, since this class exposes both.
// It does not support audio, so we do not claim it.
freenect_select_subdevices(m_ctx, static_cast<freenect_device_flags>(FREENECT_DEVICE_MOTOR | FREENECT_DEVICE_CAMERA));
if(pthread_create(&m_thread, NULL, pthread_callback, (void*)this) != 0) throw std::runtime_error("Cannot initialize freenect thread");
}
~Freenect() {
Expand Down
9 changes: 9 additions & 0 deletions wrappers/python/freenect.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ LED_BLINK_RED_YELLOW = 6
RESOLUTION_LOW = 0
RESOLUTION_MEDIUM = 1
RESOLUTION_HIGH = 2
DEVICE_MOTOR = 1
DEVICE_CAMERA = 2
DEVICE_AUDIO = 4


cdef struct freenect_raw_tilt_state:
Expand Down Expand Up @@ -91,6 +94,7 @@ cdef extern from "libfreenect.h":
int freenect_shutdown(void *ctx)
int freenect_process_events(void *ctx)
int freenect_num_devices(void *ctx)
int freenect_select_subdevices(void *ctx, int subdevs)
int freenect_open_device(void *ctx, void **dev, int index)
int freenect_close_device(void *dev)
void freenect_set_depth_callback(void *dev, freenect_depth_cb cb)
Expand Down Expand Up @@ -230,6 +234,11 @@ cdef init():
cdef void* ctx
if freenect_init(cython.address(ctx), 0) < 0:
return
# We take both the motor and camera devices here, since we provide access
# to both but haven't wrapped the python API for selecting subdevices yet.
# Also, we don't support audio in the python wrapper yet, so no sense claiming
# the device.
freenect_select_subdevices(ctx, DEVICE_MOTOR | DEVICE_CAMERA)
cdef CtxPtr ctx_out
ctx_out = CtxPtr()
ctx_out._ptr = ctx
Expand Down

0 comments on commit cdea8fd

Please sign in to comment.