// // WiiMidiDelegate.m // WiiToMidi // // Created by Mike Verdone on 22/12/06. // Copyright 2006 __MyCompanyName__. All rights reserved. // #import "WiiMidiDelegate.h" @implementation WiiMidiDelegate -(id) init { _wii = nil; _firstTime = true; _midiEvts = [[MidiEventOutput alloc] init]; _sensitivity = [[SensitivityModifier alloc] init]; _learnMode = [[LearnModeModifier alloc] init]; _smoother = [[SmoothingModifier alloc] init]; _noteSender = [[NoteSender alloc] init]; _advancedMathMod = [[AdvancedMathModifier alloc] init]; _midiTimer = nil; _animation = nil; MIDIClientCreate(CFSTR("WiiToMidi"), NULL, NULL, &_midi); MIDIOutputPortCreate(_midi, CFSTR("Output"), &_midiOut); return self; } -(void) setMidiChannel:(int)midiChannel { _midiChannel = midiChannel; [_midiEvts setChannel:midiChannel]; } -(void) sendMidi:(NSTimer*)timer { if (timer != _midiTimer) return; if (_firstTime) { memcpy(_oldState, _state, STATE_ARR_SIZE); _firstTime = FALSE; return; } // ButtonOne on buttonUp toggle learn mode. if ((! _state[SA_BUT_1]) && (_oldState[SA_BUT_1])) { [_learnMode setLearnMode:(! [_learnMode learnMode])]; [_noteSender setSendOn:(! [_learnMode learnMode])]; [self stateChanged]; [self setAnimation:([_learnMode learnMode] ? [[[Animation alloc] initWithWiiRemote:_wii initialState:1 frameData:[Animation getFramesWithId:ANIM_FLASH_1]] autorelease] : nil)]; } // ButtonPlus on buttonUp if ((! _state[SA_BUT_PLUS]) && (_oldState[SA_BUT_PLUS])) { [_sensitivity setSensitivity:([_sensitivity sensitivity] + 1)]; [self stateChanged]; [self setAnimation:[[[Animation alloc] initWithWiiRemote:_wii initialState:1 frameData:[Animation getFramesWithId:ANIM_LR]] autorelease]]; } // ButtonMinus on buttonUp if ((! _state[SA_BUT_MINUS]) && (_oldState[SA_BUT_MINUS])) { [_sensitivity setSensitivity:([_sensitivity sensitivity] - 1)]; [self stateChanged]; [self setAnimation:[[[Animation alloc] initWithWiiRemote:_wii initialState:1 frameData:[Animation getFramesWithId:ANIM_RL]] autorelease]]; } // ButtonUp on buttonUp if ((! _state[SA_BUT_UP]) && (_oldState[SA_BUT_UP])) { [_smoother setSmoothingFrames:([_smoother smoothingFrames] + 1)]; [self stateChanged]; NSLog(@"Smoothing set to %i", [_smoother smoothingFrames]); [self setAnimation:[[[Animation alloc] initWithWiiRemote:_wii initialState:1 frameData:[Animation getFramesWithId:ANIM_2UP]] autorelease]]; } // ButtonDown on buttonUp if ((! _state[SA_BUT_DOWN]) && (_oldState[SA_BUT_DOWN])) { [_smoother setSmoothingFrames:([_smoother smoothingFrames] - 1)]; [self stateChanged]; NSLog(@"Smoothing set to %i", [_smoother smoothingFrames]); [self setAnimation:[[[Animation alloc] initWithWiiRemote:_wii initialState:1 frameData:[Animation getFramesWithId:ANIM_2DOWN]] autorelease]]; } // Button2 on buttonDown if ((_state[SA_BUT_2]) && (! _oldState[SA_BUT_2])) { [_learnMode setLearnSubMode:([_learnMode learnSubMode] + 1)]; [self stateChanged]; } [_sensitivity manipulate:_state]; [_smoother manipulate:_state]; [_advancedMathMod manipulate:_state]; [_learnMode manipulate:_state]; [_noteSender manipulate:_state sendingMidiTo:_midiEvts]; int i; for (i = 0; i < SEND_ARR_SIZE; i++) { if (_state[i] == _oldState[i]) continue; [_midiEvts pushControl:(0x10 + i) value:(_state[i] >> 1)]; } MIDISend(_midiOut, _midiDest, [_midiEvts list]); [_midiEvts clearList]; memcpy(_oldState, _state, STATE_ARR_SIZE); } -(id) setMidiTimer:(NSTimer*)timer { [_midiTimer invalidate]; [_midiTimer autorelease]; _midiTimer = [timer retain]; return self; } -(id) setWiiRemote:(WiiRemote*)wii { if (_wii) { if ([_wii available]) [_wii closeConnection]; [_wii autorelease]; [self setMidiTimer:nil]; [self setAnimation:nil]; } if (wii) { [wii retain]; [wii setDelegate:self]; [wii setMotionSensorEnabled:true]; [wii setIRSensorEnabled:false]; [wii setLEDEnabled1:true enabled2:false enabled3:false enabled4:false]; // Register to receive expansion port events. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wiiRemoteExpansionPortChanged:) name:@"WiiRemoteExpansionPortChangedNotification" object:nil]; [self setMidiTimer:[NSTimer scheduledTimerWithTimeInterval:0.016666 target:self selector:@selector(sendMidi:) userInfo:nil repeats:TRUE]]; } _wii = wii; [self stateChanged]; return self; } -(void) wiiRemoteExpansionPortChanged:(NSNotification*)nc { if (((WiiRemote*) [nc object]) != _wii) return; NSLog(@"Expansion port event."); [_wii setExpansionPortEnabled:[_wii isExpansionPortAttached]]; [_advancedMathMod setExpansionPortType:[_wii expansionPortType]]; } -(void) dealloc { NSLog(@"in WiiMidiDelegate dealloc"); [self setWiiRemote:nil]; [self setMidiTimer:nil]; [self setAnimation:nil]; [_sensitivity autorelease]; [_learnMode autorelease]; [_advancedMathMod autorelease]; [super dealloc]; } -(id) setObserver:(id)observer { [_observer autorelease]; _observer = [observer retain]; [self stateChanged]; return self; } -(WiiRemote*) wii { return _wii; } -(id) setAnimation:(Animation*) animation { [[_animation stopAnimation] autorelease]; _animation = [animation retain]; return self; } -(void) setMidiDestination:(MIDIEndpointRef)midiEndpoint { _midiDest = midiEndpoint; } -(void) stateChanged { [_observer stateChanged:self wiiRemoteConnected:(_wii != nil) learnMode:[_learnMode learnMode] learnSubMode:[_learnMode learnSubMode] sensitivity:[_sensitivity sensitivity] smoothing:[_smoother smoothingFrames]]; } @end @implementation WiiMidiDelegate ( WiiRemoteDelegate ) - (void) irPointMovedX:(float)px Y:(float)py { // pointer mode not supported. } -(void) buttonChanged:(WiiButtonType)type isPressed:(BOOL)isPressed { switch (type) { case WiiRemoteAButton: _state[SA_BUT_A] = isPressed; break; case WiiRemoteBButton: _state[SA_BUT_B] = isPressed; break; case WiiRemoteOneButton: _state[SA_BUT_1] = isPressed; break; case WiiRemoteTwoButton: _state[SA_BUT_2] = isPressed; break; case WiiRemoteMinusButton: _state[SA_BUT_MINUS] = isPressed; break; case WiiRemotePlusButton: _state[SA_BUT_PLUS] = isPressed; break; case WiiRemoteUpButton: _state[SA_BUT_UP] = isPressed; break; case WiiRemoteDownButton: _state[SA_BUT_DOWN] = isPressed; break; case WiiRemoteLeftButton: _state[SA_BUT_LEFT] = isPressed; break; case WiiRemoteRightButton: _state[SA_BUT_RIGHT] = isPressed; break; case WiiNunchukCButton: _state[SA_BUT_C] = isPressed; break; case WiiNunchukZButton: _state[SA_BUT_Z] = isPressed; break; case WiiClassicControllerAButton: _state[SA_BUT_CA] = isPressed; break; case WiiClassicControllerBButton: _state[SA_BUT_CB] = isPressed; break; case WiiClassicControllerXButton: _state[SA_BUT_CX] = isPressed; break; case WiiClassicControllerYButton: _state[SA_BUT_CY] = isPressed; break; default: break; } } -(void) accelerationChanged:(WiiAccelerationSensorType)type accX:(unsigned short)accX accY:(unsigned short)accY accZ:(unsigned short)accZ { // These values seem to go up to about 512, so shift one bit to fit in the 0..256 uchar range. switch (type) { case WiiRemoteAccelerationSensor: _state[SA_ACC_X] = accX >> 2; _state[SA_ACC_Y] = accY >> 2; _state[SA_ACC_Z] = accZ >> 2; break; case WiiNunchukAccelerationSensor: _state[SA_ACC_NX] = accX >> 2; _state[SA_ACC_NY] = accY >> 2; _state[SA_ACC_NZ] = accZ >> 2; break; default: break; } } -(void) joyStickChanged:(WiiJoyStickType)type tiltX:(unsigned short)tiltX tiltY:(unsigned short)tiltY { switch (type) { case WiiNunchukJoyStick: _state[SA_JOY_NX] = tiltX; _state[SA_JOY_NY] = tiltY; break; case WiiClassicControllerLeftJoyStick: _state[SA_JOY_CLX] = tiltX * 4; _state[SA_JOY_CLY] = tiltY * 4; break; case WiiClassicControllerRightJoyStick: _state[SA_JOY_CRX] = tiltX; _state[SA_JOY_CRY] = tiltY; break; default: break; } } -(void) analogButtonChanged:(WiiButtonType)type amount:(unsigned short)press { switch(type) { case WiiClassicControllerLButton: _state[SA_BUT_CL] = press; break; case WiiClassicControllerRButton: _state[SA_BUT_CR] = press; break; default: break; } } -(void) wiiRemoteDisconnected:(IOBluetoothDevice*)device; { NSLog(@"Wii remote disconnected."); [self setWiiRemote:nil]; [self stateChanged]; } @end