[PD-cvs] externals/hcs/hid hid.h,NONE,1.1 hid_darwin.c,NONE,1.1 hid.c,1.3,1.4

Hans-Christoph Steiner eighthave at users.sourceforge.net
Fri Oct 22 07:43:20 CEST 2004


Update of /cvsroot/pure-data/externals/hcs/hid
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14734

Modified Files:
	hid.c 
Added Files:
	hid.h hid_darwin.c 
Log Message:
started the process of organizing things for cross-platformness; sketched out MacOS X HID Manager implementation using SuperCollider3's SC_HID.cpp

--- NEW FILE: hid_darwin.c ---
/*
 *  Apple Darwin HID Manager support for [hid]
 *
 *  based on SC_HID.cpp from SuperCollider3 by Jan Truetzschler v. Falkenstein
 *
 *  Copyright (c) 2004 Hans-Christoph All rights reserved.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 */
#include <Carbon/Carbon.h>

#include "HID_Utilities_External.h"

/*
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDKeys.h>
*/
#include <IOKit/hid/IOHIDUsageTables.h>

#include <mach/mach.h>
#include <mach/mach_error.h>

#include "hid.h"

/*
#include "SCBase.h"
#include "VMGlobals.h"
#include "PyrSymbolTable.h"
#include "PyrInterpreter.h"
#include "PyrKernel.h"

#include "PyrObjectProto.h"
#include "PyrPrimitiveProto.h"
#include "PyrKernelProto.h"
#include "SC_InlineUnaryOp.h"
#include "SC_InlineBinaryOp.h"
#include "PyrSched.h"
#include "GC.h"
*/

int gNumberOfHIDDevices = 0;
EventLoopTimerRef gTimer = NULL; // timer for element data updates


void releaseHIDDevices ()
{
	if (gTimer)
    {    
		RemoveEventLoopTimer(gTimer);
		gTimer = NULL;
	}
	HIDReleaseAllDeviceQueues();
	HIDReleaseDeviceList();
	gNumberOfHIDDevices = 0;
}

int prHIDBuildElementList()
{
/*
	PyrSlot *a = g->sp - 1; //class
	PyrSlot *b = g->sp; //locID device
*/
	int i, locID, cookieNum;
	pRecElement	devElement;
	pRecDevice pCurrentHIDDevice;
//	int err;

//	int err = slotIntVal(b, &locID);
//	if (err) return err;

	// look for the right device: 
	pCurrentHIDDevice = HIDGetFirstDevice ();
	while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID))
        pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
	if(!pCurrentHIDDevice) return (1);
	
	devElement =  HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeInput);
	UInt32 numElements = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeInput);

	//PyrObject* devAllElementsArray = newPyrArray(g->gc, numElements * sizeof(PyrObject), 0 , true);
		
		for(i=0; i<numElements; i++)
		{
			char cstrElementName [256];
			//PyrObject* devElementArray = newPyrArray(g->gc, 5 * sizeof(PyrObject), 0 , true);
			HIDGetTypeName((IOHIDElementType) devElement->type, cstrElementName);
			//PyrString *devstring = newPyrString(g->gc, cstrElementName, 0, true);
			//SetObject(devElementArray->slots+devElementArray->size++, devstring);
			//g->gc->GCWrite(devElementArray, (PyrObject*) devstring);
			//usage
			HIDGetUsageName (devElement->usagePage, devElement->usage, cstrElementName);
			//devstring = newPyrString(g->gc, cstrElementName, 0, true);
			//SetObject(devElementArray->slots+devElementArray->size++, devstring);
			//g->gc->GCWrite(devElementArray, (PyrObject*) devstring);
			//cookie
			//SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->cookie);
			//SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->min);
			//SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->max);
			
			//SetObject(devAllElementsArray->slots+devAllElementsArray->size++, devElementArray);
			//g->gc->GCWrite(devAllElementsArray, (PyrObject*) devElementArray);
			
			devElement =  HIDGetNextDeviceElement (devElement, kHIDElementTypeInput);
		}
		//SetObject(a, devAllElementsArray);

		return (0);	
}

int prHIDBuildDeviceList()
{
	int i,err;
	UInt32 usagePage, usage;
/*
	//build a device list
	PyrSlot *a = g->sp - 2;
	PyrSlot *b = g->sp - 1; //usagePage
	PyrSlot *c = g->sp;		//usage

	if(IsNil(b)) 
		usagePage = NULL;
	else
	{	
		err = slotIntVal(b, &usagePage);
		if (err) return err;
	}
	if(IsNil(c)) 
		usage = NULL;
	else
	{
		err = slotIntVal(c, &usage);
		if (err) return err;
	}

	//pass in usage & usagepage
	//kHIDUsage_GD_Joystick kHIDUsage_GD_GamePad
	*/
	usagePage = kHIDPage_GenericDesktop;
	usage = NULL;

	Boolean result = HIDBuildDeviceList (usagePage, usage); 
	// returns false if no device found (ignored in this case) - returns always false ?

	if(result) post("no HID devices found\n");
	
	int numdevs = HIDCountDevices();
	gNumberOfHIDDevices = numdevs;
	// exit if no devices found
	if(!numdevs) return (0);

	post("number of devices: %d", numdevs);
	char cstrDeviceName [256];
	
	pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	pRecElement devElement;
	//PyrObject* allDevsArray = newPyrArray(g->gc, numdevs * sizeof(PyrObject), 0 , true);
	for(i=0; i<numdevs; i++)
	{
		/*
		//device:
		/PyrObject* devNameArray = newPyrArray(g->gc, 6 * sizeof(PyrObject), 0 , true);
		//manufacturer:
		PyrString *devstring = newPyrString(g->gc, pCurrentHIDDevice->manufacturer, 0, true);
		SetObject(devNameArray->slots+devNameArray->size++, devstring);
		g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
		//product name:
		devstring = newPyrString(g->gc, pCurrentHIDDevice->product, 0, true);
		SetObject(devNameArray->slots+devNameArray->size++, devstring);
		g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
		*/
		//usage
		HIDGetUsageName (pCurrentHIDDevice->usagePage, pCurrentHIDDevice->usage, cstrDeviceName);
		/*
		devstring = newPyrString(g->gc, cstrDeviceName, 0, true);
		SetObject(devNameArray->slots+devNameArray->size++, devstring);
		g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
		//vendor id
		SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->vendorID);
		//product id
		SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->productID);
		//locID
		SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->locID);
		
		SetObject(allDevsArray->slots+allDevsArray->size++, devNameArray);
		g->gc->GCWrite(allDevsArray, (PyrObject*) devNameArray);
		*/
		pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);

	}

	//UInt32 outnum = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeOutput);
	//post("number of outputs: %d \n", outnum);
//	SetObject(a, allDevsArray);

	return (0);	
}

/*
int prHIDGetValue(VMGlobals *g);
int prHIDGetValue(VMGlobals *g)
{
	PyrSlot *a = g->sp - 2; //class
	PyrSlot *b = g->sp - 1; //locID device
	PyrSlot *c = g->sp; //element cookie
	int locID, cookieNum;
	int err = slotIntVal(b, &locID);
	if (err) return err;
	err = slotIntVal(c, &cookieNum);
	if (err) return err;
	IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum;
	// look for the right device: 
    pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID))
        pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
	if(!pCurrentHIDDevice) return (1);
	// look for the right element:
	pRecElement pCurrentHIDElement =  HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO);
	// use gElementCookie to find current element
    while (pCurrentHIDElement && (pCurrentHIDElement->cookie != cookie))
        pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeIO);
		
	if (pCurrentHIDElement)
    {
		SInt32 value = HIDGetElementValue (pCurrentHIDDevice, pCurrentHIDElement);
		 // if it's not a button and it's not a hatswitch then calibrate
		if(( pCurrentHIDElement->type != kIOHIDElementTypeInput_Button ) &&
			( pCurrentHIDElement->usagePage == 0x01 && pCurrentHIDElement->usage != kHIDUsage_GD_Hatswitch)) 
			value = HIDCalibrateValue ( value, pCurrentHIDElement );
		SetInt(a, value);
	}
	else SetNil(a);
	return (0);	
	
}
*/
void PushQueueEvents_RawValue ()
{
	int i;
	
	IOHIDEventStruct event;
	pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	int numdevs = gNumberOfHIDDevices;
	unsigned char result;
	for(i=0; i< numdevs; i++)
	{
		result = HIDGetEvent(pCurrentHIDDevice, (void*) &event);
		if(result) 
		{
			SInt32 value = event.value;
			int vendorID = pCurrentHIDDevice->vendorID;
			int productID = pCurrentHIDDevice->productID;			
			int locID = pCurrentHIDDevice->locID;
			IOHIDElementCookie cookie = (IOHIDElementCookie) event.elementCookie;
			//set arguments: 
//			++g->sp;SetInt(g->sp, vendorID); 
//			++g->sp;SetInt(g->sp, productID); 			
//			++g->sp;SetInt(g->sp, locID); 
//			++g->sp;SetInt(g->sp, (int) cookie); 
//			++g->sp;SetInt(g->sp, value); 
		}
		pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice);
	}
}

void PushQueueEvents_CalibratedValue ()
{
	int i;
	
	IOHIDEventStruct event;
	pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	
	int numdevs = gNumberOfHIDDevices;
	unsigned char result;
	for(i=0; i< numdevs; i++)
	{

		result = HIDGetEvent(pCurrentHIDDevice, (void*) &event);
		if(result) 
		{
			SInt32 value = event.value;
			int vendorID = pCurrentHIDDevice->vendorID;
			int productID = pCurrentHIDDevice->productID;			
			int locID = pCurrentHIDDevice->locID;
			IOHIDElementCookie cookie = (IOHIDElementCookie) event.elementCookie;
			pRecElement pCurrentHIDElement =  HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO);
	// use gElementCookie to find current element
			while (pCurrentHIDElement && ( (pCurrentHIDElement->cookie) != cookie))
				pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeIO);
		
			if (pCurrentHIDElement)
			{
			value = HIDCalibrateValue(value, pCurrentHIDElement);
			//find element to calibrate
			//set arguments: 
//			++g->sp;SetInt(g->sp, vendorID); 
//			++g->sp;SetInt(g->sp, productID); 			
//			++g->sp;SetInt(g->sp, locID); 
//			++g->sp;SetInt(g->sp, (int) cookie); 
//			++g->sp;SetInt(g->sp, value); 
			}
		}
		pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice);
	}
}

static pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData)
{
	#pragma unused (inTimer, userData)
	PushQueueEvents_CalibratedValue ();
}

int prHIDReleaseDeviceList()
{
	releaseHIDDevices();
	return (0);	
}

static EventLoopTimerUPP GetTimerUPP (void)
{
	static EventLoopTimerUPP	sTimerUPP = NULL;
	
	if (sTimerUPP == NULL)
		sTimerUPP = NewEventLoopTimerUPP (IdleTimer);
	
	return sTimerUPP;
}
/*
typedef void (*IOHIDCallbackFunction)
              (void * target, IOReturn result, void * refcon, void * sender);

*/
/*
void callback  (void * target, IOReturn result, void * refcon, void * sender);
void callback  (void * target, IOReturn result, void * refcon, void * sender)
{
}
*/
/* 
int prHIDRunEventLoop(VMGlobals *g);
int prHIDRunEventLoop(VMGlobals *g)
{
	PyrSlot *a = g->sp - 1; //class

	InstallEventLoopTimer (GetCurrentEventLoop(), 0, 0.001, GetTimerUPP (), 0, &gTimer);

	//HIDSetQueueCallback(pCurrentHIDDevice, callback);
	return (0);	
}
*/

int prHIDQueueDevice()
{
	int locID, cookieNum;
	
	//PyrSlot *a = g->sp - 1; //class
	//PyrSlot *b = g->sp; //locID device
	//int err = slotIntVal(b, &locID);
	//if (err) return err;
	//look for the right device: 
	pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID))
		pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
	if(!pCurrentHIDDevice) return (1);
	HIDQueueDevice(pCurrentHIDDevice);
	return (0);	
}

int prHIDQueueElement()
{
	int locID, cookieNum;
	
	//PyrSlot *a = g->sp - 2; //class
	//PyrSlot *b = g->sp - 1; //locID device
	//PyrSlot *c = g->sp; //element cookie
	//int err = slotIntVal(b, &locID);
	//if (err) return err;
	//err = slotIntVal(c, &cookieNum);
	//if (err) return err;
	IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum;
	//look for the right device: 
	pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID))
		pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
	if(!pCurrentHIDDevice) return (1);
	//look for the right element:
	pRecElement pCurrentHIDElement =  HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO);
	// use gElementCookie to find current element
	while (pCurrentHIDElement && (pCurrentHIDElement->cookie != cookie))
		pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeIO);
	if(!pCurrentHIDElement) return (1);
	HIDQueueElement(pCurrentHIDDevice, pCurrentHIDElement);
	return (0);	
}

