qtmobility/plugins/multimedia/symbian/mmf/audiosource/s60audiocapturesession.cpp
changeset 4 90517678cc4f
child 5 453da2cfceef
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "s60audiocapturesession.h"
       
    43 #include <QtCore/qdebug.h>
       
    44 #include <QtCore/qurl.h>
       
    45 #include <QDir>
       
    46 
       
    47 #include <Mda\Common\Audio.h>
       
    48 #include <Mda\Common\Resource.h>
       
    49 #include <Mda\Client\Utility.h>
       
    50 #include <MdaAudioSampleEditor.h>
       
    51 #include <mmf\common\mmfcontrollerpluginresolver.h>
       
    52 #include <mmf\common\mmfcontroller.h>
       
    53 #include <BADESCA.H>
       
    54 #include <BAUTILS.H>
       
    55 #include <coemain.h>  
       
    56 
       
    57 _LIT(KAudioDummyFile, "c:\\data\\temp\\temp.wav");
       
    58 
       
    59 S60AudioCaptureSession::S60AudioCaptureSession(QObject *parent):
       
    60     QObject(parent)
       
    61     , m_recorderUtility(NULL)    
       
    62     , m_captureState(ENotInitialized)    
       
    63     , m_controllerIdMap(QHash<QString, ControllerData>())    
       
    64     , m_audioCodeclist(QHash<QString, CodecData>())    
       
    65 {
       
    66     TRAPD(err, initializeSessionL());
       
    67     qWarning()<<err;
       
    68 }
       
    69 
       
    70 void S60AudioCaptureSession::initializeSessionL()
       
    71 {    
       
    72     m_recorderUtility = CMdaAudioRecorderUtility::NewL(*this, 0, 80,(TMdaPriorityPreference) 0x5210001);        
       
    73     updateAudioContainersL();    
       
    74     populateAudioCodecsDataL();
       
    75     setDefaultSettings();
       
    76 }
       
    77 
       
    78 S60AudioCaptureSession::~S60AudioCaptureSession()
       
    79 {       
       
    80     delete m_recorderUtility;    
       
    81 }
       
    82 
       
    83 QAudioFormat S60AudioCaptureSession::format() const
       
    84 {
       
    85     return m_format;
       
    86 }
       
    87 
       
    88 bool S60AudioCaptureSession::setFormat(const QAudioFormat &format)
       
    89 {		
       
    90     m_format = format;
       
    91     return true;
       
    92 }
       
    93 
       
    94 QStringList S60AudioCaptureSession::supportedAudioCodecs() const
       
    95 {    
       
    96 	return m_audioCodeclist.keys();
       
    97 }
       
    98 
       
    99 QStringList S60AudioCaptureSession::supportedAudioContainers() const
       
   100 {
       
   101     return m_controllerIdMap.keys();
       
   102 }
       
   103 
       
   104 QString S60AudioCaptureSession::codecDescription(const QString &codecName)
       
   105 {
       
   106     if (m_audioCodeclist.keys().contains(codecName))
       
   107         return m_audioCodeclist[codecName].codecDescription;
       
   108     else
       
   109         return QString();
       
   110 }
       
   111 
       
   112 QString S60AudioCaptureSession::audioContainerDescription(const QString &containerName)
       
   113 {   
       
   114     if (m_controllerIdMap.keys().contains(containerName))
       
   115         return m_controllerIdMap[containerName].destinationFormatDescription;
       
   116     else
       
   117         return QString();
       
   118 }
       
   119 
       
   120 bool S60AudioCaptureSession::setAudioCodec(const QString &codecName)
       
   121 {    
       
   122     QStringList codecs = supportedAudioCodecs();
       
   123     if(codecs.contains(codecName)) {
       
   124         m_format.setCodec(codecName);
       
   125         return true;
       
   126     }    
       
   127     return false;
       
   128 }
       
   129 
       
   130 bool S60AudioCaptureSession::setAudioContainer(const QString &containerMimeType) 
       
   131 {    
       
   132     QStringList containers = supportedAudioContainers();
       
   133     if(containers.contains(containerMimeType)) { 
       
   134         m_container = containerMimeType;
       
   135         return true;
       
   136     }
       
   137     return false;
       
   138 }
       
   139 
       
   140 QString S60AudioCaptureSession::audioCodec() const
       
   141 {   
       
   142     return m_format.codec();
       
   143 }
       
   144 
       
   145 QString S60AudioCaptureSession::audioContainer() const
       
   146 {
       
   147     return m_container;
       
   148 }
       
   149 
       
   150 QUrl S60AudioCaptureSession::outputLocation() const
       
   151 {
       
   152     return m_sink;
       
   153 }
       
   154 
       
   155 bool S60AudioCaptureSession::setOutputLocation(const QUrl& sink)
       
   156 {
       
   157     QString filename = QDir::toNativeSeparators(m_sink.toString());
       
   158     TPtrC16 path(reinterpret_cast<const TUint16*>(filename.utf16()));         
       
   159     TRAPD(err, BaflUtils::EnsurePathExistsL(CCoeEnv::Static()->FsSession(),path));
       
   160     if (err==KErrNone) {
       
   161         m_sink = sink;
       
   162         return true;
       
   163     }else 
       
   164         return false;    
       
   165 }
       
   166 
       
   167 qint64 S60AudioCaptureSession::position() const
       
   168 {    
       
   169     if ((m_captureState != ERecording) || !m_recorderUtility) 
       
   170         return 0;
       
   171         
       
   172     return m_recorderUtility->Duration().Int64() / 1000;        
       
   173 }
       
   174 
       
   175 void S60AudioCaptureSession::record()
       
   176 {   
       
   177     if (!m_recorderUtility)
       
   178         return;
       
   179     
       
   180     if (m_captureState == EInitialized || m_captureState == ERecordComplete) {
       
   181         QString filename = QDir::toNativeSeparators(m_sink.toString());        
       
   182         TPtrC16 sink(reinterpret_cast<const TUint16*>(filename.utf16()));         
       
   183         TUid controllerUid(TUid::Uid(m_controllerIdMap[m_container].controllerUid));
       
   184         TUid formatUid(TUid::Uid(m_controllerIdMap[m_container].destinationFormatUid));
       
   185                 
       
   186         TRAPD(err, 
       
   187         if (m_container != "audio/amr")   
       
   188             m_recorderUtility->OpenFileL(sink, controllerUid, KNullUid, formatUid);
       
   189         else   
       
   190             m_recorderUtility->OpenFileL(sink);
       
   191         );       
       
   192         qWarning() << err;
       
   193     }else if (m_captureState == EPaused) {        
       
   194         m_recorderUtility->SetPosition(m_pausedPosition);
       
   195         TRAPD(error, m_recorderUtility->RecordL());
       
   196         qWarning() << error;
       
   197         m_captureState = ERecording;
       
   198         emit stateChanged(m_captureState);
       
   199     }        
       
   200 }
       
   201 
       
   202 void S60AudioCaptureSession::setDefaultSettings()
       
   203 {
       
   204     // Setting AMR to default format if supported
       
   205     if (m_controllerIdMap.count() > 0) {
       
   206         if ( m_controllerIdMap.contains("audio/amr"))
       
   207             m_container = QString("audio/amr");
       
   208         else
       
   209             m_container = m_controllerIdMap.keys()[0];
       
   210     }
       
   211     if (m_audioCodeclist.keys().count() > 0) {
       
   212         if (m_audioCodeclist.keys().contains("AMR"))
       
   213             m_format.setCodec("AMR");
       
   214         else
       
   215             m_format.setCodec(m_audioCodeclist.keys()[0]);
       
   216     }
       
   217 }
       
   218 
       
   219 void S60AudioCaptureSession::pause()
       
   220 {  
       
   221     if (!m_recorderUtility)
       
   222         return;
       
   223     
       
   224     m_pausedPosition = m_recorderUtility->Position();
       
   225     m_recorderUtility->Stop();
       
   226     m_captureState = EPaused;
       
   227     emit stateChanged(m_captureState);    
       
   228 }
       
   229 
       
   230 void S60AudioCaptureSession::stop()
       
   231 {
       
   232     if (!m_recorderUtility)
       
   233         return;
       
   234     
       
   235     m_recorderUtility->Stop();
       
   236     m_recorderUtility->Close();        
       
   237     m_captureState = ERecordComplete;
       
   238     emit stateChanged(m_captureState);
       
   239 }
       
   240 
       
   241 void S60AudioCaptureSession::setCaptureDevice(const QString &deviceName)
       
   242 {
       
   243     m_captureDevice = deviceName;
       
   244 }
       
   245 
       
   246 void S60AudioCaptureSession::MoscoStateChangeEvent(CBase* aObject,
       
   247         TInt aPreviousState, TInt aCurrentState, TInt aErrorCode)
       
   248 {    
       
   249 	TRAPD(err, MoscoStateChangeEventL(aObject, aPreviousState, aCurrentState, NULL));    
       
   250 	qWarning() << err;
       
   251 }
       
   252 
       
   253 void S60AudioCaptureSession::MoscoStateChangeEventL(CBase* aObject,
       
   254         TInt aPreviousState, TInt aCurrentState, TInt aErrorCode)
       
   255 {    
       
   256 	if (aObject != m_recorderUtility)
       
   257 	    return;
       
   258 	
       
   259 		switch(aCurrentState) {
       
   260         case CMdaAudioClipUtility::EOpen: {            
       
   261             if(aPreviousState == CMdaAudioClipUtility::ENotReady) {                
       
   262                 if (m_captureState == EInitializing) {                    
       
   263                     retrieveSupportedAudioSampleRatesL();                   
       
   264                     m_recorderUtility->Close();                    
       
   265                     m_captureState = EInitialized;
       
   266                     emit stateChanged(m_captureState);
       
   267                 }else {         
       
   268                     applyAudioSettingsL();                            
       
   269                     m_recorderUtility->SetAudioDeviceMode(CMdaAudioRecorderUtility::ELocal);
       
   270                     m_recorderUtility->SetGain(m_recorderUtility->MaxGain());                    
       
   271                     m_recorderUtility->SetPosition(TTimeIntervalMicroSeconds(0));
       
   272                     m_recorderUtility->CropL();
       
   273                     m_recorderUtility->RecordL();
       
   274                     m_captureState = EOpenCompelete;                    
       
   275                     emit stateChanged(m_captureState);
       
   276                     }
       
   277                 break;
       
   278             }
       
   279         }		
       
   280         case CMdaAudioClipUtility::ENotReady: {            
       
   281             m_captureState = EInitialized;            
       
   282             emit stateChanged(m_captureState);
       
   283             break;
       
   284         }
       
   285         case CMdaAudioClipUtility::ERecording: {            
       
   286             m_captureState = ERecording;            
       
   287             emit stateChanged(m_captureState);
       
   288             break;
       
   289         }
       
   290         default: {            
       
   291             break;
       
   292         }   
       
   293 		}    
       
   294 }
       
   295 
       
   296 void S60AudioCaptureSession::updateAudioContainersL()
       
   297 {
       
   298     CMMFControllerPluginSelectionParameters* pluginParameters = 
       
   299     	CMMFControllerPluginSelectionParameters::NewLC();
       
   300 	CMMFFormatSelectionParameters* formatParameters = 
       
   301 		CMMFFormatSelectionParameters::NewLC();
       
   302 	 
       
   303 	pluginParameters->SetRequiredRecordFormatSupportL(*formatParameters);
       
   304 	 
       
   305 	RArray<TUid> ids;
       
   306 	CleanupClosePushL(ids);
       
   307 	User::LeaveIfError(ids.Append(KUidMediaTypeAudio));  
       
   308 
       
   309 	pluginParameters->SetMediaIdsL(ids, 
       
   310 		CMMFPluginSelectionParameters::EAllowOnlySuppliedMediaIds);
       
   311 	 
       
   312 	RMMFControllerImplInfoArray controllers; 
       
   313 	CleanupResetAndDestroyPushL(controllers);
       
   314 	 
       
   315 	//Get all audio record controllers/formats that are supported
       
   316 	pluginParameters->ListImplementationsL(controllers);
       
   317 	 
       
   318 	for (TInt index=0; index<controllers.Count(); index++) {
       
   319 		const RMMFFormatImplInfoArray& recordFormats = 
       
   320 			controllers[index]->RecordFormats();
       
   321 		for (TInt j=0; j<recordFormats.Count(); j++) {
       
   322 			const CDesC8Array& mimeTypes = recordFormats[j]->SupportedMimeTypes();
       
   323 			TInt count = mimeTypes.Count();
       
   324 			if (count > 0) {
       
   325 				TPtrC8 mimeType = mimeTypes[0];
       
   326 				QString type = QString::fromUtf8((char *)mimeType.Ptr(), mimeType.Length());
       
   327 				if (type != "audio/mp4") {
       
   328                     ControllerData data;
       
   329                     data.controllerUid = controllers[index]->Uid().iUid;
       
   330                     data.destinationFormatUid = recordFormats[j]->Uid().iUid;
       
   331                     data.destinationFormatDescription = QString::fromUtf16(
       
   332                             recordFormats[j]->DisplayName().Ptr(),
       
   333                             recordFormats[j]->DisplayName().Length());                
       
   334                     m_controllerIdMap[type] = data;
       
   335 				}
       
   336 			}
       
   337 		}
       
   338 	}	
       
   339 	CleanupStack::PopAndDestroy(4);//controllers, ids, formatParameters, pluginParameters
       
   340 }
       
   341 
       
   342 void S60AudioCaptureSession::retrieveSupportedAudioSampleRatesL()
       
   343 {       
       
   344     if (!m_recorderUtility || m_captureState != EInitializing) 
       
   345         return;
       
   346     
       
   347     RArray<TUint> supportedSampleRates;
       
   348     CleanupClosePushL(supportedSampleRates);
       
   349     m_recorderUtility->GetSupportedSampleRatesL(supportedSampleRates);        
       
   350     for (TInt j = 0; j < supportedSampleRates.Count(); j++ ) {            
       
   351         m_supportedSampleRates.append(supportedSampleRates[j]);
       
   352         //qDebug()<<"S60AudioCaptureSession::doPopulateAudioCodecsDataL, samplerate: "<<m_supportedSampleRates[j];                        
       
   353     }            
       
   354     CleanupStack::PopAndDestroy(&supportedSampleRates);    
       
   355 }
       
   356 
       
   357 QList<int> S60AudioCaptureSession::supportedAudioSampleRates() const
       
   358 {
       
   359     return m_supportedSampleRates;
       
   360 }
       
   361 
       
   362 void S60AudioCaptureSession::populateAudioCodecsDataL()
       
   363 {
       
   364     //qDebug() << "S60AudioCaptureSession::doInitializeAudioRecorderL START";    
       
   365     if (!m_recorderUtility)  
       
   366         return;
       
   367         
       
   368     if (m_controllerIdMap.contains("audio/amr")) {       
       
   369         CodecData data;              
       
   370         data.codecDescription = QString("GSM AMR Codec");
       
   371         m_audioCodeclist[QString("AMR")]=data;
       
   372     }   
       
   373     if (m_controllerIdMap.contains("audio/basic")) {
       
   374         CodecData data;           
       
   375         data.fourCC = KMMFFourCCCodeALAW;                   
       
   376         data.codecDescription = QString("Sun/Next ""Au"" audio codec");
       
   377         m_audioCodeclist[QString("AULAW")]=data;            
       
   378     }
       
   379     if (m_controllerIdMap.contains("audio/wav")) {            
       
   380         CodecData data;           
       
   381         data.fourCC = KMMFFourCCCodePCM16;                   
       
   382         data.codecDescription = QString("Pulse code modulation");
       
   383         m_audioCodeclist[QString("PCM")]=data;
       
   384     }    
       
   385     if (m_controllerIdMap.contains("audio/mp4")) {            
       
   386         CodecData data;           
       
   387         data.fourCC = KMMFFourCCCodeAAC;                   
       
   388         data.codecDescription = QString("Advanced Audio Codec");
       
   389         m_audioCodeclist[QString("AAC")]=data;
       
   390     }        
       
   391     
       
   392     if (m_controllerIdMap.contains("audio/wav")) {            
       
   393         TMdaFileClipLocation location;   
       
   394         location.iName = KAudioDummyFile();
       
   395         TMdaWavClipFormat format;
       
   396         m_captureState = EInitializing;
       
   397         m_recorderUtility->OpenL(&location, &format);             
       
   398     }    
       
   399 }
       
   400 
       
   401 void S60AudioCaptureSession::applyAudioSettingsL()
       
   402 {
       
   403     //qDebug() << "S60AudioCaptureSession::applyAudioSettings START";  
       
   404     if (!m_recorderUtility)
       
   405         return;
       
   406     
       
   407     TFourCC fourCC = m_audioCodeclist[m_format.codec()].fourCC;    
       
   408     
       
   409     //set destination datatype
       
   410     RArray<TFourCC> supportedDataTypes;
       
   411     CleanupClosePushL(supportedDataTypes);
       
   412     m_recorderUtility->GetSupportedDestinationDataTypesL(supportedDataTypes);
       
   413     //qDebug() << "S60AudioCaptureSession::applyAudioSettingsL, datatype count"<<supportedDataTypes.Count();
       
   414 
       
   415     for (TInt k = 0; k < supportedDataTypes.Count(); k++ ) {
       
   416         qDebug() << "S60AudioCaptureSession::applyAudioSettingsL, codec"<<m_format.codec()<<"datatype"<<supportedDataTypes[k].FourCC();
       
   417         if (supportedDataTypes[k].FourCC() == fourCC.FourCC()) {
       
   418             //qDebug() << "S60AudioCaptureSession::applyAudioSettingsL, codec"<<m_format.codec()<<"matched datatype"<<supportedDataTypes[k].FourCC();
       
   419             m_recorderUtility->SetDestinationDataTypeL(supportedDataTypes[k]);
       
   420             break;
       
   421         }
       
   422     }
       
   423     CleanupStack::PopAndDestroy(&supportedDataTypes);
       
   424     
       
   425     RArray<TUint> supportedSampleRates;
       
   426     CleanupClosePushL(supportedSampleRates);
       
   427     m_recorderUtility->GetSupportedSampleRatesL(supportedSampleRates);    
       
   428     for (TInt i = 0; i < supportedSampleRates.Count(); i++ ) {
       
   429         TUint supportedSampleRate = supportedSampleRates[i];
       
   430         if (supportedSampleRate == m_format.frequency()) { 
       
   431             m_recorderUtility->SetDestinationSampleRateL(m_format.frequency());
       
   432             break;
       
   433         }        
       
   434     }
       
   435     CleanupStack::PopAndDestroy(&supportedSampleRates);
       
   436  
       
   437     RArray<TUint> supportedChannels;
       
   438     CleanupClosePushL(supportedChannels);
       
   439     m_recorderUtility->GetSupportedNumberOfChannelsL(supportedChannels);
       
   440     for (TInt l = 0; l < supportedChannels.Count(); l++ ) {
       
   441         if (supportedChannels[l] == m_format.channels()) {
       
   442             m_recorderUtility->SetDestinationNumberOfChannelsL(m_format.channels());
       
   443             break;
       
   444         }
       
   445     }
       
   446     CleanupStack::PopAndDestroy(&supportedChannels);
       
   447     //qDebug() << "S60AudioCaptureSession::applyAudioSettings END";        
       
   448 }
       
   449 
       
   450 TFourCC S60AudioCaptureSession::determinePCMFormat()
       
   451 {
       
   452     //qDebug() << "S60AudioCaptureSession::determinePCMSampleSize START";    
       
   453     TFourCC fourCC;    
       
   454     
       
   455     if (m_format.sampleSize() == 8) {
       
   456         // 8 bit
       
   457         switch (m_format.sampleType()) {
       
   458         case QAudioFormat::SignedInt: {
       
   459             fourCC.Set(KMMFFourCCCodePCM8);
       
   460             break;
       
   461         }
       
   462         case QAudioFormat::UnSignedInt: {
       
   463             fourCC.Set(KMMFFourCCCodePCMU8);
       
   464             break;
       
   465         }
       
   466         case QAudioFormat::Float: 
       
   467         case QAudioFormat::Unknown:
       
   468         default: {
       
   469             fourCC.Set(KMMFFourCCCodePCM8);
       
   470             break;
       
   471         }
       
   472         }
       
   473     } else if (m_format.sampleSize() == 16) {
       
   474         // 16 bit 
       
   475         switch (m_format.sampleType()) {
       
   476         case QAudioFormat::SignedInt: {
       
   477             fourCC.Set(m_format.byteOrder()==QAudioFormat::BigEndian?
       
   478                 KMMFFourCCCodePCM16B:KMMFFourCCCodePCM16);
       
   479             break;
       
   480         }
       
   481         case QAudioFormat::UnSignedInt: {
       
   482             fourCC.Set(m_format.byteOrder()==QAudioFormat::BigEndian?
       
   483                 KMMFFourCCCodePCMU16B:KMMFFourCCCodePCMU16);
       
   484             break;
       
   485         }
       
   486         default: {
       
   487             fourCC.Set(KMMFFourCCCodePCM16);
       
   488             break;
       
   489         }
       
   490         }    
       
   491     }    
       
   492     //qDebug() << "S60AudioCaptureSession::determinePCMSampleSize END";
       
   493     return fourCC;
       
   494 }