diff -r f9bb0fca356a -r 0fd27995241b javauis/mmapi_qt/baseline/src/cmmamidicontrol.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/mmapi_qt/baseline/src/cmmamidicontrol.cpp Tue May 11 16:07:20 2010 +0300 @@ -0,0 +1,328 @@ +/* +* Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: This class is a MIDIControl. +* +*/ + + +// INCLUDE FILES +#include +#include + +#include "cmmamidicontrol.h" +#include "cmmamidiplayer.h" + +namespace +{ +const TReal KMMAMIDIVolumeConversionConstant = 40; +const TReal KMMADecibelToMidiVolumeConversionPowerBase = 10; +//const TTimeIntervalMicroSeconds32 KMMAMIDIVolumeChangeTimeout = 2000000; +const TInt KMMAMIDIVolumeChangeTimeout = 2000000; +const TReal KMMAMIDIMinimumVolumeDecibels = -130; +// For channel volume change message: +const TUint8 KMIDIControlChangeEvent = 0xB0; +const TUint8 KMIDIControlMainVolume = 0x07; +} + +CMMAMIDIControl* CMMAMIDIControl::NewL(CMMAMIDIPlayer* aPlayer) +{ + CMMAMIDIControl* self = new(ELeave)CMMAMIDIControl(aPlayer); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; +} + +CMMAMIDIControl::CMMAMIDIControl(CMMAMIDIPlayer* aPlayer) +{ + LOG( EJavaMMAPI, EInfo, "MMA:CMMAMIDIControl::CMMAMIDIControl"); + iPlayer = aPlayer; +} + +CMMAMIDIControl::~CMMAMIDIControl() +{ + LOG( EJavaMMAPI, EInfo, "MMA:CMMAMIDIControl::~CMMAMIDIControl +"); + delete iVolumeEventWait; + LOG( EJavaMMAPI, EInfo, "MMA:CMMAMIDIControl::~CMMAMIDIControl -"); +} + +void CMMAMIDIControl::ConstructL() +{ + LOG( EJavaMMAPI, EInfo, "MMA:CMMAMIDIControl::ConstructL +"); + iVolumeEventWait = CChannelVolumeEventWait::NewL(); + iPlayer->addObserverL(this); + LOG( EJavaMMAPI, EInfo, "MMA:CMMAMIDIControl::ConstructL -"); +} + +const TDesC& CMMAMIDIControl::ClassName() const +{ + LOG( EJavaMMAPI, EInfo, "MMA:CMMAMIDIControl::ClassName"); + return KMIDIControlName; +} + +TInt CMMAMIDIControl::ChannelVolumeL(TInt aChannel) +{ + LOG1( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: ChannelVolumeL + aChannel=%d", aChannel); + + CMidiClientUtility* midi = iPlayer->MidiClient(); + + // If engine is not processing events, current + // volume cannot be known for sure. + TMidiState engineState = midi->State(); +#ifdef RD_JAVA_TMIDISTATECHANGE + if ((engineState == EMidiStateClosedDisengaged) || + (engineState == EMidiStateOpenDisengaged)) +#else + if ((engineState == EClosedDisengaged) || + (engineState == EOpenDisengaged)) +#endif + { + return KErrNotFound; + } + + // This calculation might be slow on hardware, since + // following equation must be calculated using TReals: + // + // p1 = 10^(dB/40) * p0, where: + // p1 is target midi volume, + // p0 is reference value (maximum midi volume, 127) + // dB is volume value in Decibels from MidiClientUtility + + TReal32 volume = midi->ChannelVolumeL(aChannel); + if (volume < KMMAMIDIMinimumVolumeDecibels) + { + volume = KMMAMIDIMinimumVolumeDecibels; + } + TReal exponent = volume / KMMAMIDIVolumeConversionConstant; + TReal targetVal = 0; + + // calculate midi volume value + User::LeaveIfError( + Math::Pow( + targetVal, + KMMADecibelToMidiVolumeConversionPowerBase, + exponent)); + + // multiply by reference value + targetVal *= KMAXVolume; + + // round value to zero decimals + User::LeaveIfError(Math::Round(targetVal, targetVal, 0)); + + // clamp to bounds + TInt retVal = (int) targetVal; + if (retVal < 0) + { + retVal = 0; + } + else if (retVal > KMAXVolume) + { + retVal = KMAXVolume; + } + + LOG1( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: ChannelVolumeL - retVal=%d", retVal); + return retVal; +} + +void CMMAMIDIControl::SetChannelVolumeL(TInt aChannel, TInt aVolume) +{ + LOG2( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: SetChannelVolumeL + aChannel=%d aVolume=%d", aChannel, aVolume); + + CMidiClientUtility* midi = iPlayer->MidiClient(); + + // Change is done with shortMidiEvent so midi volume -> decibel + // calculation is avoided (would be needed for midi client api + // SetChannelVolumeL method) + + TBuf8<3> volumeChangeMessage; + // range is checked before + TUint8 channel = (KMIDIControlChangeEvent | (TUint8)aChannel); + volumeChangeMessage.Append(channel); + volumeChangeMessage.Append(KMIDIControlMainVolume); + volumeChangeMessage.Append((TUint8)aVolume); + SendMIDIEventL(&volumeChangeMessage); + + TMidiState engineState = midi->State(); + + // If engine is not processing, we do not have to + // wait until change is done. +#ifdef RD_JAVA_TMIDISTATECHANGE + if (!((engineState == EMidiStateClosedDisengaged) || + (engineState == EMidiStateOpenDisengaged))) +#else + if (!((engineState == EClosedDisengaged) || + (engineState == EOpenDisengaged))) +#endif + { + LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: SetChannelVolumeL: ExecuteL ->"); + iVolumeEventWait->StartWait(aChannel); + LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: SetChannelVolumeL: ExecuteL <-"); + } + LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: SetChannelVolumeL -"); +} + +void CMMAMIDIControl::SetProgramL(TInt aChannel, + TInt aBank, + TInt aProgram) +{ + CMidiClientUtility* midi = iPlayer->MidiClient(); + + // Program means instrument. + midi->SetInstrumentL(aChannel, aBank, aProgram); +} + +TInt CMMAMIDIControl::SendMIDIEventL(const TDesC8* aData) +{ + LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: SendMIDIEventL +"); + CMidiClientUtility* midi = iPlayer->MidiClient(); + + // SendMessageL only processes first message in the descriptor, + // so we need to send blocks of data as many times as needed. + + TInt dataLength = aData->Length(); + TInt dataSent = 0; + while (dataSent < dataLength) + { + // Delegate event directly to the native implementation + // which checks the validity. + TPtrC8 nextBlock = aData->Right(dataLength - dataSent); + dataSent += midi->SendMessageL(nextBlock); + } + LOG1( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: SendMIDIEventL: sent %d bytes", dataSent); + LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: SendMIDIEventL -"); + return dataSent; +} + +TInt CMMAMIDIControl::ReInitializeMidiL(const TDesC8* aData) +{ + LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: ReInitializeMidiL + "); + iPlayer->ReInitializeMidiEngineL(aData); + LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIControl: ReInitializeMidiL - "); + return KErrNone; +} + +void CMMAMIDIControl::MmcuoStateChanged(TMidiState /*aOldState*/, + TMidiState /*aNewState*/, + const TTimeIntervalMicroSeconds& /*aTime*/, + TInt /*aError*/) +{ +} + +void CMMAMIDIControl::MmcuoTempoChanged(TInt /*aMicroBeatsPerMinute*/) +{ +} + +void CMMAMIDIControl::MmcuoVolumeChanged(TInt aChannel, TReal32 /*aVolumeInDecibels*/) +{ + LOG1( EJavaMMAPI, EInfo, "CMMAMIDIControl:: MmcuoVolumeChanged + aChannel=%d", aChannel); + if (iVolumeEventWait) + { + iVolumeEventWait->HandleVolumeChangedEvent(aChannel); + } + LOG( EJavaMMAPI, EInfo, "CMMAMIDIControl:: MmcuoVolumeChanged -"); +} + +void CMMAMIDIControl::MmcuoMuteChanged(TInt /*aChannel*/,TBool /*aMuted*/) +{ +} + +void CMMAMIDIControl::MmcuoSyncUpdate(const TTimeIntervalMicroSeconds& /*aMicroSeconds*/,TInt64 /*aMicroBeats*/) +{ +} + +void CMMAMIDIControl::MmcuoMetaDataEntryFound(const TInt /*aMetaDataEntryId*/,const TTimeIntervalMicroSeconds& /*aPosition*/) +{ +} + +void CMMAMIDIControl::MmcuoMipMessageReceived(const RArray& /*aMessage*/) +{ +} + +void CMMAMIDIControl::MmcuoPolyphonyChanged(TInt /*aNewPolyphony*/) +{ +} + +void CMMAMIDIControl::MmcuoInstrumentChanged(TInt /*aChannel*/,TInt /*aBankId*/,TInt /*aInstrumentId*/) +{ +} + +CMMAMIDIControl::CChannelVolumeEventWait* CMMAMIDIControl::CChannelVolumeEventWait::NewL() +{ + LOG( EJavaMMAPI, EInfo, "CMMAMIDIControl::CChannelVolumeEventWait::NewL"); + CChannelVolumeEventWait* self = new(ELeave) CChannelVolumeEventWait(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; +} + +void CMMAMIDIControl::CChannelVolumeEventWait::ConstructL() +{ + iWait = new(ELeave) CActiveSchedulerWait(); + iTimer = CTimeOutTimer::NewL(CActive::EPriorityStandard, *this); +} + +CMMAMIDIControl::CChannelVolumeEventWait::CChannelVolumeEventWait() +{ +} + +CMMAMIDIControl::CChannelVolumeEventWait::~CChannelVolumeEventWait() +{ + delete iTimer; + delete iWait; +} + +void CMMAMIDIControl::CChannelVolumeEventWait::TimerExpired() +{ + LOG( EJavaMMAPI, EInfo, "CMMAMIDIControl::CChannelVolumeEventWait::TimerExpired +"); + if (iWait->IsStarted()) + { + LOG( EJavaMMAPI, EInfo, "CMMAMIDIControl::CChannelVolumeEventWait::TimerExpired - cancelling wait"); + iWait->AsyncStop(); + } + LOG( EJavaMMAPI, EInfo, "CMMAMIDIControl::CChannelVolumeEventWait::TimerExpired -"); +} + +void CMMAMIDIControl::CChannelVolumeEventWait::StartWait(TInt aChannel) +{ + LOG1( EJavaMMAPI, EInfo, "CMMAMIDIControl::CChannelVolumeEventWait::StartWait aChannel=%d", aChannel); + iChannel = aChannel; + + if (!iWait->IsStarted()) + { + iTimer->After(KMMAMIDIVolumeChangeTimeout); + iWait->Start(); + } +} + +void CMMAMIDIControl::CChannelVolumeEventWait::StopWait() +{ + LOG( EJavaMMAPI, EInfo, "CMMAMIDIControl::CChannelVolumeEventWait::StopWait"); + if (iWait->IsStarted()) + { + iTimer->Cancel(); + iWait->AsyncStop(); + } +} + +void CMMAMIDIControl::CChannelVolumeEventWait::HandleVolumeChangedEvent(TInt aChannel) +{ + LOG1( EJavaMMAPI, EInfo, "CMMAMIDIControl::CChannelVolumeEventWait::HandleVolumeChangedEvent aChannel=%d", aChannel); + if (iChannel == aChannel) + { + StopWait(); + } +} + +// END OF FILE