Commit b256a9da authored by Felix Paul Kühne's avatar Felix Paul Kühne

* modernise the Apple Remote architecture by back-porting an adapted trunk...

* modernise the Apple Remote architecture by back-porting an adapted trunk version. This fixes the AR support on Tiger and provides a couple of new features (skipping, better volume control, easy to find fullscreen-mode-toggle). additionally, fixed a nasty bug which prevented proper toggling of the fullscreen mode.
parent 9f677d3a
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
* AppleRemote * AppleRemote
* $Id$ * $Id$
* *
* Created by Martin Kahr on 11.03.06 under a MIT-style license. * Created by Martin Kahr on 11.03.06 under a MIT-style license.
* Copyright (c) 2006 martinkahr.com. All rights reserved. * Copyright (c) 2006 martinkahr.com. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation * to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, * the rights to use, copy, modify, merge, publish, distribute, sublicense,
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* *
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
...@@ -27,12 +27,12 @@ ...@@ -27,12 +27,12 @@
***************************************************************************** *****************************************************************************
* *
* Note that changes made by any members or contributors of the VideoLAN team * Note that changes made by any members or contributors of the VideoLAN team
* (i.e. changes that were checked in into one of VideoLAN's source code * (i.e. changes that were checked in exclusively into one of VideoLAN's source code
* repositories) are licensed under the GNU General Public License version 2, * repositories) are licensed under the GNU General Public License version 2,
* or (at your option) any later version. * or (at your option) any later version.
* Thus, the following statements apply to our changes: * Thus, the following statements apply to our changes:
* *
* Copyright (C) 2006 the VideoLAN team * Copyright (C) 2006-2007 the VideoLAN team
* Authors: Eric Petit <titer@m0k.org> * Authors: Eric Petit <titer@m0k.org>
* Felix Kühne <fkuehne at videolan dot org> * Felix Kühne <fkuehne at videolan dot org>
* *
...@@ -61,38 +61,51 @@ ...@@ -61,38 +61,51 @@
enum AppleRemoteEventIdentifier enum AppleRemoteEventIdentifier
{ {
kRemoteButtonVolume_Plus=0, kRemoteButtonVolume_Plus =1<<1,
kRemoteButtonVolume_Minus, kRemoteButtonVolume_Minus =1<<2,
kRemoteButtonMenu, kRemoteButtonMenu =1<<3,
kRemoteButtonPlay, kRemoteButtonPlay =1<<4,
kRemoteButtonRight, kRemoteButtonRight =1<<5,
kRemoteButtonLeft, kRemoteButtonLeft =1<<6,
kRemoteButtonRight_Hold, kRemoteButtonRight_Hold =1<<7,
kRemoteButtonLeft_Hold, kRemoteButtonLeft_Hold =1<<8,
kRemoteButtonMenu_Hold, kRemoteButtonMenu_Hold =1<<9,
kRemoteButtonPlay_Sleep, kRemoteButtonPlay_Sleep =1<<10,
kRemoteControl_Switched kRemoteControl_Switched =1<<11,
kRemoteButtonVolume_Plus_Hold =1<<12,
kRemoteButtonVolume_Minus_Hold =1<<13
}; };
typedef enum AppleRemoteEventIdentifier AppleRemoteEventIdentifier; typedef enum AppleRemoteEventIdentifier AppleRemoteEventIdentifier;
/* Encapsulates usage of the apple remote control /* Encapsulates usage of the apple remote control
This class is implemented as a singleton as there is exactly one remote per machine (until now) This class is implemented as a singleton as there is exactly one remote per machine (until now)
The class is not thread safe The class is not thread safe
*/ */
@interface AppleRemote : NSObject { @interface AppleRemote : NSObject {
IOHIDDeviceInterface** hidDeviceInterface; IOHIDDeviceInterface** hidDeviceInterface;
IOHIDQueueInterface** queue; IOHIDQueueInterface** queue;
NSMutableArray* allCookies; NSMutableArray* allCookies;
NSMutableDictionary* cookieToButtonMapping; NSMutableDictionary* cookieToButtonMapping;
BOOL openInExclusiveMode; BOOL openInExclusiveMode;
BOOL simulatePlusMinusHold;
int remoteId; BOOL processesBacklog;
IBOutlet id delegate; /* state for simulating plus/minus hold */
BOOL lastEventSimulatedHold;
AppleRemoteEventIdentifier lastPlusMinusEvent;
NSTimeInterval lastPlusMinusEventTime;
int remoteId;
unsigned int clickCountEnabledButtons;
NSTimeInterval maxClickTimeDifference;
NSTimeInterval lastClickCountEventTime;
AppleRemoteEventIdentifier lastClickCountEvent;
unsigned int eventClickCount;
IBOutlet id delegate;
} }
- (void) setRemoteId: (int) aValue;
- (int) remoteId; - (int) remoteId;
- (BOOL) isRemoteAvailable; - (BOOL) isRemoteAvailable;
...@@ -103,6 +116,42 @@ typedef enum AppleRemoteEventIdentifier AppleRemoteEventIdentifier; ...@@ -103,6 +116,42 @@ typedef enum AppleRemoteEventIdentifier AppleRemoteEventIdentifier;
- (BOOL) isOpenInExclusiveMode; - (BOOL) isOpenInExclusiveMode;
- (void) setOpenInExclusiveMode: (BOOL) value; - (void) setOpenInExclusiveMode: (BOOL) value;
/* click counting makes it possible to recognize if the user has pressed a button repeatedly
* click counting does delay each event as it has to wait if there is another event (second click)
* therefore there is a slight time difference (maximumClickCountTimeDifference) between a single click
* of the user and the call of your delegate method
* click counting can be enabled individually for specific buttons. Use the property clickCountEnableButtons
* to set the buttons for which click counting shall be enabled */
- (BOOL) clickCountingEnabled;
- (void) setClickCountingEnabled: (BOOL) value;
- (unsigned int) clickCountEnabledButtons;
- (void) setClickCountEnabledButtons: (unsigned int)value;
/* the maximum time difference till which clicks are recognized as multi clicks */
- (NSTimeInterval) maximumClickCountTimeDifference;
- (void) setMaximumClickCountTimeDifference: (NSTimeInterval) timeDiff;
/* When your application needs to much time on the main thread when processing an event other events
* may already be received which are put on a backlog. As soon as your main thread
* has some spare time this backlog is processed and may flood your delegate with calls.
* Backlog processing is turned off by default. */
- (BOOL) processesBacklog;
- (void) setProcessesBacklog: (BOOL) value;
/* Sets an NSApplication delegate which starts listening when application is becoming active
* and stops listening when application resigns being active.
* If an NSApplication delegate has been already set all method calls will be forwarded to this delegate, too. */
- (BOOL) listeningOnAppActivate;
- (void) setListeningOnAppActivate: (BOOL) value;
/* Simulating plus/minus hold does deactivate sending of individual requests for plus/minus pressed down/released.
* Instead special hold events are being triggered when the user is pressing and holding plus/minus for a small period.
* With simulating enabled the plus/minus buttons do behave as the left/right buttons */
- (BOOL) simulatesPlusMinusHold;
- (void) setSimulatesPlusMinusHold: (BOOL) value;
/* Delegates are not retained */
- (void) setDelegate: (id) delegate; - (void) setDelegate: (id) delegate;
- (id) delegate; - (id) delegate;
...@@ -116,24 +165,35 @@ typedef enum AppleRemoteEventIdentifier AppleRemoteEventIdentifier; ...@@ -116,24 +165,35 @@ typedef enum AppleRemoteEventIdentifier AppleRemoteEventIdentifier;
@end @end
/* Method definitions for the delegate of the AppleRemote class /* Method definitions for the delegate of the AppleRemote class */
*/
@interface NSObject(NSAppleRemoteDelegate) @interface NSObject(NSAppleRemoteDelegate)
- (void) appleRemoteButton: (AppleRemoteEventIdentifier)buttonIdentifier pressedDown: (BOOL) pressedDown; - (void) appleRemoteButton: (AppleRemoteEventIdentifier)buttonIdentifier pressedDown: (BOOL) pressedDown clickCount: (unsigned int) count;
@end @end
@interface AppleRemote (PrivateMethods) @interface AppleRemote (PrivateMethods)
- (void) setRemoteId: (int) aValue;
- (NSDictionary*) cookieToButtonMapping; - (NSDictionary*) cookieToButtonMapping;
- (IOHIDQueueInterface**) queue; - (IOHIDQueueInterface**) queue;
- (IOHIDDeviceInterface**) hidDeviceInterface; - (IOHIDDeviceInterface**) hidDeviceInterface;
- (void) handleEventWithCookieString: (NSString*) cookieString sumOfValues: (SInt32) sumOfValues; - (void) handleEventWithCookieString: (NSString*) cookieString sumOfValues: (SInt32) sumOfValues;
@end @end
@interface AppleRemote (IOKitMethods) @interface AppleRemote (IOKitMethods)
- (io_object_t) findAppleRemoteDevice; - (io_object_t) findAppleRemoteDevice;
- (IOHIDDeviceInterface**) createInterfaceForDevice: (io_object_t) hidDevice; - (IOHIDDeviceInterface**) createInterfaceForDevice: (io_object_t) hidDevice;
- (BOOL) initializeCookies; - (BOOL) initializeCookies;
- (BOOL) openDevice; - (BOOL) openDevice;
@end @end
\ No newline at end of file
/* A NSApplication delegate which is used to activate and deactivate listening to the remote control
* dependent on the activation state of your application.
* All events are delegated to the original NSApplication delegate if necessary */
@interface AppleRemoteApplicationDelegate : NSObject {
id applicationDelegate;
}
- (id) initWithApplicationDelegate: (id) delegate;
- (id) applicationDelegate;
@end
This diff is collapsed.
...@@ -459,6 +459,9 @@ ...@@ -459,6 +459,9 @@
var_Get( p_playlist, "fullscreen", &val ); var_Get( p_playlist, "fullscreen", &val );
var_Set( p_playlist, "fullscreen", (vlc_value_t)!val.b_bool ); var_Set( p_playlist, "fullscreen", (vlc_value_t)!val.b_bool );
} }
else
NSLog( sender );
if( p_playlist ) vlc_object_release( (vlc_object_t *)p_playlist ); if( p_playlist ) vlc_object_release( (vlc_object_t *)p_playlist );
} }
......
...@@ -289,7 +289,7 @@ struct intf_sys_t ...@@ -289,7 +289,7 @@ struct intf_sys_t
int i_lastShownVolume; int i_lastShownVolume;
AppleRemote * o_remote; AppleRemote * o_remote;
BOOL b_left_right_remote_button_hold; /* true as long as the user holds the left or right button on the remote control */ BOOL b_remote_button_hold; /* true as long as the user holds the left,right,plus or minus on the remote control */
} }
+ (VLCMain *)sharedInstance; + (VLCMain *)sharedInstance;
......
...@@ -351,6 +351,7 @@ static VLCMain *_o_sharedMainInstance = nil; ...@@ -351,6 +351,7 @@ static VLCMain *_o_sharedMainInstance = nil;
i_lastShownVolume = -1; i_lastShownVolume = -1;
o_remote = [[AppleRemote alloc] init]; o_remote = [[AppleRemote alloc] init];
[o_remote setClickCountEnabledButtons: kRemoteButtonPlay];
[o_remote setDelegate: _o_sharedMainInstance]; [o_remote setDelegate: _o_sharedMainInstance];
return _o_sharedMainInstance; return _o_sharedMainInstance;
...@@ -719,52 +720,60 @@ static VLCMain *_o_sharedMainInstance = nil; ...@@ -719,52 +720,60 @@ static VLCMain *_o_sharedMainInstance = nil;
[o_remote stopListening: self]; [o_remote stopListening: self];
} }
/* Helper method for the remote control interface in order to trigger forward/backward /* Helper method for the remote control interface in order to trigger forward/backward and volume
as long as the user holds the left/right button */ increase/decrease as long as the user holds the left/right, plus/minus button */
- (void) triggerMovieStepForRemoteButton: (NSNumber*) buttonIdentifierNumber - (void) executeHoldActionForRemoteButton: (NSNumber*) buttonIdentifierNumber
{ {
if (b_left_right_remote_button_hold) { if (b_remote_button_hold)
switch([buttonIdentifierNumber intValue]) { {
case kRemoteButtonRight_Hold: switch([buttonIdentifierNumber intValue])
{
case kRemoteButtonRight_Hold:
[o_controls forward: self]; [o_controls forward: self];
break; break;
case kRemoteButtonLeft_Hold: case kRemoteButtonLeft_Hold:
[o_controls backward: self]; [o_controls backward: self];
break; break;
case kRemoteButtonVolume_Plus_Hold:
[o_controls volumeUp: self];
break;
case kRemoteButtonVolume_Minus_Hold:
[o_controls volumeDown: self];
break;
} }
if (b_left_right_remote_button_hold) { if (b_remote_button_hold)
{
/* trigger event */ /* trigger event */
[self performSelector:@selector(triggerMovieStepForRemoteButton:) [self performSelector:@selector(executeHoldActionForRemoteButton:)
withObject:buttonIdentifierNumber withObject:buttonIdentifierNumber
afterDelay:0.25]; afterDelay:0.25];
} }
} }
} }
/* Apple Remote callback */ /* Apple Remote callback */
- (void)appleRemoteButton:(AppleRemoteEventIdentifier)buttonIdentifier - (void) appleRemoteButton: (AppleRemoteEventIdentifier)buttonIdentifier
pressedDown:(BOOL)pressedDown pressedDown: (BOOL) pressedDown
clickCount: (unsigned int) count
{ {
switch( buttonIdentifier ) switch( buttonIdentifier )
{ {
case kRemoteButtonPlay: case kRemoteButtonPlay:
[o_controls play: self]; if (count >= 2)
break;
case kRemoteButtonVolume_Plus:
/* there are two events when the plus or minus button is pressed
one when the button is pressed down and one when the button is released */
if( pressedDown )
{ {
[o_controls volumeUp: self]; /* we're cheating here to convince o_controls to toggle fullscreen */
[o_controls windowAction: o_mi_fullscreen];
}
else
{
[o_controls play: self];
} }
break; break;
case kRemoteButtonVolume_Plus:
[o_controls volumeUp: self];
break;
case kRemoteButtonVolume_Minus: case kRemoteButtonVolume_Minus:
/* there are two events when the plus or minus button is pressed [o_controls volumeDown: self];
one when the button is pressed down and one when the button is released */
if( pressedDown )
{
[o_controls volumeDown: self];
}
break; break;
case kRemoteButtonRight: case kRemoteButtonRight:
[o_controls next: self]; [o_controls next: self];
...@@ -774,17 +783,20 @@ static VLCMain *_o_sharedMainInstance = nil; ...@@ -774,17 +783,20 @@ static VLCMain *_o_sharedMainInstance = nil;
break; break;
case kRemoteButtonRight_Hold: case kRemoteButtonRight_Hold:
case kRemoteButtonLeft_Hold: case kRemoteButtonLeft_Hold:
case kRemoteButtonVolume_Plus_Hold:
case kRemoteButtonVolume_Minus_Hold:
/* simulate an event as long as the user holds the button */ /* simulate an event as long as the user holds the button */
b_left_right_remote_button_hold = pressedDown; b_remote_button_hold = pressedDown;
if( pressedDown ) if( pressedDown )
{ {
NSNumber* buttonIdentifierNumber = [NSNumber numberWithInt: buttonIdentifier]; NSNumber* buttonIdentifierNumber = [NSNumber numberWithInt: buttonIdentifier];
[self performSelector:@selector(triggerMovieStepForRemoteButton:) [self performSelector:@selector(executeHoldActionForRemoteButton:)
withObject:buttonIdentifierNumber]; withObject:buttonIdentifierNumber];
} }
break; break;
case kRemoteButtonMenu: case kRemoteButtonMenu:
[o_controls windowAction: self]; /* we're cheating here to convince o_controls to toggle fullscreen */
[o_controls windowAction: o_mi_fullscreen];
break; break;
default: default:
/* Add here whatever you want other buttons to do */ /* Add here whatever you want other buttons to do */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment