/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2001 Apple Computer, Inc. All Rights Reserved. The * contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please * obtain a copy of the License at http://www.apple.com/publicsource and * read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please * see the License for the specific language governing rights and * limitations under the License. * * * @APPLE_LICENSE_HEADER_END@ * */ #include "playlist_parsers.h" SDPFileParser::~SDPFileParser() { if (fSDPBuff) { delete[] fSDPBuff; fSDPBuff = NULL; } } bool SDPFileParser::IsCommented(SimpleString *theString) { bool result = false; if ( *theString->fTheString == '#' ) result = true; // It's commented if the first non-white char is # return result; } int TextLine::Parse (SimpleString *textStrPtr) { short count = 0; do { if (!textStrPtr) break; count = CountDelimeters(textStrPtr,sWordDelimeters); if (count < 1) break; fWords.SetSize(count); fSource = *textStrPtr; SimpleString *listStringPtr = fWords.Begin(); SimpleString currentString; currentString.SetString(textStrPtr->fTheString, 0); for ( short i = 0; i < count; i ++) { GetNextThing(textStrPtr,¤tString, sWordDelimeters, ¤tString); *listStringPtr = currentString; listStringPtr++; } } while (false); return count; } int LineAndWordsParser::Parse (SimpleString *textStrPtr) { short count = 0; do { if (!textStrPtr) break; count = CountDelimeters(textStrPtr,sLineDelimeters); if (count < 1) break; fLines.SetSize(count); fSource = *textStrPtr; TextLine *listStringPtr = fLines.Begin(); SimpleString currentString; currentString.SetString(textStrPtr->fTheString, 0); for ( short i = 0; i < count; i ++) { GetNextThing(textStrPtr,¤tString, sLineDelimeters, ¤tString); listStringPtr->Parse(¤tString); listStringPtr++; } } while (false); return count; } short SDPFileParser::CountQTTextLines() { short numlines = 0; TextLine *theLinePtr = fParser.fLines.Begin(); while (theLinePtr) { if (GetQTTextFromLine(theLinePtr)) numlines ++; theLinePtr = fParser.fLines.Next(); }; return numlines; } short SDPFileParser::CountMediaEntries() { bool commented = false; bool isEqual = false; short numTracks = 0; TextLine *theLinePtr = fParser.fLines.Begin(); SimpleString *firstWordPtr; SimpleString mediaString("m"); while (theLinePtr) { do { firstWordPtr = theLinePtr->fWords.Begin(); if (!firstWordPtr) break; commented = IsCommented(firstWordPtr); if (commented) break; isEqual = Compare(firstWordPtr, &mediaString); if (!isEqual) break; numTracks ++; } while (false); theLinePtr = fParser.fLines.Next(); }; return numTracks; } short SDPFileParser::CountRTPMapEntries() { short startPos = fParser.fLines.GetPos(); short result = 0; TextLine *theLinePtr = fParser.fLines.Get(); SimpleString mediaString("m"); SimpleString attributeString("a"); SimpleString mapString("rtpmap"); SimpleString *aWordPtr; bool isEqual; while (theLinePtr) { aWordPtr = theLinePtr->fWords.Begin(); if (aWordPtr) { isEqual = Compare(aWordPtr, &attributeString); if (isEqual) // see if this attribute is a rtpmap line { aWordPtr = theLinePtr->fWords.SetPos(1); isEqual = Compare(aWordPtr, &mapString); if (isEqual) result ++; } else // could be a comment or some other attribute { isEqual = Compare(aWordPtr, &mediaString); if (isEqual) break; // its another media line so stop } } theLinePtr = fParser.fLines.Next(); }; fParser.fLines.SetPos(startPos); return result; } void SDPFileParser::GetPayLoadsFromLine(TextLine *theLinePtr, TypeMap *theTypeMapPtr) { short count = 0; if (theLinePtr == NULL || theTypeMapPtr == NULL) return; SimpleString *aWordPtr = theLinePtr->fWords.SetPos(5);// get protocol ID str while (aWordPtr) { count ++; aWordPtr = theLinePtr->fWords.Next();// get next protocol ID str } theTypeMapPtr->fPayLoads.SetSize(count); short* idPtr = theTypeMapPtr->fPayLoads.Begin();// get protocol ID ref aWordPtr = theLinePtr->fWords.SetPos(5);// get protocol ID str while (aWordPtr && idPtr) { *idPtr = (short) aWordPtr->GetInt(); aWordPtr = theLinePtr->fWords.Next();// get next protocol ID str idPtr = theTypeMapPtr->fPayLoads.Next();// get next protocol ID ref } } bool SDPFileParser::GetQTTextFromLine(TextLine *theLinePtr) { //a=x-qt-text-cpy:xxxxx //a=x-qt-text-nam:xxxxxx //a=x-qt-text-inf:xxxxxxx bool result = false; SimpleString *aWordPtr; char *xString ="a=x-qt-text"; do { aWordPtr = theLinePtr->fWords.Begin(); if (!aWordPtr) break; bool isEqual = (0 == strncmp(aWordPtr->fTheString, xString,strlen(xString) ) ) ? true: false; if (!isEqual) break; result = true; } while (false); return result; } bool SDPFileParser::GetMediaFromLine(TextLine *theLinePtr, TypeMap *theTypeMapPtr) { bool result = false; SimpleString *aWordPtr; SimpleString mediaString("m"); do { aWordPtr = theLinePtr->fWords.Begin(); if (!aWordPtr) break; bool isEqual = Compare(aWordPtr, &mediaString); if (!isEqual) break; aWordPtr = theLinePtr->fWords.SetPos(1);// get type if (!aWordPtr) break; theTypeMapPtr->fTheTypeStr = *aWordPtr; aWordPtr = theLinePtr->fWords.SetPos(2);// get movie port if (!aWordPtr) break; theTypeMapPtr->fPort = aWordPtr->GetInt(); aWordPtr = theLinePtr->fWords.SetPos(3);// get protocol if (!aWordPtr) break; theTypeMapPtr->fProtocolStr = *aWordPtr; GetPayLoadsFromLine(theLinePtr, theTypeMapPtr); result = true; } while (false); return result; } bool SDPFileParser::GetRTPMap(TextLine *theLinePtr,PayLoad *payloadPtr) { bool lineOK = false; SimpleString *aWordPtr; do { if (!theLinePtr || !payloadPtr) break; aWordPtr = theLinePtr->fWords.SetPos(2); // the Payload ID if (!aWordPtr) break; payloadPtr->payloadID = aWordPtr->GetInt(); aWordPtr = theLinePtr->fWords.Next(); // the Payload type string if (!aWordPtr) break; payloadPtr->payLoadString = *aWordPtr; payloadPtr->timeScale = 0; aWordPtr = theLinePtr->fWords.Next(); // the Payload timeScale if (aWordPtr) payloadPtr->timeScale = aWordPtr->GetInt(); lineOK = true; } while (false); return lineOK; } TextLine *SDPFileParser::GetRTPMapLines(TextLine *theLinePtr,TypeMap *theTypeMapPtr) { do { if (!theLinePtr || !theTypeMapPtr) break; short numAttributes = CountRTPMapEntries(); theTypeMapPtr->fPayLoadTypes.SetSize(numAttributes); PayLoad *payloadPtr = theTypeMapPtr->fPayLoadTypes.Begin(); while( theLinePtr && payloadPtr && (numAttributes > 0) ) { bool haveMAP = GetRTPMap(theLinePtr,payloadPtr); if (haveMAP) { numAttributes --; payloadPtr = theTypeMapPtr->fPayLoadTypes.Next(); //skip to next payload entry } theLinePtr = fParser.fLines.Next(); // skip to next line if(theLinePtr == NULL || Compare(theLinePtr->fWords.Begin(), "m")) //stop checking if this is a new media line break; } } while (false); return theLinePtr; } TextLine * SDPFileParser::GetTrackID(TextLine *theLinePtr,TypeMap *theTypeMapPtr) { SimpleString *aFieldPtr; SimpleString *aWordPtr; Bool16 foundID = false; while(theLinePtr && !foundID) { if(Compare(theLinePtr->fWords.Begin(), "m")) //stop checking if this is a new media line break; do { SimpleString attributeString("a"); SimpleString controlString("control"); aFieldPtr = theLinePtr->fWords.Begin(); if (!aFieldPtr) break; bool isEqual = Compare(aFieldPtr, &attributeString); if (!isEqual) break; aWordPtr = theLinePtr->fWords.SetPos(1); if (!aWordPtr) break; isEqual = Compare(aWordPtr, &controlString); if (!isEqual) break; aWordPtr = theLinePtr->fWords.SetPos(3); if (!aWordPtr) break; theTypeMapPtr->fTrackID = aWordPtr->GetInt(); foundID = true; } while (false); theLinePtr = fParser.fLines.Next(); } return theLinePtr; } bool SDPFileParser::ParseIPString(TextLine *theLinePtr) { bool result = false; SimpleString *aWordPtr; do { if (theLinePtr->fWords.Size() != 4) break; SimpleString attributeString("c"); SimpleString ipIDString("IP4"); aWordPtr = theLinePtr->fWords.Begin(); if (!aWordPtr) break; bool isEqual = Compare(aWordPtr, &attributeString); if (!isEqual) break; aWordPtr = theLinePtr->fWords.SetPos(2); if (!aWordPtr) break; isEqual = Compare(aWordPtr, &ipIDString); if (!isEqual) break; aWordPtr = theLinePtr->fWords.SetPos(3); if (!aWordPtr) break; fIPAddressString.SetString(aWordPtr->fTheString, aWordPtr->fLen); result = true; } while (false); return result; } SInt32 SDPFileParser::ParseSDP(char *theBuff) { SInt32 result = 0; bool found = false; SimpleString source(theBuff); fSource.SetString( theBuff, strlen(theBuff) ); fParser.Parse(&source); // Test parse #if 0 printf("-----------------------------------------------------\n"); char tempString[256]; TextLine *theLine = fParser.fLines.Begin(); while (theLine) { SimpleString *theWord = theLine->fWords.Begin(); while (theWord) { theWord->GetString(tempString,256); printf(tempString); theWord = theLine->fWords.Next(); if (theWord) printf(" _ "); } theLine = fParser.fLines.Next(); printf("\n"); } // exit (0); #endif fNumQTTextLines = CountQTTextLines(); fQTTextLines.SetSize(fNumQTTextLines); SimpleString *theQTTextPtr = fQTTextLines.Begin(); fNumTracks = CountMediaEntries(); fSDPMediaList.SetSize(fNumTracks); TextLine *theLinePtr = fParser.fLines.Begin(); TypeMap *theTypeMapPtr = fSDPMediaList.Begin(); bool foundIP = false; while (theLinePtr && theTypeMapPtr) { if (foundIP == false) { foundIP = ParseIPString(theLinePtr); } if (theQTTextPtr && GetQTTextFromLine(theLinePtr)) { SimpleString *srcLinePtr = theLinePtr->fWords.Begin(); theQTTextPtr->SetString(srcLinePtr->fTheString, strcspn(srcLinePtr->fTheString, "\r\n") ); theQTTextPtr = fQTTextLines.Next(); } found = GetMediaFromLine(theLinePtr, theTypeMapPtr); if (found) { theLinePtr = fParser.fLines.Next(); if (!theLinePtr) break; int startLine = fParser.fLines.GetPos(); theLinePtr = fParser.fLines.SetPos(startLine); (void) GetRTPMapLines(theLinePtr,theTypeMapPtr); theLinePtr = fParser.fLines.SetPos(startLine); (void) GetTrackID(theLinePtr,theTypeMapPtr); theTypeMapPtr = fSDPMediaList.Next(); theLinePtr = fParser.fLines.SetPos(startLine); continue; } theLinePtr = fParser.fLines.Next(); }; return result; } SInt32 SDPFileParser::ReadSDP(char *filename) { int result = -1; long int bytes= 0; FILE *f = NULL; if (fSDPBuff != NULL) { delete[] fSDPBuff; fSDPBuff = NULL; } do { f = ::fopen(filename, "r"); if (f == NULL) break; result = 1; result = ::fseek(f, 0, SEEK_SET); if (result != 0) break; fSDPBuff = new char[cMaxBytes + 1]; if (NULL == fSDPBuff) break; fSDPBuff[cMaxBytes] = 0; bytes = ::fread(fSDPBuff, sizeof(char), cMaxBytes, f); if (bytes < 1) break; fSDPBuff[bytes] = 0; result = ParseSDP(fSDPBuff); if (result != 0) break; result = 0; } while (false); if (f != NULL) { ::fclose (f); f = NULL; } return result; }