1/*****************************************************************************
2 * RemoteMainController.m
3 *
4 * Created by Martin Kahr on 11.03.06 under a MIT-style license.
5 * Copyright (c) 2006 martinkahr.com. All rights reserved.
6 *
7 * Code modified and adapted to OpenOffice.org
8 * by Eric Bachard on 11.08.2008 under the same License
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 *
28 *****************************************************************************/
29
30#import "RemoteMainController.h"
31#import "AppleRemote.h"
32#import "KeyspanFrontRowControl.h"
33#import "GlobalKeyboardDevice.h"
34#import "RemoteControlContainer.h"
35#import "MultiClickRemoteBehavior.h"
36
37// -------------------------------------------------------------------------------------------
38// Sample Code 3: Multi Click Behavior and Hold Event Simulation
39// -------------------------------------------------------------------------------------------
40
41@implementation MainController
42
43- (id) init {
44    self = [super init];  // because we redefined our own init instead of use the fu..nny awakeFromNib
45    if (self != nil) {
46
47        // 1. instantiate the desired behavior for the remote control device
48        remoteControlBehavior = [[MultiClickRemoteBehavior alloc] init];
49
50        // 2. configure the behavior
51        [remoteControlBehavior setDelegate: self];
52
53        // 3. a Remote Control Container manages a number of devices and conforms to the RemoteControl interface
54        //    Therefore you can enable or disable all the devices of the container with a single "startListening:" call.
55        RemoteControlContainer* container = [[RemoteControlContainer alloc] initWithDelegate: remoteControlBehavior];
56
57        if ( [container instantiateAndAddRemoteControlDeviceWithClass: [AppleRemote class]] != 0 ) {
58#ifdef DEBUG
59            NSLog(@"[container instantiateAndAddRemoteControlDeviceWithClass: [AppleRemote class]] successfull");
60        }
61        else {
62            NSLog(@"[container instantiateAndAddRemoteControlDeviceWithClass: [AppleRemote class]] failed");
63#endif
64        }
65
66        if ( [container instantiateAndAddRemoteControlDeviceWithClass: [KeyspanFrontRowControl class]] != 0 ) {
67#ifdef DEBUG
68            NSLog(@"[container instantiateAndAddRemoteControlDeviceWithClass: [KeyspanFrontRowControl class]] successfull");
69        }
70        else {
71            NSLog(@"[container instantiateAndAddRemoteControlDeviceWithClass: [KeyspanFrontRowControl class]] failed");
72#endif
73        }
74
75        if ( [container instantiateAndAddRemoteControlDeviceWithClass: [GlobalKeyboardDevice class]] != 0 ) {
76#ifdef DEBUG
77            NSLog(@"[container instantiateAndAddRemoteControlDeviceWithClass: [GlobalKeyboardDevice class]] successfull");
78        }
79        else {
80            NSLog(@"[container instantiateAndAddRemoteControlDeviceWithClass: [GlobalKeyboardDevice class]] failed");
81#endif
82        }
83        // to give the binding mechanism a chance to see the change of the attribute
84        [self setValue: container forKey: @"remoteControl"];
85#ifdef DEBUG
86            NSLog(@"MainController init done");
87#endif
88    }
89    else
90        NSLog(@"MainController init failed");
91    return self;
92}
93
94- (void) postTheEvent: (short int)buttonIdentifier modifierFlags:(int)modifierFlags
95{
96    [NSApp postEvent:
97    [NSEvent    otherEventWithType:NSApplicationDefined
98                location:NSZeroPoint
99                modifierFlags:modifierFlags
100                timestamp: 0
101                windowNumber:[[NSApp keyWindow] windowNumber]
102                context:nil
103                subtype:AppleRemoteControlEvent
104                data1: buttonIdentifier
105                data2: 0]
106    atStart: NO];
107}
108
109
110- (void) remoteButton: (RemoteControlEventIdentifier)buttonIdentifier pressedDown: (BOOL) pressedDown clickCount: (unsigned int)clickCount
111{
112    NSString* pressed = @"";
113#ifdef DEBUG
114    NSString* buttonName = nil;
115#endif
116    if (pressedDown)
117    {
118        pressed = @"(pressed)";
119
120#ifdef DEBUG
121        switch(buttonIdentifier)
122        {
123            case kRemoteButtonPlus:         buttonName = @"Volume up";              break;  // MEDIA_COMMAND_VOLUME_UP  ( see vcl/inc/vcl/cmdevt.hxx )
124            case kRemoteButtonMinus:        buttonName = @"Volume down";            break;  // MEDIA_COMMAND_VOLUME_DOWN
125            case kRemoteButtonMenu:         buttonName = @"Menu";                   break;  // MEDIA_COMMAND_MENU
126            case kRemoteButtonPlay:         buttonName = @"Play";                   break;  // MEDIA_COMMAND_PLAY
127            case kRemoteButtonRight:        buttonName = @"Next slide";             break;  // MEDIA_COMMAND_NEXTTRACK
128            case kRemoteButtonLeft:         buttonName = @"Left";                   break;  // MEDIA_COMMAND_PREVIOUSTRACK
129            case kRemoteButtonRight_Hold:   buttonName = @"Last slide";             break;  // MEDIA_COMMAND_NEXTTRACK_HOLD
130            case kRemoteButtonLeft_Hold:    buttonName = @"First slide";            break;  // MEDIA_COMMAND_PREVIOUSTRACK_HOLD
131            case kRemoteButtonPlus_Hold:    buttonName = @"Volume up holding";      break;
132            case kRemoteButtonMinus_Hold:   buttonName = @"Volume down holding";    break;
133            case kRemoteButtonPlay_Hold:    buttonName = @"Play (sleep mode)";      break;  // MEDIA_COMMAND_PLAY_HOLD
134            case kRemoteButtonMenu_Hold:    buttonName = @"Menu (long)";            break;  // MEDIA_COMMAND_MENU_HOLD
135            case kRemoteControl_Switched:   buttonName = @"Remote Control Switched";break;
136
137            default:    NSLog(@"Unmapped event for button %d", buttonIdentifier);   break;
138        }
139#endif
140        [ self postTheEvent:buttonIdentifier modifierFlags: 0 ];
141    }
142    else // not pressed
143    {
144        pressed = @"(released)";
145    }
146
147#ifdef DEBUG
148	//NSLog(@"Button %@ pressed %@", buttonName, pressed);
149	NSString* clickCountString = @"";
150	if (clickCount > 1) clickCountString = [NSString stringWithFormat: @"%d clicks", clickCount];
151	NSString* feedbackString = [NSString stringWithFormat:@"(Value:%4d) %@  %@ %@",buttonIdentifier, buttonName, pressed, clickCountString];
152
153	// print out events
154	NSLog(@"%@", feedbackString);
155
156    if (pressedDown == NO) printf("\n");
157	// simulate slow processing of events
158	// [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.5]];
159#endif
160}
161
162- (void) dealloc {
163    [remoteControl autorelease];
164	[remoteControlBehavior autorelease];
165	[super dealloc];
166}
167
168// for bindings access
169- (RemoteControl*) remoteControl {
170	return remoteControl;
171}
172
173- (MultiClickRemoteBehavior*) remoteBehavior {
174	return remoteControlBehavior;
175}
176
177@end