⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oggplaycontroller.cpp

📁 OggPlay for Symbian 是symbian上的一个媒体播放程序的源码。它支持ogg,wav等等多媒体格式。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  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 + -