diff --git a/configure.ac b/configure.ac index 1f0ebc47c61874bc857ebba6413bf0b07b0aa417..4171971aef15c1c915ab356e7228ec3ce5daf2eb 100644 --- a/configure.ac +++ b/configure.ac @@ -173,6 +173,7 @@ case "${host_os}" in VLC_ADD_LDFLAGS([mkv mp4], [-framework IOKit -framework CoreFoundation]) VLC_ADD_CFLAGS([libvlc vlc],[-x objective-c]) VLC_ADD_LDFLAGS([vlc],[-undefined dynamic_lookup]) + VLC_ADD_LDFLAGS([motion],[-framework IOKit -framework CoreFoundation]) AC_ARG_ENABLE(macosx-defaults, [ --enable-macosx-defaults Build the default configuration on Mac OS X (default enabled)]) if test "x${enable_macosx_defaults}" != "xno" @@ -3330,7 +3331,6 @@ AS_IF([test "${enable_libtar}" != "no"],[ ] ) ]) - dnl dnl A52/AC3 decoder plugin dnl diff --git a/modules/control/Modules.am b/modules/control/Modules.am index bc50699f150220198240d420a667f23d210fa475..c982b05d77dab9c263270035d1400e6671e823b2 100644 --- a/modules/control/Modules.am +++ b/modules/control/Modules.am @@ -6,5 +6,14 @@ SOURCES_ntservice = ntservice.c SOURCES_hotkeys = hotkeys.c SOURCES_lirc = lirc.c SOURCES_rc = rc.c -SOURCES_motion = motion.c SOURCES_dbus = dbus.c dbus.h +if HAVE_DARWIN +motion_extra = unimotion.c unimotion.h +else +motion_extra = $(NULL) +endif +SOURCES_motion = \ + motion.c \ + $(motion_extra) \ + $(NULL) + diff --git a/modules/control/motion.c b/modules/control/motion.c index 4541551eea7d92a72612704d4a053065d370f5b2..783af9fe1cc0bdb0387d0d1fd63a7b2a85591a99 100644 --- a/modules/control/motion.c +++ b/modules/control/motion.c @@ -1,10 +1,11 @@ /***************************************************************************** * motion.c: control VLC with laptop built-in motion sensors ***************************************************************************** - * Copyright (C) 2006 the VideoLAN team + * Copyright (C) 2006 - 2007 the VideoLAN team * $Id$ * * Author: Sam Hocevar + * Jérôme Decoodt (unimotion integration) * * 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 @@ -26,6 +27,7 @@ *****************************************************************************/ #include /* malloc(), free() */ #include +#include #include #include @@ -35,12 +37,17 @@ # include #endif +#ifdef __APPLE__ +#include "unimotion.h" +#endif + /***************************************************************************** * intf_sys_t: description and status of interface *****************************************************************************/ struct intf_sys_t { - enum { NO_SENSOR, HDAPS_SENSOR, AMS_SENSOR } sensor; + enum { NO_SENSOR, HDAPS_SENSOR, AMS_SENSOR, UNIMOTION_SENSOR } sensor; + enum sms_hardware unimotion_hw; int i_calibrate; @@ -110,6 +117,10 @@ int Open ( vlc_object_t *p_this ) /* Apple Motion Sensor support */ p_intf->p_sys->sensor = AMS_SENSOR; } +#ifdef __APPLE__ + else if( p_intf->p_sys->unimotion_hw = detect_sms() ) + p_intf->p_sys->sensor = UNIMOTION_SENSOR; +#endif else { /* No motion sensor support */ @@ -136,14 +147,17 @@ void Close ( vlc_object_t *p_this ) /***************************************************************************** * RunIntf: main loop *****************************************************************************/ +#define FILTER_LENGTH 16 +#define LOW_THRESHOLD 800 +#define HIGH_THRESHOLD 1000 static void RunIntf( intf_thread_t *p_intf ) { - int i_x, i_oldx = 0; + int i_x, i_oldx = 0, i_sum = 0, i = 0; + int p_oldx[FILTER_LENGTH]; + memset( p_oldx, 0, FILTER_LENGTH * sizeof( int ) ); while( !intf_ShouldDie( p_intf ) ) { -#define LOW_THRESHOLD 80 -#define HIGH_THRESHOLD 100 vout_thread_t *p_vout; const char *psz_filter, *psz_type; vlc_bool_t b_change = VLC_FALSE; @@ -152,6 +166,10 @@ static void RunIntf( intf_thread_t *p_intf ) msleep( INTF_IDLE_SLEEP ); i_x = GetOrientation( p_intf ); + i_sum += i_x - p_oldx[i]; + p_oldx[i++] = i_x; + if( i == FILTER_LENGTH ) i = 0; + i_x = i_sum / FILTER_LENGTH; if( p_intf->p_sys->b_use_rotate ) { @@ -162,7 +180,8 @@ static void RunIntf( intf_thread_t *p_intf ) vlc_object_find_name( p_intf->p_libvlc, "rotate", FIND_CHILD ); if( p_obj ) { - var_SetInteger( p_obj, "rotate-angle",((360+i_x/2)%360) ); + var_SetInteger( p_obj, "rotate-deciangle", + ((3600+i_x/2)%3600) ); i_oldx = i_x; vlc_object_release( p_obj ); } @@ -209,14 +228,17 @@ static void RunIntf( intf_thread_t *p_intf ) i_oldx = i_x; } } +#undef FILTER_LENGTH +#undef LOW_THRESHOLD +#undef HIGH_THRESHOLD /***************************************************************************** - * GetOrientation: get laptop orientation, range -180 / +180 + * GetOrientation: get laptop orientation, range -1800 / +1800 *****************************************************************************/ static int GetOrientation( intf_thread_t *p_intf ) { FILE *f; - int i_x, i_y; + int i_x, i_y, i_z; switch( p_intf->p_sys->sensor ) { @@ -231,7 +253,7 @@ static int GetOrientation( intf_thread_t *p_intf ) fscanf( f, "(%d,%d)", &i_x, &i_y ); fclose( f ); - return i_x - p_intf->p_sys->i_calibrate; + return ( i_x - p_intf->p_sys->i_calibrate ) * 10; case AMS_SENSOR: f = fopen( "/sys/devices/ams/x", "r" ); @@ -243,8 +265,23 @@ static int GetOrientation( intf_thread_t *p_intf ) fscanf( f, "%d", &i_x); fclose( f ); - return - i_x * 3; /* FIXME: arbitrary */ - + return - i_x * 30; /* FIXME: arbitrary */ +#ifdef __APPLE__ + case UNIMOTION_SENSOR: + if( read_sms_raw( p_intf->p_sys->unimotion_hw, &i_x, &i_y, &i_z ) ) + { + double d_norm = sqrt( i_x*i_x+i_z*i_z ); + if( d_norm < 100 ) + return 0; + double d_x = i_x / d_norm; + if( i_z > 0 ) + return -asin(d_x)*3600/3.141; + else + return 3600 + asin(d_x)*3600/3.141; + } +#endif + else + return 0; default: return 0; } diff --git a/modules/control/unimotion.c b/modules/control/unimotion.c new file mode 100644 index 0000000000000000000000000000000000000000..331f7fc99e5efe21dc022eb2e3a979b91c6819f4 --- /dev/null +++ b/modules/control/unimotion.c @@ -0,0 +1,310 @@ + /* + * UniMotion - Unified Motion detection for Apple portables. + * + * Copyright (c) 2006 Lincoln Ramsay. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation Inc. 59 Temple Place, Suite 330, Boston MA 02111-1307 USA + */ + +/* + * HISTORY of Motion + * Written by Christian Klein + * Modified for iBook compatibility by Pall Thayer + * Modified for Hi Res Powerbook compatibility by Pall Thayer + * Modified for MacBook Pro compatibility by Randy Green + * Disparate forks unified into UniMotion by Lincoln Ramsay + */ + +// This license applies to the portions created by Cristian Klein. +/* motion.c + * + * a little program to display the coords returned by + * the powerbook motion sensor + * + * A fine piece of c0de, brought to you by + * + * ---===--- + * *** teenage mutant ninja hero coders *** + * ---===--- + * + * All of the software included is copyrighted by Christian Klein . + * + * Copyright 2005 Christian Klein. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author must not be used to endorse or promote + * products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifdef __APPLE__ + +#include "unimotion.h" +#include +#include +#include +#include + +enum data_type { + PB_IB, + MBP +}; + +struct pb_ib_data { + int8_t x; + int8_t y; + int8_t z; + int8_t pad[57]; +}; + +struct mbp_data { + int16_t x; + int16_t y; + int16_t z; + int8_t pad[34]; +}; + +union motion_data { + struct pb_ib_data pb_ib; + struct mbp_data mbp; +}; + + +static int set_values(int type, int *kernFunc, char **servMatch, int *dataType) +{ + switch ( type ) { + case powerbook: + *kernFunc = 21; + *servMatch = "IOI2CMotionSensor"; + *dataType = PB_IB; + break; + case ibook: + *kernFunc = 21; + *servMatch = "IOI2CMotionSensor"; + *dataType = PB_IB; + break; + case highrespb: + *kernFunc = 21; + *servMatch = "PMUMotionSensor"; + *dataType = PB_IB; + break; + case macbookpro: + *kernFunc = 5; + *servMatch = "SMCMotionSensor"; + *dataType = MBP; + break; + default: + return 0; + } + + return 1; +} + +static int probe_sms(int kernFunc, char *servMatch, int dataType, void *data) +{ + kern_return_t result; + mach_port_t masterPort; + io_iterator_t iterator; + io_object_t aDevice; + io_connect_t dataPort; + + IOItemCount structureInputSize; + IOByteCount structureOutputSize; + + union motion_data inputStructure; + union motion_data *outputStructure; + + outputStructure = (union motion_data *)data; + + result = IOMasterPort(MACH_PORT_NULL, &masterPort); + + CFMutableDictionaryRef matchingDictionary = IOServiceMatching(servMatch); + + result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator); + + if (result != KERN_SUCCESS) { + //fputs("IOServiceGetMatchingServices returned error.\n", stderr); + return 0; + } + + aDevice = IOIteratorNext(iterator); + IOObjectRelease(iterator); + + if (aDevice == 0) { + //fputs("No motion sensor available\n", stderr); + return 0; + } + + result = IOServiceOpen(aDevice, mach_task_self(), 0, &dataPort); + IOObjectRelease(aDevice); + + if (result != KERN_SUCCESS) { + //fputs("Could not open motion sensor device\n", stderr); + return 0; + } + + switch ( dataType ) { + case PB_IB: + structureInputSize = sizeof(struct pb_ib_data); + structureOutputSize = sizeof(struct pb_ib_data); + break; + case MBP: + structureInputSize = sizeof(struct mbp_data); + structureOutputSize = sizeof(struct mbp_data); + break; + default: + return 0; + } + + memset(&inputStructure, 0, sizeof(union motion_data)); + memset(outputStructure, 0, sizeof(union motion_data)); + + result = IOConnectMethodStructureIStructureO(dataPort, kernFunc, structureInputSize, + &structureOutputSize, &inputStructure, outputStructure); + + IOServiceClose(dataPort); + + if (result != KERN_SUCCESS) { + //puts("no coords"); + return 0; + } + return 1; +} + +int detect_sms() +{ + int kernFunc; + char *servMatch; + int dataType; + union motion_data data; + int i; + + for ( i = 1; ; i++ ) { + if ( !set_values(i, &kernFunc, &servMatch, &dataType) ) + break; + if ( probe_sms(kernFunc, servMatch, dataType, &data) ) + return i; + } + + return unknown; +} + +int read_sms_raw(int type, int *x, int *y, int *z) +{ + int kernFunc; + char *servMatch; + int dataType; + union motion_data data; + + if ( !set_values(type, &kernFunc, &servMatch, &dataType) ) + return 0; + if ( probe_sms(kernFunc, servMatch, dataType, &data) ) { + switch ( dataType ) { + case PB_IB: + if ( x ) *x = data.pb_ib.x; + if ( y ) *y = data.pb_ib.y; + if ( z ) *z = data.pb_ib.z; + break; + case MBP: + if ( x ) *x = data.mbp.x; + if ( y ) *y = data.mbp.y; + if ( z ) *z = data.mbp.z; + break; + default: + return 0; + } + return 1; + } + return 0; +} + +int read_sms(int type, int *x, int *y, int *z) +{ + int _x, _y, _z; + int xoff, yoff, zoff; + Boolean ok; + int ret; + + ret = read_sms_raw(type, &_x, &_y, &_z); + if ( !ret ) + return 0; + + static CFStringRef app = CFSTR("com.ramsayl.UniMotion"); + static CFStringRef xoffstr = CFSTR("x_offset"); + static CFStringRef yoffstr = CFSTR("y_offset"); + static CFStringRef zoffstr = CFSTR("z_offset"); + xoff = CFPreferencesGetAppIntegerValue(xoffstr, app, &ok); + if ( ok ) _x += xoff; + yoff = CFPreferencesGetAppIntegerValue(yoffstr, app, &ok); + if ( ok ) _y += yoff; + zoff = CFPreferencesGetAppIntegerValue(zoffstr, app, &ok); + if ( ok ) _z += zoff; + + *x = _x; + *y = _y; + *z = _z; + + return ret; +} + +int read_sms_real(int type, double *x, double *y, double *z) +{ + int _x, _y, _z; + int xscale, yscale, zscale; + int ret; + Boolean ok; + + ret = read_sms_raw(type, &_x, &_y, &_z); + if ( !ret ) + return 0; + + static CFStringRef app = CFSTR("com.ramsayl.UniMotion"); + static CFStringRef xscalestr = CFSTR("x_scale"); + static CFStringRef yscalestr = CFSTR("y_scale"); + static CFStringRef zscalestr = CFSTR("z_scale"); + xscale = CFPreferencesGetAppIntegerValue(xscalestr, app, &ok); + if ( !ok ) return 0; + yscale = CFPreferencesGetAppIntegerValue(yscalestr, app, &ok); + if ( !ok ) return 0; + zscale = CFPreferencesGetAppIntegerValue(zscalestr, app, &ok); + if ( !ok ) return 0; + + *x = _x / (double)xscale; + *y = _y / (double)yscale; + *z = _z / (double)zscale; + + return 1; +} + +#endif diff --git a/modules/control/unimotion.h b/modules/control/unimotion.h new file mode 100644 index 0000000000000000000000000000000000000000..4c7118a60bbe5e3d3d1bc05192dd01b1478a45f6 --- /dev/null +++ b/modules/control/unimotion.h @@ -0,0 +1,58 @@ +/* + * UniMotion - Unified Motion detection for Apple portables. + * + * Copyright (c) 2006 Lincoln Ramsay. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation Inc. 59 Temple Place, Suite 330, Boston MA 02111-1307 USA + */ +#ifndef UNIMOTION_H +#define UNIMOTION_H + +#ifdef __cplusplus +extern "C" { +#endif + +// The various SMS hardware that unimotion supports +enum sms_hardware { + unknown = 0, + powerbook = 1, + ibook = 2, + highrespb = 3, + macbookpro = 4 +}; + +// prototypes for the functions in unimotion.c + +// returns the value of SMS hardware present or unknown if no hardware is detected +int detect_sms(); + +// use the value returned from detect_sms as the type +// these functinos return 1 on success and 0 on failure +// they modify x, y and z if they are not 0 + +// raw, unmodified values +int read_sms_raw(int type, int *x, int *y, int *z); +// "calibrated" values (same as raw if no calibration data exists) +int read_sms(int type, int *x, int *y, int *z); +// real (1.0 = 1G) values (requires calibration data) +// note that this is the preferred API as it need not change with new machines +// however, this API does not work if no "scale" calibration data exists +int read_sms_real(int type, double *x, double *y, double *z); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/modules/video_filter/rotate.c b/modules/video_filter/rotate.c index ec32815dd2543bff234aaf13e29aac7d72b7d88a..ac9cddf5040500f866ee5b1b1581fe4415205d9e 100644 --- a/modules/video_filter/rotate.c +++ b/modules/video_filter/rotate.c @@ -46,6 +46,10 @@ static int RotateCallback( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ); +static int PreciseRotateCallback( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, + void *p_data ); + #define ANGLE_TEXT N_("Angle in degrees") #define ANGLE_LONGTEXT N_("Angle in degrees (0 to 359)") @@ -84,7 +88,7 @@ struct filter_sys_t static inline void cache_trigo( int i_angle, int *i_sin, int *i_cos ) { - const double f_angle = (((double)i_angle)*M_PI)/180.; + const double f_angle = (((double)i_angle)*M_PI)/1800.; *i_sin = (int)(sin( f_angle )*256.); *i_cos = (int)(cos( f_angle )*256.); } @@ -110,8 +114,10 @@ static int Create( vlc_object_t *p_this ) p_filter->p_cfg ); p_sys->i_angle = var_CreateGetIntegerCommand( p_filter, - FILTER_PREFIX "angle" ); + FILTER_PREFIX "angle" ) * 10; + var_CreateGetIntegerCommand( p_filter, FILTER_PREFIX "deciangle" ); var_AddCallback( p_filter, FILTER_PREFIX "angle", RotateCallback, p_sys ); + var_AddCallback( p_filter, FILTER_PREFIX "deciangle", PreciseRotateCallback, p_sys ); cache_trigo( p_sys->i_angle, &p_sys->i_sin, &p_sys->i_cos ); @@ -219,6 +225,20 @@ static int RotateCallback( vlc_object_t *p_this, char const *psz_var, filter_sys_t *p_sys = (filter_sys_t *)p_data; if( !strcmp( psz_var, "rotate-angle" ) ) + { + p_sys->i_angle = newval.i_int*10; + + cache_trigo( p_sys->i_angle, &p_sys->i_sin, &p_sys->i_cos ); + } + return VLC_SUCCESS; +} +static int PreciseRotateCallback( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, + void *p_data ) +{ + filter_sys_t *p_sys = (filter_sys_t *)p_data; + + if( !strcmp( psz_var, "rotate-deciangle" ) ) { p_sys->i_angle = newval.i_int;