📄 shoutcastadapter.cpp
字号:
{
// We have a metadata event
TInt i,f,e;
CMetaDataEntry *mdEntry = NULL;
f = aError&0xFF; // bitmap of metadata indicators
// Check which metadata got updated
for( i=0; i < iNrMetadata; i++)
{
e = f&0x01;
f = f>>1;
if( e )
{
// Updated metadata found
LOG1("HandleEvent - Update Metadata %d", i);
TRAPD(err, mdEntry = iStreamSource->GetMetaDataEntryL(i));
if ( !err )
{
if( iObserver )
{
iObserver->SetMetadata(i, mdEntry->Value(), f==0);
}
delete mdEntry;
mdEntry = NULL;
}
}
}
}
if ( aEvent == TUid::Uid(KShoutcastStreamUid) &&
( aError == KShoutcastEvent_Connecting || aError==KShoutcastEvent_Reconnecting) )
{
//create the text for the waiting note
TBuf<256> text;
CMetaDataEntry *mdEntry=NULL;
if( aError == KShoutcastEvent_Connecting )
{
text.Copy(KMsgShoutcast_Connecting);
}
else
{
text.Copy(KMsgShoutcast_Reconnecting);
}
TRAP(r, mdEntry = iStreamSource->GetMetaDataEntryL(KShoutcastMetaData_URL));
if( r == KErrNone )
{
text.Append(mdEntry->Value());
delete mdEntry;
}
// pop-up waiting dialog
if ( !iWaitDialog )
{
iWaitDialog = new(ELeave)CAknWaitDialog( (REINTERPRET_CAST(CEikDialog**,&iWaitDialog)));
}
// we want to be notified when this dialog is dismissed.
iWaitDialog->SetCallback(this);
iWaitDialog->SetTextL(text);
// show the dialog
iWaitDialog->ExecuteLD(R_WAIT_NOTE);
}
if ( aEvent == TUid::Uid(KShoutcastStreamUid) && aError == KShoutcastEvent_Connected )
{
LOG("HandleEvent - Connected");
// Dismiss the waiting dialog
if ( iWaitDialog )
{
TRAPD(r,iWaitDialog->ProcessFinishedL());
delete iWaitDialog;
iWaitDialog = NULL;
}
iPrimed = ETrue;
//issue PLay command
TRAPD(err, iStreamSource->PlayL());
if ( err )
{
HandleError(r, EOpPlay);
iStreamSource->Stop();
return;
}
iState = EPlaying;
}
if ( aEvent == TUid::Uid(KShoutcastStreamUid) && aError == KShoutcastEvent_Disconnected)
{
//we got disconnected somehow!
iState = EReadyToPlay;
iPrimed = EFalse;
DeleteLabels(ETrue);
//try to reconnect
PlayL(); // PlayL doesn't leave
}
if( aEvent == TUid::Uid(KShoutcastStreamUid) && aError==KShoutcastEvent_BufferEmpty )
{
//Buffer is empty! write buffering
TBufC<10> buf=_L("Buffering");
DeleteLabels(EFalse,&buf);
}
if ( aEvent == TUid::Uid(KShoutcastStreamUid) && aError == KShoutcastEvent_BufferingComplete )
{
//Buffer is full again. Write song title
CMetaDataEntry *mdEntry = NULL;
TRAPD(err, mdEntry=iStreamSource->GetMetaDataEntryL(3));
if ( !err )
{
if ( iObserver )
{
iObserver->SetMetadata(3,mdEntry->Value(),ETrue);
delete mdEntry;
mdEntry = NULL;
}
}
}
if ( aEvent == TUid::Uid(KShoutcastStreamUid) && aError < 0)
{
//this is an error connecting
HandleError(aError,EOpPrime);
//there are no labels to delete
}
}
// -----------------------------------------------------------------------------
// CShoutcastAdapter::DialogDismissedL
// Called when the waiting for connection dialog is dismissed.
// -----------------------------------------------------------------------------
//
void CShoutcastAdapter::DialogDismissedL(
TInt aButtonId)
{
if ( aButtonId == EAknSoftkeyCancel ) // if user pressed cancel
{
StopL();
CloseUrl();
}
}
// -----------------------------------------------------------------------------
// CShoutcastAdapter::HandleError
// Handle errors from shoutcast stream
// -----------------------------------------------------------------------------
//
void CShoutcastAdapter::HandleError(
TInt aError,
TOp aOperation )
{
TBuf<256> text;
TBuf<15> textErr;
TInt globalErr = aError%100;
TInt shoutcastErr = aError-globalErr;
LOG2("HandleError: ShoutcastErr=%d GlobalErr=%d",shoutcastErr,globalErr);
// dismiss the waiting dialog
if ( iWaitDialog )
{
TRAPD(r,iWaitDialog->ProcessFinishedL());
delete iWaitDialog;
iWaitDialog = NULL;
}
//first, we need to build the error text
switch ( aOperation )
{
case EOpOpen:
text.Copy(KErrMsgShoutcast_Controller);
ASSERT(shoutcastErr == 0);
break;
case EOpAddDataSink:
text.Copy(KErrMsgShoutcast_AddDataSink);
ASSERT(shoutcastErr == 0);
break;
case EOpAddDataSource:
ASSERT(shoutcastErr == 0);
switch( globalErr )
{
case KErrNotFound:
text.Copy(KErrMsgShoutcast_AddDataSource_PlaylistNotFound);
break;
case KErrPathNotFound:
text.Copy(KErrMsgShoutcast_AddDataSource_URLNotFound);
break;
default:
ASSERT(0);
}
break;
case EOpPrime:
text.Copy(KErrMsgShoutcast_Prime);
break;
case EOpPlay:
text.Copy(KErrMsgShoutcast_Play);
break;
default:
ASSERT(0);
}
switch ( shoutcastErr )
{
case KErrShoutcast_ReadFromFile:
text.Append(KErrMsgShoutcast_ReadFromFile);
break;
case KErrShoutcast_ConnectToSockServer:
text.Append(KErrMsgShoutcast_ConnectToSockServer);
break;
case KErrShoutcast_OpenSocket:
text.Append(KErrMsgShoutcast_OpenSocket);
break;
case KErrShoutcast_Connecting2Server:
text.Append(KErrMsgShoutcast_Connecting2Server);
break;
case KErrShoutcast_SendingHTTPRequest:
text.Append(KErrMsgShoutcast_SendingHTTPRequest);
break;
case KErrShoutcast_ReceivingHTTPResponse:
text.Append(KErrMsgShoutcast_ReceivingHTTPResponse);
break;
case KErrShoutcast_NoHTTPServer:
text.Append(KErrMsgShoutcast_NoHTTPServer);
break;
case KErrShoutcast_BadIcyMetadataFormat:
text.Append(KErrMsgShoutcast_BadIcyMetadataFormat);
break;
case KErrShoutcast_NoShoutcastServer:
text.Append(KErrMsgShoutcast_NoShoutcastServer);
break;
case KErrShoutcast_FormatNotSupported:
text.Append(KErrMsgShoutcast_FormatNotSupported);
break;
case KErrNone:
break;
default:
ASSERT(0);
}
if ( globalErr != KErrNone )
{
textErr.Format(_L(" Err=%d"),globalErr);
text.Append(textErr);
}
TRAPD(r,
{
//build note
if ( !iErrorNote )
iErrorNote = CAknGlobalNote::NewL();
LOG1("HandleError note: %s",text.PtrZ());
iErrorNote->ShowNoteL(EAknGlobalErrorNote ,text);
});
}
// -----------------------------------------------------------------------------
// CShoutcastAdapter::SetVolume
// Sets the volume level
// -----------------------------------------------------------------------------
//
void CShoutcastAdapter::SetVolume(
TInt aVolume )
{
LOG1("CShoutcastAdapter::SetVolume %d", aVolume);
if ( iStreamSource )
iStreamSource->SetVolume((TInt)(aVolume/iVolFactor));
LOG("CShoutcastAdapter::SetVolume OK");
}
// -----------------------------------------------------------------------------
// CShoutcastAdapter::Volume
// Get the current volume level
// -----------------------------------------------------------------------------
//
TInt CShoutcastAdapter::Volume()
{
LOG("CShoutcastAdapter::GetVolume");
TInt volume = KDefaultVolumeLevel;
if ( iStreamSource )
{
if( !iVolFactor )
{
TInt maxVol = iStreamSource->MaxVolume();
if ( maxVol != 0)
iVolFactor=10.0/maxVol;
}
volume = iStreamSource->Volume();
volume = (TInt)(iVolFactor*volume);
};
LOG1("CShoutcastAdapter::GetVolume: %d", volume);
return volume;
}
// -----------------------------------------------------------------------------
// CShoutcastAdapter::DeleteLabels
// All the labels are cleared if the playing has stopped.
// Only server, genre, technical data are cleared if the playing is paused.
// The price and bytes labels always remains.
// -----------------------------------------------------------------------------
//
void CShoutcastAdapter::DeleteLabels(
TBool aAll,
TDesC *buf )
{
LOG("DeleteLabels");
if ( !iObserver )
{
return;
}
TBufC<10> bufe=_L("");
if ( !buf )
{
buf = &bufe;
}
iObserver->SetMetadata(3,*buf,!aAll);
if (aAll)
{
iObserver->SetMetadata(0,bufe,EFalse);
iObserver->SetMetadata(1,bufe,EFalse);
iObserver->SetMetadata(2,bufe,ETrue);
}
LOG("DeleteLabels OK");
}
// -----------------------------------------------------------------------------
// CShoutcastAdapter::ParsePlaylistFileL
// -----------------------------------------------------------------------------
//
void CShoutcastAdapter::ParsePlaylistFileL(
RFs aFs,
const TFileName &aFilename )
{
RFile file;
TBool done = EFalse;
TInt gotMatch;
TUint8 *fileBuf;
TPtr8 lineBuf(NULL,0,0);
HBufC8 *urlBuf;
TInt posBegin,lineSize,fileSize,len2cut=0,extraByteNL;
LOG("Adapter::ParsePlaylistFileL - begin");
User::LeaveIfError(file.Open(aFs, aFilename, EFileShareReadersOnly|EFileRead|EFileStreamText));
CleanupClosePushL(file);
User::LeaveIfError(file.Size(fileSize));
//get the file in memory if smaller that 64k
if ( fileSize > KMaxFileSize )
{
User::Leave(KErrTooBig);
}
fileBuf = new (ELeave) TUint8[fileSize];
lineBuf.Set(fileBuf,fileSize,fileSize);
file.Read(lineBuf);
fileSize = lineBuf.Length();//should be the same as before ...
posBegin = 0;
while ( !done )
{
//construct lineBuf
lineBuf.Set(fileBuf+posBegin,fileSize-posBegin,fileSize-posBegin);
lineSize = lineBuf.Locate(KLineFeed); // try to locate a line feed char
if ( lineSize == KErrNotFound )
{
done = ETrue;//we are at the end
continue;
}
if ( lineSize > 0 && lineBuf[lineSize-1] == KCarriageReturn )
{
extraByteNL=1; //include also the \r
}
else
{
extraByteNL=0;
}
lineBuf.Set(fileBuf+posBegin,lineSize-extraByteNL,lineSize-extraByteNL);
posBegin += (lineSize+1);
//here we have a complete line in lineBuf, but without the \n at the end
//parse
if ( lineBuf.Match(_L8("File?=http://*")) == 0 )
{
gotMatch=1;
len2cut = 6;
}
else if ( lineBuf.Match(_L8("File?*=http://*")) == 0 )
{
gotMatch=1;
len2cut = 7;
}
else if( lineBuf.Match(_L8("Title?=*")) == 0 )
{
gotMatch=2;
len2cut = 7;
}
else if ( lineBuf.Match(_L8("Title?*=*")) == 0 )
{
gotMatch=2;
len2cut = 8;
}
else
{
gotMatch=0;
}
if ( gotMatch )
{
urlBuf = HBufC8::NewL(lineBuf.Length()-len2cut);
*urlBuf = lineBuf.Right(lineBuf.Length()-len2cut);
//provision for an empty title
if( iURLs.Count()%2 && gotMatch == 1 )
{
//insert a dummy title if the previous URL did not have one
HBufC8 *dummy = HBufC8::NewL(12);
*dummy = _L8("- Unknown -");
iURLs.Append(dummy);
};
if ( gotMatch != 2 || iURLs.Count()%2 )
{
iURLs.Append(urlBuf);//if this is a title and an even place, we skip it, because it would be a title without URL
}
};
//LOG2("gotMatch %d, URL Count %d", gotMatch, iURLs.Count());
}
delete fileBuf;
//close stuff now
CleanupStack::Pop();
file.Close();
LOG("Adapter::ParsePlaylistFileL - end");
}
// -----------------------------------------------------------------------------
// Exported proxy for instantiation method resolution
// Define the interface UIDs
// -----------------------------------------------------------------------------
const TImplementationProxy ImplementationTable[] =
{
IMPLEMENTATION_PROXY_ENTRY(KShoutcastImplementationUid, CShoutcastAdapter::NewL),
};
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
{
aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
/*
RFileLogger log;
log.Connect();
log.CreateLog(_L("Shoutcast"),_L("ShoutcastDLL.txt"),EFileLoggingModeOverwrite);
log.WriteFormat(_L("Somebody is asking for me! %d"),aTableCount);
log.CloseLog();
log.Close();
*/
return ImplementationTable;
}
#ifndef EKA2
GLDEF_C TInt E32Dll(TDllReason)
{
return KErrNone;
}
#endif //EKA2
// End of File
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -