aboutsummaryrefslogtreecommitdiff
path: root/multitouch.c
blob: 0b9b0a779a52b08272b91214a3b029d25d015df4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* --------------------------------------------------------------------------*/
/*                                                                           */
/* get info from the multitouch trackpad on Apple Mac OS X                   */
/* based on 'fingerpinger'                                                  */
/*                                                                           */
/* Copyright (c) 2009 Hans-Christoph Steiner                                 */
/* Copyright (c) 2009 Michael & Max Egger                                    */
/* Copyright (c) 2008 Steike                                                 */
/*                                                                           */
/* 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 3            */
/* of the License, or (at your option) any later version.                    */
/*                                                                           */
/* See file LICENSE for further informations on licensing terms.             */
/*                                                                           */
/* 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,   */
/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
/*                                                                           */
/* --------------------------------------------------------------------------*/

#include <mach/mach.h> 
#include <IOKit/IOKitLib.h> 
#include <CoreFoundation/CoreFoundation.h> 
#include <math.h>
#include <unistd.h>
#include "MultitouchSupport.h"
#include <m_pd.h>

//#define DEBUG(x)
#define DEBUG(x) x 

/*------------------------------------------------------------------------------
 *  CLASS DEF
 */

static t_class *multitouch_class;

typedef struct _multitouch {
    t_object            x_obj;
    t_outlet*           data_outlet;
    t_outlet*           status_outlet;
} t_multitouch;

static MTDeviceRef dev;      /* reference to the trackpad */
static int fingerc;  /* current count of Fingers */
static Finger fingerv[32];  /* current list of Fingers */
static int polling = 0; /* set when one instance is polling so others don't */

/*------------------------------------------------------------------------------
 * CALLBACK TO GET DATA
 */

static int callback(int device, Finger *data, int nFingers, double timestamp, int frame) 
{
	DEBUG(post("callback"););
    memcpy(fingerv, data, nFingers * sizeof(Finger));
    fingerc = nFingers;
    return 0;
}

/*------------------------------------------------------------------------------
 * IMPLEMENTATION                    
 */

static void multitouch_output(t_multitouch* x)
{
	DEBUG(post("multitouch_output"););
	int i;
	t_atom output_list[12];
	for (i=0; i < fingerc; i++) {
		Finger *f = &fingerv[i];
		SETFLOAT(output_list,i);
		SETFLOAT(output_list + 1 , f->frame);
		SETFLOAT(output_list + 2 , f->angle);
		SETFLOAT(output_list + 3 , f->majorAxis);
		SETFLOAT(output_list + 4 , f->minorAxis);
		SETFLOAT(output_list + 5 , f->normalized.pos.x);
		SETFLOAT(output_list + 6 , f->normalized.pos.y);
		SETFLOAT(output_list + 7 , f->normalized.vel.x);
		SETFLOAT(output_list + 8 , f->normalized.vel.y);
		SETFLOAT(output_list + 9 , f->identifier);
		SETFLOAT(output_list + 10 , f->state);
		SETFLOAT(output_list + 11 , f->size);
        outlet_list(x->data_outlet, &s_, 12, output_list);
    }
}


static void multitouch_float(t_multitouch* x, t_float f)
{
	DEBUG(post("multitouch_float"););
	if (f > 0) {
        polling++;
        /* if I am the first instance to poll, then set the callback up */
		if (polling == 1) {
			dev = MTDeviceCreateDefault();
		  	MTRegisterContactFrameCallback(dev, callback);
		  	MTDeviceStart(dev, 0);
		}
	} else {
        polling--;
        /* if I am the last instance, clean up the callback stuff */
		if (polling == 0) {
			MTDeviceStop(dev);
		  	MTUnregisterContactFrameCallback(dev, callback);
			MTDeviceRelease(dev);
			dev = NULL;
		}
	}
}


static void multitouch_free(t_multitouch* x)
{
	DEBUG(post("multitouch_free"););
    /* make sure callback is released before deleting the object */
	multitouch_float(x, 0);
}

static void *multitouch_new(void) 
{
	DEBUG(post("multitouch_new"););
	t_multitouch *x = (t_multitouch *)pd_new(multitouch_class);

    x->data_outlet = outlet_new(&x->x_obj, &s_list);
	x->status_outlet = outlet_new(&x->x_obj, &s_anything);

	return (x);
}

void multitouch_setup(void) 
{
	multitouch_class = class_new(gensym("multitouch"), 
                                        (t_newmethod)multitouch_new,
                                        (t_method)multitouch_free,
                                        sizeof(t_multitouch), 
                                        CLASS_DEFAULT,
                                        0);
	/* add inlet datatype methods */
	class_addbang(multitouch_class,(t_method) multitouch_output);
	class_addfloat(multitouch_class,(t_method) multitouch_float);
}