int prHIDDequeueElement()
{
	int locID, cookieNum;
	
	//PyrSlot *a = g->sp - 2; //class
	//PyrSlot *b = g->sp - 1; //locID device
	//PyrSlot *c = g->sp; //element cookie
	//int err = slotIntVal(b, &locID);
	//if (err) return err;
	//err = slotIntVal(c, &cookieNum);
	//if (err) return err;
	IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum;
	//look for the right device: 
    pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID))
        pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
	if(!pCurrentHIDDevice) return (1);
	//look for the right element:
	pRecElement pCurrentHIDElement =  HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO);
    while (pCurrentHIDElement && (pCurrentHIDElement->cookie != cookie))
        pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeIO);
	if(!pCurrentHIDElement) return (1);
	HIDDequeueElement(pCurrentHIDDevice, pCurrentHIDElement);
	return (0);	
}

int prHIDDequeueDevice()
{
	int locID, cookieNum;
	
	/*
	PyrSlot *a = g->sp - 1; //class
	PyrSlot *b = g->sp; //locID device
	int err = slotIntVal(b, &locID);
	if (err) return err;
	*/
	//look for the right device: 
	pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID))
		pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);
	if(!pCurrentHIDDevice) return (1);
	HIDDequeueDevice(pCurrentHIDDevice);
	return (0);	
}

int prHIDStopEventLoop()
{
	if (gTimer)
        RemoveEventLoopTimer(gTimer);
	gTimer = NULL;
	return (0);	
}



--- NEW FILE: hid.h ---

#include <m_pd.h>

#include "input_arrays.h"

static char *version = "$Revision: 1.1 $";

/*------------------------------------------------------------------------------
 *  CLASS DEF
 */
static t_class *hid_class;

typedef struct _hid 
{
		t_object            x_obj;
		t_int               x_fd;
		t_symbol            *x_devname;
		t_clock             *x_clock;
		t_int               x_read_ok;
		t_int               x_started;
		t_int               x_delay;
		t_int               x_vendorID;
		t_int               x_productID;
		t_int               x_locID;
} t_hid;


Index: hid.c
===================================================================
RCS file: /cvsroot/pure-data/externals/hcs/hid/hid.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** hid.c	20 Oct 2004 02:06:08 -0000	1.3
--- hid.c	22 Oct 2004 05:43:17 -0000	1.4
***************
*** 26,82 ****
  /* ---------------------------------------------------------------------------- */
  
! 
! #include <stdio.h>
! #include <stdlib.h>
! #include <unistd.h>
! #include <ctype.h>
! 
! #ifdef __APPLE__
! #include <sys/errno.h>
! #include <sysexits.h>
! #include <mach/mach.h>
! #include <mach/mach_error.h>
! #include <IOKit/IOKitLib.h>
! #include <IOKit/IOCFPlugIn.h>
! #include <IOKit/hid/IOHIDLib.h>
! #include <IOKit/hid/IOHIDKeys.h>
! #include <IOKit/hid/IOHIDUsageTables.h>
! #include <CoreFoundation/CoreFoundation.h>
! #include <Carbon/Carbon.h>
! 
! #ifndef __APPLE_CC__
! #include "Carbon_Include.h"
! #endif  /* #ifndef __APPLE_CC__ */
! 
! #include <HID_Utilities.h>
! #endif  /* #ifdef __APPLE__ */
! 
! #include "linuxhid.h"
! #include "input_arrays.h"
! 
! static char *version = "$Revision$";
! 
! /*------------------------------------------------------------------------------
!  *  CLASS DEF
!  */
! static t_class *hid_class;
! 
! typedef struct _hid 
! {
!   t_object            x_obj;
!   t_int               x_fd;
!   t_symbol            *x_devname;
!   t_clock             *x_clock;
!   t_int               x_read_ok;
!   t_int               x_started;
!   t_int               x_delay;
! #ifdef __gnu_linux__
!   struct input_event  x_input_event; 
! #elif defined (__APPLE__)
!   IOHIDEventStruct event;
! #endif
!   t_outlet            *x_event_outlet;
! }t_hid;
! 
  
  /*------------------------------------------------------------------------------
--- 26,31 ----
  /* ---------------------------------------------------------------------------- */
  
! #include "hid.h"
! #include "../linuxhid.h"
  
  /*------------------------------------------------------------------------------
***************
*** 114,117 ****
--- 63,69 ----
  	t_int eventType, eventCode;
  	char *eventTypeName = "";
+ #ifdef __linux__
+ 	struct input_event hid_input_event;
+ #endif
  	/* counts for various event types */
  	t_int synCount,keyCount,relCount,absCount,mscCount,ledCount,sndCount,repCount,ffCount,pwrCount,ff_statusCount;
***************
*** 148,152 ****
     * It seems that is just there to flush the input event queue
     */
!   while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1);
    
    /* get name of device */
--- 100,104 ----
     * It seems that is just there to flush the input event queue
     */
!   while (read (x->x_fd, &(hid_input_event), sizeof(struct input_event)) > -1);
    
    /* get name of device */
***************
*** 252,273 ****
  	char *eventType;
  	char *eventCode;
  
- #ifdef __gnu_linux__
  	if (x->x_fd < 0) return 0;
  
! 	while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1) 
  	{
  		/* build event_data list from event data */
! 		SETSYMBOL(event_data, gensym(ev[x->x_input_event.type]));
! 		SETSYMBOL(event_data + 1, gensym(event_names[x->x_input_event.type][x->x_input_event.code]));
! 		SETFLOAT(event_data + 2, (t_float)x->x_input_event.value);
! 		SETFLOAT(event_data + 3, (t_float)(x->x_input_event.time).tv_sec);
  		outlet_anything(x->x_obj.te_outlet,atom_gensym(event_data),3,event_data+1); 
  	}
  #endif /* #ifdef__gnu_linux__ */
! #ifdef __APPLE__
  	pRecDevice pCurrentHIDDevice = GetSetCurrentDevice (gWindow);
  	pRecElement pCurrentHIDElement = GetSetCurrenstElement (gWindow);
! 	r/l
  	// if we have a good device and element which is not a collecion
  	if (pCurrentHIDDevice && pCurrentHIDElement && (pCurrentHIDElement->type != kIOHIDElementTypeCollection))
--- 204,226 ----
  	char *eventType;
  	char *eventCode;
+ #ifdef __linux__
+ 	struct input_event hid_input_event;
  
  	if (x->x_fd < 0) return 0;
  
! 	while (read (x->x_fd, &(hid_input_event), sizeof(struct input_event)) > -1) 
  	{
  		/* build event_data list from event data */
! 		SETSYMBOL(event_data, gensym(ev[hid_input_event.type]));
! 		SETSYMBOL(event_data + 1, gensym(event_names[hid_input_event.type][hid_input_event.code]));
! 		SETFLOAT(event_data + 2, (t_float)hid_input_event.value);
! 		SETFLOAT(event_data + 3, (t_float)(hid_input_event.time).tv_sec);
  		outlet_anything(x->x_obj.te_outlet,atom_gensym(event_data),3,event_data+1); 
  	}
  #endif /* #ifdef__gnu_linux__ */
! #ifdef IGNOREIGNOREIGNORE
  	pRecDevice pCurrentHIDDevice = GetSetCurrentDevice (gWindow);
  	pRecElement pCurrentHIDElement = GetSetCurrenstElement (gWindow);
! 
  	// if we have a good device and element which is not a collecion
  	if (pCurrentHIDDevice && pCurrentHIDElement && (pCurrentHIDElement->type != kIOHIDElementTypeCollection))
***************
*** 365,369 ****
    x->x_clock = clock_new(x, (t_method)hid_read);
  
!   /* create anything outlet */ 
    outlet_new(&x->x_obj, 0);
    
--- 318,322 ----
    x->x_clock = clock_new(x, (t_method)hid_read);
  
!   /* create anything outlet used for HID data */ 
    outlet_new(&x->x_obj, 0);
    





More information about the Pd-cvs mailing list