Created
November 17, 2009 10:02
-
-
Save lericson/236799 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import with_statement | |
# {{{ MultitouchSupport | |
import time | |
import ctypes | |
import threading | |
from ctypes.util import find_library | |
CFArrayRef = ctypes.c_void_p | |
CFMutableArrayRef = ctypes.c_void_p | |
CFIndex = ctypes.c_long | |
MultitouchSupport = ctypes.CDLL("/System/Library/PrivateFrameworks/MultitouchSupport.framework/MultitouchSupport") | |
CFArrayGetCount = MultitouchSupport.CFArrayGetCount | |
CFArrayGetCount.argtypes = [CFArrayRef] | |
CFArrayGetCount.restype = CFIndex | |
CFArrayGetValueAtIndex = MultitouchSupport.CFArrayGetValueAtIndex | |
CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex] | |
CFArrayGetValueAtIndex.restype = ctypes.c_void_p | |
MTDeviceCreateList = MultitouchSupport.MTDeviceCreateList | |
MTDeviceCreateList.argtypes = [] | |
MTDeviceCreateList.restype = CFMutableArrayRef | |
class MTPoint(ctypes.Structure): | |
_fields_ = [("x", ctypes.c_float), | |
("y", ctypes.c_float)] | |
class MTVector(ctypes.Structure): | |
_fields_ = [("position", MTPoint), | |
("velocity", MTPoint)] | |
class MTData(ctypes.Structure): | |
_fields_ = [ | |
("frame", ctypes.c_int), | |
("timestamp", ctypes.c_double), | |
("identifier", ctypes.c_int), | |
("state", ctypes.c_int), # Current state (of unknown meaning). | |
("unknown1", ctypes.c_int), | |
("unknown2", ctypes.c_int), | |
("normalized", MTVector), # Normalized position and vector of | |
# the touch (0 to 1). | |
("size", ctypes.c_float), # The area of the touch. | |
("unknown3", ctypes.c_int), | |
# The following three define the ellipsoid of a finger. | |
("angle", ctypes.c_float), | |
("major_axis", ctypes.c_float), | |
("minor_axis", ctypes.c_float), | |
("unknown4", MTVector), | |
("unknown5_1", ctypes.c_int), | |
("unknown5_2", ctypes.c_int), | |
("unknown6", ctypes.c_float), | |
] | |
MTDataRef = ctypes.POINTER(MTData) | |
MTContactCallbackFunction = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, MTDataRef, | |
ctypes.c_int, ctypes.c_double, ctypes.c_int) | |
MTDeviceRef = ctypes.c_void_p | |
MTRegisterContactFrameCallback = MultitouchSupport.MTRegisterContactFrameCallback | |
MTRegisterContactFrameCallback.argtypes = [MTDeviceRef, MTContactCallbackFunction] | |
MTRegisterContactFrameCallback.restype = None | |
MTDeviceStart = MultitouchSupport.MTDeviceStart | |
MTDeviceStart.argtypes = [MTDeviceRef, ctypes.c_int] | |
MTDeviceStart.restype = None | |
MTDeviceStop = MultitouchSupport.MTDeviceStop | |
MTDeviceStop.argtypes = [MTDeviceRef] | |
#MTDeviceStop.restype = None | |
def _cfarray_to_list(arr): | |
rv = [] | |
n = CFArrayGetCount(arr) | |
for i in xrange(n): | |
rv.append(CFArrayGetValueAtIndex(arr, i)) | |
return rv | |
# }}} | |
from Queue import Queue | |
touches_lock = threading.Lock() | |
touches = [] | |
def init_multitouch(cb): | |
devices = _cfarray_to_list(MultitouchSupport.MTDeviceCreateList()) | |
for device in devices: | |
MTRegisterContactFrameCallback(device, cb) | |
MTDeviceStart(device, 0) | |
return devices | |
def stop_multitouch(devices): | |
for device in devices: | |
MTDeviceStop(device) | |
@MTContactCallbackFunction | |
def touch_callback(device, data_ptr, n_fingers, timestamp, frame): | |
fingers = [] | |
for i in xrange(n_fingers): | |
fingers.append(data_ptr[i]) | |
touches[:] = [(frame, timestamp, fingers)] | |
return 0 | |
import pygame | |
from pygame import draw, display, mouse | |
from pygame.locals import * | |
from numpy import * | |
pygame.init() | |
#n_samples = 22050 * 4 | |
#sa = zeros((n_samples, 2)) | |
#sound = sndarray.make_sound(sa) | |
#sa = sndarray.samples(sound) | |
#sound.play(-1) | |
devs = init_multitouch(touch_callback) | |
flags = FULLSCREEN | HWSURFACE | DOUBLEBUF | |
mode = max(display.list_modes(0, flags)) | |
display.set_mode(mode, flags) | |
#display.set_mode((640, 480)) | |
screen = display.get_surface() | |
width, height = screen.get_size() | |
mouse.set_visible(False) | |
fingers = [] | |
while True: | |
if touches: | |
frame, timestamp, fingers = touches.pop() | |
#print frame, timestamp | |
screen.fill((0xef, 0xef, 0xef)) | |
prev = None | |
for i, finger in enumerate(fingers): | |
pos = finger.normalized.position | |
vel = finger.normalized.velocity | |
x = int(pos.x * width) | |
y = int((1 - pos.y) * height) | |
p = (x, y) | |
r = int(finger.size * 10) | |
#print "finger", i, "at", (x, y) | |
#xofs = int(finger.minor_axis / 2) | |
#yofs = int(finger.major_axis / 2) | |
if prev: | |
draw.line(screen, (0xd0, 0xd0, 0xd0), p, prev[0], 3) | |
draw.circle(screen, 0, prev[0], prev[1], 0) | |
prev = p, r | |
draw.circle(screen, 0, p, r, 0) | |
#draw.ellipse(screen, 0, (x - xofs, y - yofs, xofs * 2, yofs * 2)) | |
#sa[int(pos.x * n_samples)] = int(-32768 + pos.y * 65536) | |
vx = vel.x | |
vy = -vel.y | |
posvx = x + vx / 10 * width | |
posvy = y + vy / 10 * height | |
draw.line(screen, 0, p, (posvx, posvy)) | |
# EXIT! One finger still, four motioning quickly downward. | |
if len(fingers) == 5: | |
n_still = 0 | |
n_down = 0 | |
for i, finger in enumerate(fingers): | |
vel = finger.normalized.velocity | |
#print i, "%.2f, %.2f" % (vel.x, vel.y) | |
t = 0.1 | |
if -t <= vel.x < t and -t <= vel.y < t: | |
n_still += 1 | |
elif -2 <= vel.x < 2 and vel.y < -4: | |
n_down += 1 | |
if n_still == 1 and n_down == 4: | |
break | |
display.flip() | |
stop_multitouch(devs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment