VorbisComments.cpp

Go to the documentation of this file.
00001 //===========================================================================
00002 //Copyright (C) 2004 Zentaro Kavanagh
00003 //
00004 //Redistribution and use in source and binary forms, with or without
00005 //modification, are permitted provided that the following conditions
00006 //are met:
00007 //
00008 //- Redistributions of source code must retain the above copyright
00009 //  notice, this list of conditions and the following disclaimer.
00010 //
00011 //- Redistributions in binary form must reproduce the above copyright
00012 //  notice, this list of conditions and the following disclaimer in the
00013 //  documentation and/or other materials provided with the distribution.
00014 //
00015 //- Neither the name of Zentaro Kavanagh nor the names of contributors 
00016 //  may be used to endorse or promote products derived from this software 
00017 //  without specific prior written permission.
00018 //
00019 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00022 //PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
00023 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00024 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00025 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 //===========================================================================
00031 
00032 #include "stdafx.h"
00033 #include "VorbisComments.h"
00034 
00035 VorbisComments::VorbisComments(void)
00036 {
00037 }
00038 
00039 VorbisComments::~VorbisComments(void)
00040 {
00041 }
00042 
00043 string VorbisComments::vendorString() {
00044         return mVendorString;
00045 }
00046 bool VorbisComments::setVendorString(string inVendorString) {
00047         //FIX::: Validation needed
00048         mVendorString = inVendorString;
00049         return true;
00050 }
00051 
00052 unsigned long VorbisComments::numUserComments() {
00053         return (unsigned long)mCommentList.size();
00054 }
00055 SingleVorbisComment* VorbisComments::getUserComment(unsigned long inIndex) {
00056         //FIX::: Bounds checking
00057         return mCommentList[inIndex];
00058 }
00059         
00060 vector<SingleVorbisComment*> VorbisComments::getCommentsByKey(string inKey) {
00061         //FIX::: Probably faster not to iterate... but who cares for now.. there aren't many.
00062         vector<SingleVorbisComment*> retComments;
00063         SingleVorbisComment* locCurrComment = NULL;
00064 
00065         for (size_t i = 0; i < mCommentList.size(); i++) {
00066                 locCurrComment = mCommentList[i];
00067                 //FIX::: Need to upcase everything
00068                 if (locCurrComment->key() == inKey) {
00069                         retComments.push_back(locCurrComment);
00070                 }
00071         }
00072         return retComments;
00073 }
00074 
00075 bool VorbisComments::addComment(SingleVorbisComment* inComment) {
00076         mCommentList.push_back(inComment);
00077         return true;
00078 }
00079 bool VorbisComments::addComment(string inKey, string inValue) {
00080         SingleVorbisComment* locComment = new SingleVorbisComment;
00081         locComment->setKey(inKey);
00082         locComment->setValue(inValue);
00083         mCommentList.push_back(locComment);
00084         return true;
00085 }
00086 
00087 bool VorbisComments::parseOggPacket(OggPacket* inPacket, unsigned long inStartOffset) {
00088         //FIX::: Validate it is a comment packet
00089         unsigned long locPackSize = inPacket->packetSize();
00090 
00091         //Account for header ident stuff
00092         unsigned long locUpto = inStartOffset;
00093         unsigned long locVendorLength = 0;
00094         string locVendorString;
00095         char* tempBuff = NULL;
00096         unsigned char* locPackBuff = inPacket->packetData();
00097         unsigned long locNumComments = 0;
00098         vector<SingleVorbisComment*> locCommentList;
00099 
00100         if (locPackSize < locUpto + 4 - 1) {
00101                 //FAILED - No vendor length
00102                 return false;
00103         }
00104 
00105         locVendorLength = iLE_Math::charArrToULong(inPacket->packetData() + locUpto);
00106         locUpto+=4;
00107 
00108         if (locPackSize < locUpto + locVendorLength - 1) {
00109                 //FAILED - Vendor string not present
00110                 return false;
00111         }
00112 
00113         tempBuff = new char[locVendorLength + 1];
00114 
00115         if (tempBuff == NULL) {
00116                 //FAILED - Vendor length too big, out of memory
00117                 return false;
00118         }
00119 
00120         memcpy((void*)tempBuff, (const void*)(locPackBuff + locUpto), locVendorLength);
00121         tempBuff[locVendorLength] = '\0';
00122 
00123         locVendorString = tempBuff;
00124         delete[] tempBuff;
00125         tempBuff = NULL;
00126 
00127         locUpto += locVendorLength;
00128 
00129         if (locPackSize < locUpto + 4 - 1) {
00130                 //FAILED - User comment list length not present
00131                 return false;
00132         }
00133 
00134         locNumComments = iLE_Math::charArrToULong(locPackBuff + locUpto);
00135         locUpto += 4;
00136 
00137         unsigned long locUserCommentLength = 0;
00138         bool locFailed = false;
00139         string locUserComment;
00140         unsigned long i = 0;
00141         while (!locFailed && (i < locNumComments)) {
00142                 if (locPackSize < locUpto + 4 -1) {
00143                         //FAILED - User comment string length not present
00144                         return false;
00145                 }
00146 
00147                 locUserCommentLength = iLE_Math::charArrToULong(locPackBuff + locUpto);
00148                 locUpto += 4;
00149 
00150 
00151                 if (locPackSize < locUpto + locUserCommentLength - 1) {
00152                         //FAILED - User comment string not present
00153                         return false;
00154                 }
00155 
00156                 tempBuff = new char[locUserCommentLength+1];
00157 
00158                 memcpy((void*)tempBuff, (const void*)(locPackBuff + locUpto), locUserCommentLength);
00159                 tempBuff[locUserCommentLength] = '\0';
00160 
00161         locUserComment = tempBuff;
00162                 delete[] tempBuff;
00163                 locUpto += locUserCommentLength;
00164 
00165 
00166                 SingleVorbisComment* locComment = new SingleVorbisComment;
00167                 if (locComment->parseComment(locUserComment)) {
00168                         locCommentList.push_back(locComment);
00169                 } else {
00170                         //FAILED - Comment not parsable
00171                         return false;
00172                 }
00173 
00174                 i++;
00175 
00176         }
00177 
00178         //Check the bit.
00179         if (locPackSize < locUpto) {
00180                 //FAILED - No check bit
00181                 return false;
00182         }
00183 
00184         //Everythings ok... put it into the class fields
00185         if ((locPackBuff[locUpto] & 1) == 1) {
00186                 //OK
00187                 mVendorString = locVendorString;
00188                 
00189                 mCommentList.empty();
00190                 mCommentList.clear();
00191                 for (size_t j = 0; j < locCommentList.size(); j++) {
00192                         mCommentList.push_back(locCommentList[j]);      
00193                 }
00194         } else {
00195                 //FAILED - Check bit not set
00196                 return false;
00197         }
00198 
00199         return true;
00200 
00201 
00202 
00203         
00204 
00205         
00206 }
00207 
00208 string VorbisComments::toString() {
00209         string retStr;
00210 
00211         retStr = "VENDOR : " + mVendorString + "\n";
00212         for (size_t i = 0; i < mCommentList.size(); i++) {
00213                 retStr += "-- " + mCommentList[i]->toString() + "\n";
00214         }
00215         retStr += "\n";
00216         return retStr;
00217 
00218 }
00219 unsigned long VorbisComments::size() {
00220         unsigned long locPackSize = 0;
00221 
00222         locPackSize = (unsigned long)mVendorString.size() + 4;
00223 
00224         for (size_t i = 0; i < mCommentList.size(); i++) {
00225                 locPackSize += mCommentList[i]->length() + 4;
00226         }
00227 
00228         //Check bit
00229         locPackSize++;
00230         
00231         return locPackSize;
00232 }
00233 OggPacket* VorbisComments::toOggPacket(unsigned char* inPrefixBuff, unsigned long inPrefixBuffSize) {
00234 
00235         unsigned long locPackSize = size();
00236         unsigned long locUpto = 0;
00237         unsigned char* locPackData = NULL;
00238 
00239         if (inPrefixBuff != NULL && inPrefixBuffSize != 0) {
00240                 locPackSize += inPrefixBuffSize;
00241                 locPackData = new unsigned char[locPackSize];
00242                 memcpy((void*)locPackData, (const void*)inPrefixBuff, inPrefixBuffSize);
00243                 locUpto += inPrefixBuffSize;
00244         } else {
00245                 locPackData = new unsigned char[locPackSize];
00246         }
00247         
00248         iLE_Math::ULongToCharArr((unsigned long)mVendorString.length(), locPackData + locUpto);
00249         locUpto += 4;
00250 
00251         memcpy((void*)(locPackData + locUpto), (const void*)mVendorString.c_str(), mVendorString.length());
00252         locUpto += (unsigned long)mVendorString.length();
00253 
00254         iLE_Math::ULongToCharArr((unsigned long)mCommentList.size(), locPackData + locUpto);
00255         locUpto += 4;
00256 
00257         for (size_t i = 0; i < mCommentList.size(); i++) {
00258                 iLE_Math::ULongToCharArr(mCommentList[i]->length(), locPackData + locUpto);
00259                 locUpto += 4;
00260 
00261                 memcpy((void*)(locPackData + locUpto), (const void*)mCommentList[i]->toString().c_str(), mCommentList[i]->length());
00262                 locUpto += mCommentList[i]->length();
00263         }
00264 
00265         locPackData[locUpto] = 1;
00266 
00267         OggPacket* locPacket = NULL;
00268                                                                                                         //Full packet not truncated or continued.
00269         locPacket = new OggPacket(locPackData, locPackSize, false, false);
00270 
00271         return locPacket;
00272 
00273 }

Generated on Tue Feb 15 14:54:21 2005 for oggdsf by  doxygen 1.3.9