📄 oggplaycontroller.cpp
字号:
else if (iUsedChannels == 2)
ac = TMdaAudioDataSettings::EChannelsStereo;
else
{
// iEnv->OggErrorMsgL(R_OGG_ERROR_12, R_OGG_ERROR_10);
User::Leave(KErrNotSupported);
}
// Note current settings
TInt bestRate = iUsedRate;
TInt convertingRate = convertRate;
TMdaAudioDataSettings::TAudioCaps bestRT = rt;
// Try the current settings.
// Adjust sample rate and channels if necessary
TInt err = KErrNotSupported;
while (err == KErrNotSupported)
{
TRAP(err, iStream->SetAudioPropertiesL(rt, ac));
if (err == KErrNotSupported)
{
// Frequency is not supported
// Try dropping the frequency
convertRate = GetNextLowerRate(iUsedRate, rt);
// If that doesn't work, try changing stereo to mono
if (!convertRate && (iUsedChannels == 2))
{
// Reset the sample rate
convertRate = convertingRate;
iUsedRate = bestRate;
rt = bestRT;
// Drop channels to 1
iUsedChannels = 1;
ac = TMdaAudioDataSettings::EChannelsMono;
convertChannel = ETrue;
}
else if (!convertRate)
break; // Give up, nothing supported :-(
}
}
// TBuf<256> buf,tbuf;
if (err != KErrNone)
{
/* CEikonEnv::Static()->ReadResource(buf, R_OGG_ERROR_16);
CEikonEnv::Static()->ReadResource(tbuf, R_OGG_ERROR_12);
buf.AppendNum(err);
iEnv->OggErrorMsgL(tbuf,buf); */
User::Leave(err);
}
// Trace the settings
TRACEF(COggLog::VA(_L("SetAudioCaps: theRate: %d, theChannels: %d, usedRate: %d, usedChannels: %d"), theRate, theChannels, iUsedRate, iUsedChannels));
/* if ((convertRate || convertChannel) && iEnv->WarningsEnabled())
{
// Display a warning message
SamplingRateSupportedMessage(convertRate, theRate, convertChannel, theChannels);
// Put the audio properties back the way they were
#if defined(MULTI_THREAD_PLAYBACK)
err = SetAudioProperties(usedRate, usedChannels);
#else
TRAP(err, iStream->SetAudioPropertiesL(rt, ac));
#endif
// Check that it worked (it should have)
if (err != KErrNone)
{
CEikonEnv::Static()->ReadResource(buf, R_OGG_ERROR_16);
CEikonEnv::Static()->ReadResource(tbuf, R_OGG_ERROR_12);
buf.AppendNum(err);
iEnv->OggErrorMsgL(tbuf,buf);
return err;
}
} */
// Determine buffer sizes so that we make approx 10-15 calls to the mediaserver per second
// + another 10-15 calls for position if the frequency analyzer is on screen
TInt bufferSize = 0;
switch (iUsedRate)
{
case 48000:
case 44100:
bufferSize = KBufferSize48K;
break;
case 32000:
bufferSize = KBufferSize32K;
break;
case 22050:
bufferSize = KBufferSize22K;
break;
case 16000:
bufferSize = KBufferSize16K;
break;
case 11025:
case 8000:
bufferSize = KBufferSize11K;
break;
default:
User::Panic(_L("COggControl:SAC"), 0);
break;
}
#if !defined(USE_FIXED_SIZE_BUFFERS)
if (iUsedChannels == 1)
bufferSize /= 2;
#endif
// We are finished with the stream, so delete it
delete iStream;
iStream = NULL;
// Set up the source with the used rate and channels
iOggSource->ConstructL(bufferSize, theRate, iUsedRate, theChannels, iUsedChannels);
}
void COggPlayController::PrimeL()
{
PRINT("COggPlayController::PrimeL");
if (iState == EStatePrimed)
return; // Nothing to do
if ((iState == EStateInterrupted) || (iState == EStateOpen))
{
iDecoder->Clear();
if (iFile)
iFile->Close();
delete iFile;
iFile = NULL;
iState = EStateNotOpened;
}
if ((iAudioOutput == NULL) || (iState != EStateNotOpened))
User::Leave(KErrNotReady);
iState = EStateOpen;
OpenFileL(iFileName,EFalse);
iAudioOutput->SinkPrimeL();
if (!iSinkBuffer)
{
if (!iAudioOutput->CanCreateSinkBuffer())
{
iSinkBuffer = CMMFDescriptorBuffer::NewL(KBufferSize48K);
iOwnSinkBuffer = ETrue;
}
else
{
iSinkBuffer = iAudioOutput->CreateSinkBufferL(TMediaId(KUidMediaTypeAudio), iOwnSinkBuffer);
}
}
iState = EStatePrimed;
PRINT("COggPlayController::PrimeL Out");
}
void COggPlayController::PlayL()
{
PRINT("COggPlayController::PlayL In");
if (iState!=EStatePrimed)
User::Leave(KErrNotReady);
// Clear the frequency analyser
Mem::FillZ(&iFreqArray, sizeof(iFreqArray));
// Do our own rate conversion, some firmware do it very badly.
if (iUsedRate == 0 && (iStreamState == EStreamOpened) && (iStreamError == KErrNone))
SetAudioCapsL(iDecoder->Rate(), iDecoder->Channels());
else if (iStreamState == EStreamNotOpen)
{
// The audio stream isn't ready, so start playing later
PlayDeferred();
return;
}
else if (iStreamError != KErrNone)
{
// There is a stream error, we can't play
User::Leave(iStreamError);
}
// Start playing now
PlayNowL();
}
void COggPlayController::PlayDeferred()
{
iPlayRequestPending = ETrue;
}
void COggPlayController::PlayNowL()
{
CFakeFormatDecode* fake = CFakeFormatDecode::NewL(
TFourCC(' ', 'P', '1', '6'),
iUsedChannels,
iUsedRate,
iDecoder->Bitrate());
CleanupStack::PushL(fake);
// NegiotiateL leaves with KErrNotSupported if you don't give a CMMFFormatDecode for it's source:
// indeed, it looks to be pretty useless if the source if not a CMMFFormatDecode. So use a
// fake CMMFFormatDecode class that just reports the configuration info (see CFakeFormatDecode)
iAudioOutput->NegotiateL(*fake);
CleanupStack::PopAndDestroy();
iAudioOutput->SinkPlayL();
// send first buffer to sink - sending a NULL buffer prompts it to request some data the usual way
iOggSource->SetSink(iAudioOutput);
iAudioOutput->EmptyBufferL(NULL, iOggSource, TMediaId(KUidMediaTypeAudio));
iState=EStatePlaying;
}
void COggPlayController::CustomCommand(TMMFMessage& aMessage)
{
if (aMessage.Destination().InterfaceId().iUid != KOggTremorUidControllerImplementation)
{
aMessage.Complete(KErrNotSupported);
return;
}
TInt err = KErrNone;
switch (aMessage.Function())
{
case EOggPlayControllerStreamWait:
// Complete now if the stream is open, otherwise mark that we have received the request
if (iStreamState == EStreamOpened)
aMessage.Complete(iStreamError);
else
{
iStreamState = EStreamStateRequested;
iStreamMessage = new TMMFMessage(aMessage);
if (!iStreamMessage)
aMessage.Complete(KErrNoMemory);
}
break;
case EOggPlayControllerCCGetAudioProperties:
{
TInt audioProperties[4];
audioProperties[0] = iRate;
audioProperties[1] = iChannels;
audioProperties[2] = iBitRate;
audioProperties[3] = iFileSize;
TPckg<TInt [4]> dataTo(audioProperties);
aMessage.WriteDataToClient(dataTo);
aMessage.Complete(KErrNone);
break;
}
case EOggPlayControllerCCGetFrequencies:
{
TRAP(err, GetFrequenciesL(aMessage));
aMessage.Complete(err);
break;
}
case EOggPlayControllerCCSetVolumeGain:
{
TRAP(err, SetVolumeGainL(aMessage));
aMessage.Complete(err);
break;
}
default:
{
err = KErrNotSupported;
aMessage.Complete(err);
break;
}
}
}
void COggPlayController::PauseL()
{
PRINT("COggPlayController::PauseL");
if (iPlayRequestPending)
{
iPlayRequestPending = EFalse;
return;
}
if (iState!=EStatePlaying)
User::Leave(KErrNotReady);
iAudioOutput->SinkPauseL();
iOggSource->SourcePauseL();
iState=EStatePrimed;
}
void COggPlayController::StopL()
{
PRINT("COggPlayController::StopL");
if (iPlayRequestPending)
{
iPlayRequestPending = EFalse;
return;
}
if ((iState!=EStatePrimed)&&(iState!=EStatePlaying))
User::Leave(KErrNotReady);
iAudioOutput->SinkStopL();
iState=EStateNotOpened;
iDecoder->Clear();
if (iFile)
iFile->Close();
delete iFile;
iFile = NULL;
PRINT("COggPlayController::StopL Out");
}
TTimeIntervalMicroSeconds COggPlayController::PositionL() const
{
if(iDecoder && (iState != EStateNotOpened) )
return( TTimeIntervalMicroSeconds(iDecoder->Position( ) * 1000) );
else
return TTimeIntervalMicroSeconds(0);
}
void COggPlayController::SetPositionL(const TTimeIntervalMicroSeconds& aPosition)
{
PRINT("COggPlayController::SetPositionL");
// const TInt64 KConst500 = TInt64(500);
TInt64 positionMilliseconds = aPosition.Int64() / 1000;
if (iDecoder)
iDecoder->Setposition(positionMilliseconds);
if (iOggSource)
{
// iOggSource->iTotalBufferBytes = (positionMilliseconds*TInt64(iUsedRate*iUsedChannels))/KConst500;
iOggSource->iTotalBufferBytes = 0;
}
}
TTimeIntervalMicroSeconds COggPlayController::DurationL() const
{
//PRINT("COggPlayController::DurationL");
return (iFileLength);
}
void COggPlayController::GetNumberOfMetaDataEntriesL(TInt& aNumberOfEntries)
{
PRINT("COggPlayController::GetNumberOfMetaDataEntriesL");
aNumberOfEntries = 5;
}
CMMFMetaDataEntry* COggPlayController::GetMetaDataEntryL(TInt aIndex)
{
PRINT("COggPlayController::GetMetaDataEntryL");
switch(aIndex)
{
case 0:
return (CMMFMetaDataEntry::NewL(_L("title"), iTitle));
break;
case 1:
return (CMMFMetaDataEntry::NewL(_L("album"), iAlbum));
break;
case 2:
return (CMMFMetaDataEntry::NewL(_L("artist"), iArtist));
break;
case 3:
return (CMMFMetaDataEntry::NewL(_L("genre"), iGenre));
break;
case 4:
return (CMMFMetaDataEntry::NewL(_L("albumtrack"), iTrackNumber));
break;
}
return NULL;
}
void COggPlayController::OpenFileL(const TDesC& aFile, TBool aOpenForInfo)
{
iFile = new(ELeave) RFile;
if (iFile->Open(*iFs, aFile, EFileShareReadersOnly) != KErrNone)
{
iState= EStateNotOpened;
delete iFile;
iFile = NULL;
TRACEF(COggLog::VA(_L("OpenFileL failed %S"), &aFile ));
User::Leave(KOggPlayPluginErrFileNotFound);
}
iState= EStateOpen;
TInt ret=0;
if (aOpenForInfo)
{
ret = iDecoder->OpenInfo(iFile) ;
}
else
{
ret = iDecoder->Open(iFile) ;
}
if( ret < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -