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

📄 oggplaycontroller.cpp

📁 OggPlay for Symbian 是symbian上的一个媒体播放程序的源码。它支持ogg,wav等等多媒体格式。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
*  Copyright (c) 2004 OggPlayTeam
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "OggPlayController.h"
#include <charconv.h>
#include <utf.h>
#include "OggLog.h"
#include "Plugin\ImplementationUIDs.hrh"
#include "Plugin\OggPlayControllerCustomCommands.h"

#if 1
#include <e32svr.h> 
#define PRINT(x) TRACEF(_L(x));
//#define PRINT(x) RDebug::Print _L(x);
#else
#define PRINT()
#endif

// Nokia phones don't seem to like large buffers, so just use one size (4K)
#define USE_FIXED_SIZE_BUFFERS

// Buffer sizes to use
// (approx. 0.1s of audio per buffer)
#if defined(USE_FIXED_SIZE_BUFFERS)
const TInt KBufferSize48K = 4096;
const TInt KBufferSize32K = 4096;
const TInt KBufferSize22K = 4096;
const TInt KBufferSize16K = 4096;
const TInt KBufferSize11K = 4096;
#else
const TInt KBufferSize48K = 16384;
const TInt KBufferSize32K = 12288;
const TInt KBufferSize22K = 8192;
const TInt KBufferSize16K = 6144;
const TInt KBufferSize11K = 4096;
#endif

COggPlayController* COggPlayController::NewL(RFs* aFs, MDecoder *aDecoder)
{
    PRINT("COggPlayController::NewL()");

	// Take ownership of the file session and the decoder
    COggPlayController* self = new COggPlayController(aFs, aDecoder);
	if (!self)
	{
		delete aDecoder;

		aFs->Close();
		delete aFs;

		User::Leave(KErrNoMemory);
	}

    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();
    return self;
}

COggPlayController::COggPlayController(RFs* aFs, MDecoder *aDecoder)
: iFs(aFs), iDecoder(aDecoder)
{
}

COggPlayController::~COggPlayController()
{
    PRINT("COggPlayController::~COggPlayController In");
	iState = EStateDestroying;

	delete iStream;
	delete iStreamMessage;

    if (iOwnSinkBuffer) 
        delete iSinkBuffer;

	delete iOggSource;

	if (iAudioOutput)
        iAudioOutput->SinkThreadLogoff();

	iDecoder->Clear();
	if (iFile)
		iFile->Close();

	delete iFile;
	delete iDecoder;

	iFs->Close();
	delete iFs;

    PRINT("COggPlayController::~COggPlayController Out");
    COggLog::Exit();  // MUST BE AFTER LAST TRACE, otherwise will leak memory
}

void COggPlayController::ConstructL()
{
    PRINT("COggPlayController::ConstructL() In");

	// Construct custom command parsers
    CMMFAudioPlayDeviceCustomCommandParser* audPlayDevParser = 
                                     CMMFAudioPlayDeviceCustomCommandParser::NewL(*this);
    CleanupStack::PushL(audPlayDevParser);
    AddCustomCommandParserL(*audPlayDevParser); //parser now owned by controller framework
    CleanupStack::Pop();//audPlayDevParser

    CMMFAudioPlayControllerCustomCommandParser* audPlayCtrlParser =
                                     CMMFAudioPlayControllerCustomCommandParser::NewL(*this);
    CleanupStack::PushL(audPlayCtrlParser);
    AddCustomCommandParserL(*audPlayCtrlParser); //parser now owned by controller framework
    CleanupStack::Pop(audPlayCtrlParser);

    iState = EStateNotOpened;
     
	// We do not want to look at file duration when	discovering the file: it takes too long
	// If DurationL is asked before we actually have the information, pretend length is 5 minutes.
	iFileLength = TTimeIntervalMicroSeconds(5*60*1000000);

    iOggSource = new(ELeave) COggSource(*this);

	// Open an audio stream (used for determining audio capabilities)
	iStream = CMdaAudioOutputStream::NewL(*this);
	iStream->Open(&iSettings);

	PRINT("COggPlayController::ConstructL() Out");
}

