Problems with CMdaAudioInputStream and RHTTPRequest coexisting.
| Thu, 2007-12-13 18:19 | |
|
Hi all, I want to write a streaming application that sends sound to an HTTP server using HTTP POST. Basically, I have that kind of code : /*On the HTTP side, only OverallDataSize is called 3 times in a row just after SubmitL. Also, after closing, I'm getting a KERN-EXEC 3. If it can be of interest, by messing some parameters and returning an OverallDataSize, I can get the program to send something and not crash, but it always sends after the audio capture has been stopped. Did I do something wrong, is there some code missing ? I can put more detailed code if necessary. Thanks in advance for your help. |
|






Forum posts: 159
You'll have to post more code
Forum posts: 116
Post more code...
Chao,
Raghav
Forum posts: 5
It took some time, but I think I've gathered everything that can be meaningful, but this is rather long
// Classes
class HttpAudioStream
{
static HttpAudioStream * New();
TBool Start(const TDesC8& aUri);
Pipe * iPipe;
CAudioStreamEngine * iAudioEngine;
CWebClientEngine * iWebEngine;
TBool iRunning;
};
class CAudioStreamEngine : public CBase, MMdaAudioInputStreamCallback
{
void Record(Pipe*, BasicNotify*);
virtual void MaiscOpenComplete(TInt aError);
virtual void MaiscBufferCopied(TInt aError, const TDesC8& aBuffer);
HBufC8* iStreamBuffer;
CMdaAudioInputStream* iInputStream;
TMdaAudioDataSettings iStreamSettings;
Pipe* iPipe ;
BasicNotify* iNotify;
};
class CWebClientEngine : public HC_EventHandler, public BasicNotify
{
// Inherited from HC_EventHandler interface
void TransactionEnd(TInt aStatus);
void ClientEvent( const TDesC& aEventDescription );
// Inherited from BasicNotify interface
void Notify(TInt);
void StreamPost(const TDesC8&, Pipe*);
RHTTPSession iSession;
RHTTPTransaction iTransaction;
TBool iRunning;
HC_DataSupplier * iPostData;
HC_BaseEventHandler * iBaseEventHandler;
HC_EventHandler * iEventInterface;
}
class HC_DataSupplier : public CBase, public MHTTPDataSupplier, public BasicNotify
{
TBool PostPipe(Pipe *);
// methods inherited from MHTTPDataSupplier
virtual TBool GetNextDataPart(TPtrC8& aDataPart);
virtual void ReleaseData();
virtual TInt OverallDataSize();
virtual TInt Reset();
}
class HC_BaseEventHandler : public CBase, public MHTTPTransactionCallback
{
public:
// methods from MHTTPTransactionCallback
/*virtual*/ void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
/*virtual*/ TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
void HandleRunErrorL( TInt aError );
};
// Constructors
// First, iHttpAudioStream, an HttpAudioStream instance is created
HttpAudioStream * HttpAudioStream()
{
iPipe = Pipe::New();
iAudioEngine = CAudioStreamEngine::NewL(); // see ConstructL instead
iWebEngine = CWebClientEngine::NewL(); // see ConstructL instead
}
void CAudioStreamEngine::ConstructL()
{
iInputStream = CMdaAudioInputStream::NewL(*this);
}
void CWebClientEngine::ConstructL()
{
iSession.OpenL();
iPostData = HC_DataSupplier::NewL(&iTransaction); // nothing special in there : sets iTrans to "&iTransaction".
iBaseEventHandler = HC_BaseEventHandler::NewL(this); // nothing special in there : sets iEventHandler to "this".
}
// Starting the recording
// class CAudioStreamAppUi : public CAknAppUi
void CAudioStreamAppUi::HandleCommandL(TInt aCommand)
{
switch ( aCommand )
{
case EAudioStreamCmdRecord:
{
_LIT8(myurl,"http://www.example.com/getpost.php");
iHttpAudioStream->Start(myurl);
break;
}
}
}
TBool HttpAudioStream::Start(const TDesC8& aUri)
{
iAudioEngine->Record(iPipe, iWebEngine);
iWebEngine->StreamPost(aUri, iPipe);
return ETrue;
}
void CAudioStreamEngine::Record(Pipe* aPipe, BasicNotify* aNotify)
{
iPipe = aPipe ;
iNotify = aNotify;
iPipe->Open();
iInputStream->Open(&iStreamSettings);
}
void CWebClientEngine::StreamPost( const TDesC8& aUri, Pipe* aPipe )
{
iPostData->PostPipe(aPipe);
IssueHTTPPostL(aUri);
}
TBool HC_DataSupplier::PostPipe(Pipe * aPipe)
{
_LIT(contentType,"text/plain");
iReqBodyContentType = contentType;
iPipe = aPipe;
return ETrue;
}
void CWebClientEngine::IssueHTTPPostL(const TDesC8& aUri/*, const TDesC8& aFilePostPath,const TDesC8& aFilePath*/)
{
TInt errCode;
// Parse string to URI (as defined in RFC2396)
TUriParser8 uri;
uri.Parse(aUri);
RStringF method = iSession.StringPool().StringF(HTTP::EPOST, RHTTPSession::GetTable());
iTransaction = iSession.OpenTransactionL(uri, *iBaseEventHandler, method);
RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection();
SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent);
SetHeaderL(hdr, HTTP::EAccept, KAccept);
SetHeaderL(hdr, HTTP::EContentType, KContentTypeForm);
MHTTPDataSupplier* dataSupplier = iPostData;
iTransaction.Request().SetBody(*dataSupplier);
iTransaction.SubmitL();
}
// Callbacks
// MMdaAudioInputStreamCallback
void CAudioStreamEngine::MaiscOpenComplete(TInt aError)
{
// assuming here (aError==KErrNone)
iInputStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime);
iInputStream->ReadL(iStreamBuffer);
}
void CAudioStreamEngine::MaiscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
{
// assuming here (aError==KErrNone)
TInt count = iPipe->Write(iStreamBuffer);
iNotify->Notify(0);
iInputStream->ReadL(iStreamBuffer);
}
// MHTTPDataSupplier, and the notification indicating it's been fed.
void HC_DataSupplier::Notify(TInt aEvent)
{
if (iAvailableData) return;
iAvailableData = ETrue;
iTrans->NotifyNewRequestBodyPartL();
}
TBool HC_DataSupplier::GetNextDataPart(TPtrC8& aDataPart)
{
count = iPipe->Read(Buffer);
if (count < aDataPart.Size() ) iAvailableData = EFalse;;
return iPipe->IsEOP(); // ETrue if pipe empty and closed by the writer, indicating last part.
}
TInt HC_DataSupplier::OverallDataSize()
{
return KErrNotFound;
}
void HC_DataSupplier::ReleaseData()
{
if ( iAvailableData )
{
iTrans->NotifyNewRequestBodyPartL();
}
}
TInt HC_DataSupplier::Reset()
{
DB("<Reset/>\r\n");
return KErrNotSupported;
}
// MHTTPTransactionCallback
// Never called with provided code. By providing a (positive) return value to OverallDataSize, MHFRunL can be called AFTER the end of the audio recording.