_LIT(KRandomRingingToneFileName, "random_ringing_tone.ogg");
_LIT(KRandomRingingToneTitle, "this is a random ringing tone");
void COggPlayController::AddDataSourceL(MDataSource& aDataSource)
{
    PRINT("COggPlayController::AddDataSourceL In");

    if ( iState != EStateNotOpened )
    {
        User::Leave(KOggPlayPluginErrNotReady);
    }

    iRandomRingingTone = EFalse;
    TUid uid = aDataSource.DataSourceType() ;
    if (uid == KUidMmfFileSource)
    {
        CMMFFile* aFile = STATIC_CAST(CMMFFile*, &aDataSource);
        iFileName = aFile->FullName();

	    TParsePtrC aP(iFileName);
        TBool result = aP.NameAndExt().CompareF(KRandomRingingToneFileName) == 0;
        if ( result )
        {
            // Use a random file, for ringing tones
            TFileName aPathToSearch = aP.Drive();
            aPathToSearch.Append ( aP.Path() );
            CDir* dirList;
            User::LeaveIfError(iFs->GetDir(aPathToSearch,
                KEntryAttMaskSupported,ESortByName,dirList));
            TInt nbFound=0;
            TInt i; 
            for (i=0;i<dirList->Count();i++)
            {
                TParsePtrC aParser((*dirList)[i].iName);
                TBool found = ( aParser.Ext().CompareF(_L(".ogg")) == 0 );
                TBool theRandomTone = ( ( (*dirList)[i].iName).CompareF(KRandomRingingToneFileName) == 0);
                if (found && !theRandomTone)
                    nbFound++;
            }
            if (nbFound == 0)
            {
                // Only the random_ringing_tone.ogg in that directory, leave
                User::Leave(KErrNotFound);
            }
#if defined(SERIES60V3)
			TInt64 rnd64 = Math::Random();
			TInt64 maxInt64 = MAKE_TINT64(1, 0);
			TInt64 nbFound64 = nbFound;
			TInt64 picked64 = (rnd64 * nbFound64) / maxInt64;
			TInt picked = I64LOW(picked64);
#else //2.x
			TInt64 rnd64 = TInt64(0, Math::Random());
			TInt64 maxInt64 = TInt64(1, 0);
			TInt64 nbFound64 = nbFound;
			TInt64 picked64 = (rnd64 * nbFound64) / maxInt64;
			TInt picked = picked64.Low();
#endif
			

            nbFound=-1;
            for (i=0;i<dirList->Count();i++)
            {
                TParsePtrC aParser((*dirList)[i].iName);
                TBool found = ( aParser.Ext().CompareF(_L(".ogg")) == 0 ); 
                TBool theRandomTone = ( ( (*dirList)[i].iName).CompareF(KRandomRingingToneFileName) == 0);
                if (found && !theRandomTone)
                    nbFound++;
                if (nbFound == picked)
                    break;
            }
            iFileName = aPathToSearch;
            iFileName.Append ( (*dirList)[i].iName );
            
            TRACEF(COggLog::VA(_L("Random iFileName choosen %S "),&iFileName ));
            delete dirList;
            iRandomRingingTone = ETrue;
        }
    }
    else
    {
        User::Leave(KOggPlayPluginErrNotSupported);
    }

    
    TRACEF(COggLog::VA(_L("iFileName %S "),&iFileName ));
    // Open the file here, in order to get the tags.
    OpenFileL(iFileName,ETrue);
    // Save the tags.
    
  iDecoder->Clear(); // Close the file. This is required for the ringing tone stuff.

  if (iFile)
	iFile->Close();
  
  delete iFile;
  iFile = NULL;
  
  iState = EStateNotOpened;
  PRINT("COggPlayController::AddDataSourceL Out");
}

void COggPlayController::AddDataSinkL(MDataSink& aDataSink)
{
    PRINT("COggPlayController::AddDataSinkL In");
    
    if (aDataSink.DataSinkType() != KUidMmfAudioOutput)
        User::Leave(KErrNotSupported);
    if (iAudioOutput)
        User::Leave(KErrNotSupported);

    iAudioOutput = static_cast<CMMFAudioOutput*>(&aDataSink);
    iAudioOutput->SinkThreadLogon(*this);

    iAudioOutput->SetSinkPrioritySettings(iMMFPrioritySettings);
    PRINT("COggPlayController::AddDataSinkL Out");
}

void COggPlayController::RemoveDataSourceL(MDataSource& /*aDataSource*/)
{
    PRINT("COggPlayController::RemoveDataSourceL");
    // Nothing to do
}
void COggPlayController::RemoveDataSinkL(MDataSink&  aDataSink)
{
    PRINT("COggPlayController::RemoveDataSinkL");

    if (iState==EStatePlaying)
        User::Leave(KErrNotReady);

    if (iAudioOutput==&aDataSink) 
        iAudioOutput=NULL;
}

void COggPlayController::SetPrioritySettings(const TMMFPrioritySettings& aPrioritySettings)
{   
    PRINT("COggPlayController::SetPrioritySettingsL");
    // Not implemented yet
    iMMFPrioritySettings = aPrioritySettings;
    if (iAudioOutput)
        iAudioOutput->SetSinkPrioritySettings(aPrioritySettings);
}

TInt COggPlayController::SendEventToClient(const TMMFEvent& aEvent)
    {
    PRINT("COggPlayController::SendEventToClient");

    TRACEF(COggLog::VA(_L("Event %i %i"), aEvent.iEventType,aEvent.iErrorCode ));
    TMMFEvent myEvent = aEvent;
    if  (myEvent.iErrorCode == KErrUnderflow)
     myEvent.iErrorCode = KErrNone; // Client expect KErrNone when playing as completed correctly

    if (aEvent.iErrorCode == KErrDied)
        iState = EStateInterrupted;

	return DoSendEventToClient(myEvent);
    }

void COggPlayController::ResetL()
{
    PRINT("COggPlayController::ResetL");
    iAudioOutput=NULL;
    iDecoder->Clear();

	if (iFile)
		iFile->Close();

    delete iFile;
	iFile = NULL;

	iState= EStateNotOpened;
}

TBool COggPlayController::GetNextLowerRate(TInt& usedRate, TMdaAudioDataSettings::TAudioCaps& rt)
{
  TBool retValue = ETrue;
  switch (usedRate)
  {
	case 48000:
		usedRate = 44100;
		rt = TMdaAudioDataSettings::ESampleRate44100Hz;
		break;

	case 44100:
		usedRate = 32000;
		rt = TMdaAudioDataSettings::ESampleRate32000Hz;
		break;

	case 32000:
		usedRate = 22050;
		rt = TMdaAudioDataSettings::ESampleRate22050Hz;
		break;

	case 22050:
		usedRate = 16000;
		rt = TMdaAudioDataSettings::ESampleRate16000Hz;
		break;

	case 16000:
		usedRate = 11025;
		rt = TMdaAudioDataSettings::ESampleRate11025Hz;
		break;

	case 11025:
		usedRate = 8000;
		rt = TMdaAudioDataSettings::ESampleRate8000Hz;
		break;

	default:
		retValue = EFalse;
		break;
  }

  return retValue;
}

void COggPlayController::SetAudioCapsL(TInt theRate, TInt theChannels)
{
  TMdaAudioDataSettings::TAudioCaps ac(TMdaAudioDataSettings::EChannelsMono);
  TMdaAudioDataSettings::TAudioCaps rt(TMdaAudioDataSettings::ESampleRate8000Hz);
  TBool convertChannel = EFalse;
  TBool convertRate = EFalse;

  iUsedRate = theRate;
  if (theRate==8000) rt= TMdaAudioDataSettings::ESampleRate8000Hz;
  else if (theRate==11025) rt= TMdaAudioDataSettings::ESampleRate11025Hz;
  else if (theRate==16000) rt= TMdaAudioDataSettings::ESampleRate16000Hz;
  else if (theRate==22050) rt= TMdaAudioDataSettings::ESampleRate22050Hz;
  else if (theRate==32000) rt= TMdaAudioDataSettings::ESampleRate32000Hz;
  else if (theRate==44100) rt= TMdaAudioDataSettings::ESampleRate44100Hz;
  else if (theRate==48000) rt= TMdaAudioDataSettings::ESampleRate48000Hz;
  else
  {
      // Rate not supported by the phone
	  TRACEF(COggLog::VA(_L("SetAudioCaps: Non standard rate: %d"), theRate));

	  // Convert to nearest rate
      convertRate = ETrue;
	  if (theRate>48000)
	  {
		  iUsedRate = 48000;
	      rt = TMdaAudioDataSettings::ESampleRate48000Hz;
	  }
	  else if (theRate>44100)
	  {
		  iUsedRate = 44100;
	      rt = TMdaAudioDataSettings::ESampleRate44100Hz;
	  }
	  else if (theRate>32000)
	  {
		  iUsedRate = 32000;
	      rt = TMdaAudioDataSettings::ESampleRate32000Hz;
	  }
	  else if (theRate>22050)
	  {
		  iUsedRate = 22050;
	      rt = TMdaAudioDataSettings::ESampleRate22050Hz;
	  }
	  else if (theRate>16000)
	  {
		  iUsedRate = 16000;
	      rt = TMdaAudioDataSettings::ESampleRate16000Hz;
	  }
	  else if (theRate>11025)
	  {
		  iUsedRate = 11025;
	      rt = TMdaAudioDataSettings::ESampleRate11025Hz;
	  }
	  else if (theRate>8000)
	  {
		  iUsedRate = 8000;
	      rt = TMdaAudioDataSettings::ESampleRate8000Hz;
	  }
	  else
	  {
		  // Frequencies less than 8KHz are not supported
	      // iEnv->OggErrorMsgL(R_OGG_ERROR_20, R_OGG_ERROR_12);
		  User::Leave(KErrNotSupported);
	  }
  }

  iUsedChannels = theChannels;
  if (iUsedChannels == 1)
	  ac = TMdaAudioDataSettings::EChannelsMono;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -