metadata.cpp

Go to the documentation of this file.
00001 /**
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /** \file metadata.cpp Implementation of various metadata-related classes. */
00020 
00021 #include <hn/hnprec.h>
00022 #include <hn/metadata.h>
00023 #include <hn/log.h>
00024 #include <hn/hash.h>
00025 using namespace CGComm;
00026 
00027 // StreamData
00028 // ----------
00029 StreamData::StreamData() : m_bitrate(0) {}
00030 StreamData::StreamData(const std::string &codec, uint32_t bitrate, uint32_t len)
00031 : m_bitrate(bitrate), m_codec(codec), m_length(len) {}
00032 StreamData::StreamData(std::istream &i) : m_bitrate(0), m_length(0) {
00033         m_bitrate = Utils::getVal<uint32_t>(i);
00034         m_codec   = Utils::getVal<std::string>(i);
00035         m_length  = Utils::getVal<uint32_t>(i);
00036 }
00037 StreamData::~StreamData() {}
00038 
00039 std::ostream& operator<<(std::ostream &o, const StreamData &s) {
00040         std::ostringstream tmp;
00041         Utils::putVal<uint32_t>(tmp, s.m_bitrate);
00042         Utils::putVal<std::string>(tmp, s.m_codec);
00043         Utils::putVal<uint32_t>(tmp, s.m_length);
00044         Utils::putVal<uint16_t>(o, tmp.str().size());
00045         o.write(tmp.str().c_str(), tmp.str().size());
00046         return o;
00047 }
00048 
00049 // VideoMetaData
00050 // -------------
00051 // Default constructor
00052 VideoMetaData::VideoMetaData()
00053 : m_runtime(), m_frames(0), m_framerate(0), m_framesize(0, 0), m_subtitles(0) {}
00054 //! Destructor
00055 VideoMetaData::~VideoMetaData() {}
00056 
00057 // Construct and load
00058 VideoMetaData::VideoMetaData(std::istream &i)
00059 : m_runtime(), m_frames(0), m_framerate(0), m_framesize(0, 0), m_subtitles(0) {
00060         logTrace(TRACE_MD, "Reading VideoMetaData from stream.");
00061         uint16_t tagcount = Utils::getVal<uint16_t>(i);
00062         logTrace(TRACE_MD, boost::format("Reading %d tags.") % tagcount);
00063         while (tagcount--) {
00064                 uint8_t opcode = Utils::getVal<uint8_t>(i);
00065                 uint16_t len = Utils::getVal<uint16_t>(i);
00066                 switch (opcode) {
00067                         case OP_VMD_RUNTIME:
00068                                 m_runtime = Utils::getVal<uint32_t>(i);
00069                                 logTrace(
00070                                         TRACE_MD,
00071                                         boost::format("Got runtime: %d")
00072                                         % m_runtime
00073                                 );
00074                                 break;
00075                         case OP_VMD_FRAMES:
00076                                 m_frames = Utils::getVal<uint32_t>(i);
00077                                 logTrace(
00078                                         TRACE_MD,
00079                                         boost::format("Got framecount: %d")
00080                                         % m_frames
00081                                 );
00082                                 break;
00083                         case OP_VMD_FRAMERATE:
00084                                 m_framerate = Utils::getVal<float>(i);
00085                                 logTrace(
00086                                         TRACE_MD,
00087                                         boost::format("Got framerate: %f")
00088                                         % m_framerate
00089                                 );
00090                                 break;
00091                         case OP_VMD_FRAMESIZE:
00092                                 m_framesize.first = Utils::getVal<uint32_t>(i);
00093                                 m_framesize.second = Utils::getVal<uint32_t>(i);
00094                                 logTrace(
00095                                         TRACE_MD,
00096                                         boost::format("Got framesize: %dx%d")
00097                                         % m_framesize.first % m_framesize.second
00098                                 );
00099                                 break;
00100                         case OP_VMD_SUBTITLES:
00101                                 m_subtitles = Utils::getVal<uint32_t>(i);
00102                                 logTrace(
00103                                         TRACE_MD,
00104                                         boost::format("Got subtitle count: %d")
00105                                         % m_subtitles
00106                                 );
00107                                 break;
00108                         case OP_VMD_VIDSTREAM:
00109                                 m_vidData.push_back(StreamData(i));
00110                                 logTrace(
00111                                         TRACE_MD,
00112                                         boost::format("Got video stream: %s/%d")
00113                                         % m_vidData.back().getCodec()
00114                                         % m_vidData.back().getBitrate()
00115                                 );
00116                                 break;
00117                         case OP_VMD_AUDSTREAM:
00118                                 m_audData.push_back(StreamData(i));
00119                                 logTrace(
00120                                         TRACE_MD,
00121                                         boost::format("Got audio stream: %s/%d")
00122                                         % m_audData.back().getCodec()
00123                                         % m_audData.back().getBitrate()
00124                                 );
00125                                 break;
00126                         default:
00127                                 logWarning(
00128                                         boost::format(
00129                                                 "Unhandled tag %s found at "
00130                                                 "offset %s while parsing "
00131                                                 "VideoMetaData stream."
00132                                         ) % Utils::hexDump(opcode)
00133                                         % Utils::hexDump(-3+i.tellg())
00134                                 );
00135                                 i.seekg(len, std::ios::cur);
00136                                 break;
00137                 }
00138                 if (!i) {
00139                         logError(
00140                                 "Unexpected end of stream while parsing "
00141                                 "VideoMetaData stream."
00142                         );
00143                         break;
00144                 }
00145 
00146         }
00147 }
00148 
00149 // Write to stream
00150 std::ostream& operator<<(std::ostream &o, const VideoMetaData &vmd) {
00151         logTrace(TRACE_MD, "Writing VideoMetaData to stream.");
00152         Utils::putVal<uint8_t>(o, OP_VMD);
00153         std::ostringstream str;
00154         uint16_t tagcount = 0;
00155         if (vmd.m_runtime) {
00156                 Utils::putVal<uint8_t>(str, OP_VMD_RUNTIME);
00157                 Utils::putVal<uint16_t>(str, 4);
00158                 Utils::putVal<uint32_t>(str, vmd.m_runtime);
00159                 ++tagcount;
00160         }
00161         if (vmd.m_frames) {
00162                 Utils::putVal<uint8_t>(str, OP_VMD_FRAMES);
00163                 Utils::putVal<uint16_t>(str, 4);
00164                 Utils::putVal<uint32_t>(str, vmd.m_frames);
00165                 ++tagcount;
00166         }
00167         if (vmd.m_framerate) {
00168                 Utils::putVal<uint8_t>(str, OP_VMD_FRAMERATE);
00169                 Utils::putVal<uint16_t>(str, 4);
00170                 Utils::putVal<float>(str, vmd.m_framerate);
00171                 ++tagcount;
00172         }
00173         if (vmd.m_framesize.first && vmd.m_framesize.second) {
00174                 Utils::putVal<uint8_t>(str, OP_VMD_FRAMESIZE);
00175                 Utils::putVal<uint16_t>(str, 8);
00176                 Utils::putVal<uint32_t>(str, vmd.m_framesize.first);
00177                 Utils::putVal<uint32_t>(str, vmd.m_framesize.second);
00178                 ++tagcount;
00179         }
00180         if (vmd.m_subtitles) {
00181                 Utils::putVal<uint8_t>(str, OP_VMD_SUBTITLES);
00182                 Utils::putVal<uint16_t>(str, 4);
00183                 Utils::putVal<uint32_t>(str, vmd.m_subtitles);
00184                 ++tagcount;
00185         }
00186         if (vmd.m_vidData.size() > 0) {
00187                 for (
00188                         VideoMetaData::CSIter i = vmd.m_vidData.begin();
00189                         i != vmd.m_vidData.end(); i++
00190                 ) {
00191                         Utils::putVal<uint8_t>(str, OP_VMD_VIDSTREAM);
00192                         str << *i;
00193                         ++tagcount;
00194                 }
00195         }
00196         if (vmd.m_audData.size() > 0) {
00197                 for (
00198                         VideoMetaData::CSIter i = vmd.m_audData.begin();
00199                         i != vmd.m_audData.end(); i++
00200                 ) {
00201                         Utils::putVal<uint8_t>(str, OP_VMD_AUDSTREAM);
00202                         str << *i;
00203                         ++tagcount;
00204                 }
00205         }
00206         Utils::putVal<uint16_t>(o, str.str().size() + 2);
00207         Utils::putVal<uint16_t>(o, tagcount);
00208         Utils::putVal(o, str.str(), str.str().size());
00209         logTrace(
00210                 TRACE_MD,
00211                 boost::format("VideoMetaData: %d tags written.") % tagcount
00212         );
00213         return o;
00214 }
00215 
00216 // AudioMetaData
00217 // -------------
00218 // Default constructor
00219 AudioMetaData::AudioMetaData()
00220         : m_title(0), m_artist(0), m_album(0), m_genre(0),
00221         m_comment(0), m_composer(0), m_origartist(0), m_copyright(0), m_url(0),
00222         m_encoded(0), m_year(0) {
00223 }
00224 // Destructor
00225 AudioMetaData::~AudioMetaData() {
00226         if (m_title)      { free(m_title);      }
00227         if (m_artist)     { free(m_artist);     }
00228         if (m_album)      { free(m_album);      }
00229         if (m_genre)      { free(m_genre);      }
00230         if (m_comment)    { free(m_comment);    }
00231         if (m_composer)   { free(m_composer);   }
00232         if (m_origartist) { free(m_origartist); }
00233         if (m_copyright)  { free(m_copyright);  }
00234         if (m_url)        { free(m_url);        }
00235         if (m_encoded)    { free(m_encoded);    }
00236 }
00237 
00238 // Construct and load
00239 AudioMetaData::AudioMetaData(std::istream &i)
00240 : m_title(0), m_artist(0), m_album(0), m_genre(0), m_comment(0), m_composer(0),
00241 m_origartist(0), m_copyright(0), m_url(0), m_encoded(0), m_year(0) {
00242         using boost::format;
00243         logTrace(TRACE_MD, "Reading AudioMetaData from stream.");
00244         uint16_t tagcount = Utils::getVal<uint16_t>(i);
00245         logTrace(TRACE_MD, boost::format("%d tags to read.") % tagcount);
00246         while (tagcount--) {
00247                 uint8_t opcode = Utils::getVal<uint8_t>(i);
00248                 uint16_t len = Utils::getVal<uint16_t>(i);
00249                 switch (opcode) {
00250                         case OP_AMD_TITLE:
00251                                 setTitle(Utils::getVal<std::string>(
00252                                         i, len
00253                                 ).c_str());
00254                                 logTrace(
00255                                         TRACE_MD,
00256                                         format("Got title: %s") % getTitle()
00257                                 );
00258                                 break;
00259                         case OP_AMD_ARTIST:
00260                                 setArtist(Utils::getVal<std::string>(
00261                                         i, len
00262                                 ).c_str());
00263                                 logTrace(
00264                                         TRACE_MD,
00265                                         format("Got artist: %s") % getArtist()
00266                                 );
00267                                 break;
00268                         case OP_AMD_ALBUM:
00269                                 setAlbum(Utils::getVal<std::string>(
00270                                         i, len
00271                                 ).c_str());
00272                                 logTrace(
00273                                         TRACE_MD,
00274                                         format("Got album: %s") % getAlbum()
00275                                 );
00276                                 break;
00277                         case OP_AMD_GENRE:
00278                                 setGenre(Utils::getVal<std::string>(
00279                                         i, len
00280                                 ).c_str());
00281                                 logTrace(
00282                                         TRACE_MD,
00283                                         format("Got genre: %s") % getGenre()
00284                                 );
00285                                 break;
00286                         case OP_AMD_COMMENT:
00287                                 setComment(Utils::getVal<std::string>(
00288                                         i, len
00289                                 ).c_str());
00290                                 logTrace(
00291                                         TRACE_MD,
00292                                         format("Got comment: %s") % getComment()
00293                                 );
00294                                 break;
00295                         case OP_AMD_ORIGARTIST:
00296                                 setOrigArtist(Utils::getVal<std::string>(
00297                                         i, len
00298                                 ).c_str());
00299                                 logTrace(
00300                                         TRACE_MD,
00301                                         format("Got origartist: %s") %
00302                                         getOrigArtist()
00303                                 );
00304                                 break;
00305                         case OP_AMD_COPYRIGHT:
00306                                 setCopyright(Utils::getVal<std::string>(
00307                                         i, len
00308                                 ).c_str());
00309                                 logTrace(
00310                                         TRACE_MD, format("Got copyright: %s")
00311                                         % getCopyright()
00312                                 );
00313                                 break;
00314                         case OP_AMD_URL:
00315                                 setUrl(Utils::getVal<std::string>(
00316                                         i, len
00317                                 ).c_str());
00318                                 logTrace(
00319                                         TRACE_MD, format("Got url: %s")
00320                                         % getUrl()
00321                                 );
00322                                 break;
00323                         case OP_AMD_ENCODED:
00324                                 setEncoded(Utils::getVal<std::string>(
00325                                         i, len
00326                                 ).c_str());
00327                                 logTrace(
00328                                         TRACE_MD,
00329                                         format("Got encoded: %s") % getEncoded()
00330                                 );
00331                                 break;
00332                         case OP_AMD_YEAR:
00333                                 setYear(Utils::getVal<uint16_t>(i));
00334                                 logTrace(
00335                                         TRACE_MD,
00336                                         format("Got year: %d") % getYear()
00337                                 );
00338                                 break;
00339                         case OP_AMD_COMPOSER:
00340                                 setComposer(Utils::getVal<std::string>(
00341                                         i, len
00342                                 ).c_str());
00343                                 logTrace(
00344                                         TRACE_MD,
00345                                         format("Got composer: %s")
00346                                         % getComposer()
00347                                 );
00348                                 break;
00349                         default:
00350                                 logWarning(
00351                                         boost::format(
00352                                                 "Unhandled tag %s found at "
00353                                                 "offset %s while parsing "
00354                                                 "AudioMetaData stream."
00355                                         ) % Utils::hexDump(opcode)
00356                                         % Utils::hexDump(-3+i.tellg())
00357                                 );
00358                                 i.seekg(len, std::ios::cur);
00359                                 break;
00360                 }
00361                 if (!i) {
00362                         logError(
00363                                 "Unexpected end of stream while parsing "
00364                                 "AudioMetaData stream."
00365                         );
00366                         break;
00367                 }
00368         }
00369 }
00370 
00371 // Write to stream
00372 std::ostream& operator<<(std::ostream &o, const AudioMetaData &amd) {
00373         logTrace(TRACE_MD, "Writing AudioMetaData to stream.");
00374         Utils::putVal<uint8_t>(o, OP_AMD);
00375         uint16_t tagcount = 0;
00376         std::ostringstream str;
00377         if (amd.m_title) {
00378                 Utils::putVal<uint8_t>(str, OP_AMD_TITLE);
00379                 Utils::putVal<std::string>(str, amd.m_title);
00380                 ++tagcount;
00381         }
00382         if (amd.m_artist) {
00383                 Utils::putVal<uint8_t>(str, OP_AMD_ARTIST);
00384                 Utils::putVal<std::string>(str, amd.m_artist);
00385                 ++tagcount;
00386         }
00387         if (amd.m_album) {
00388                 Utils::putVal<uint8_t>(str, OP_AMD_ALBUM);
00389                 Utils::putVal<std::string>(str, amd.m_album);
00390                 ++tagcount;
00391         }
00392         if (amd.m_year) {
00393                 Utils::putVal<uint8_t>(str, OP_AMD_YEAR);
00394                 Utils::putVal<uint16_t>(str, 2);
00395                 Utils::putVal<uint16_t>(str, amd.m_year);
00396                 ++tagcount;
00397         }
00398         if (amd.m_genre) {
00399                 Utils::putVal<uint8_t>(str, OP_AMD_GENRE);
00400                 Utils::putVal<std::string>(str, amd.m_genre);
00401                 ++tagcount;
00402         }
00403         if (amd.m_comment) {
00404                 Utils::putVal<uint8_t>(str, OP_AMD_COMMENT);
00405                 Utils::putVal<std::string>(str, amd.m_comment);
00406                 ++tagcount;
00407         }
00408         if (amd.m_composer) {
00409                 Utils::putVal<uint8_t>(str, OP_AMD_COMPOSER);
00410                 Utils::putVal<std::string>(str, amd.m_composer);
00411                 ++tagcount;
00412         }
00413         if (amd.m_origartist) {
00414                 Utils::putVal<uint8_t>(str, OP_AMD_ORIGARTIST);
00415                 Utils::putVal<std::string>(str, amd.m_origartist);
00416                 ++tagcount;
00417         }
00418         if (amd.m_copyright) {
00419                 Utils::putVal<uint8_t>(str, OP_AMD_COPYRIGHT);
00420                 Utils::putVal<std::string>(str, amd.m_copyright);
00421                 ++tagcount;
00422         }
00423         if (amd.m_url) {
00424                 Utils::putVal<uint8_t>(str, OP_AMD_URL);
00425                 Utils::putVal<std::string>(str, amd.m_url);
00426                 ++tagcount;
00427         }
00428         if (amd.m_encoded) {
00429                 Utils::putVal<uint8_t>(str, OP_AMD_ENCODED);
00430                 Utils::putVal<std::string>(str, amd.m_encoded);
00431                 ++tagcount;
00432         }
00433         Utils::putVal<uint16_t>(o, str.str().size() + 2);
00434         Utils::putVal<uint16_t>(o, tagcount);
00435         Utils::putVal(o, str.str(), str.str().size());
00436         logTrace(
00437                 TRACE_MD,
00438                 boost::format("AudioMetaData: %d tags written.") % tagcount
00439         );
00440         return o;
00441 }
00442 
00443 // ArchiveMetaData
00444 // ---------------
00445 // Default constructor
00446 ArchiveMetaData::ArchiveMetaData()
00447 : m_format(0), m_files(0), m_uncomprsize(0), m_ratio(0), m_comment(0),
00448 m_password(false) {
00449 }
00450 
00451 // Constructo and load
00452 ArchiveMetaData::ArchiveMetaData(std::istream &i)
00453 : m_format(0), m_files(0), m_uncomprsize(0), m_ratio(0), m_comment(0),
00454 m_password(false) {
00455         logTrace(TRACE_MD, "Reading ArchiveMetaData from stream.");
00456         uint16_t tagcount = Utils::getVal<uint16_t>(i);
00457         logTrace(TRACE_MD, boost::format("%d tags to read") % tagcount);
00458         while (tagcount--) {
00459                 uint8_t opcode = Utils::getVal<uint8_t>(i);
00460                 uint16_t len = Utils::getVal<uint16_t>(i);
00461                 switch (opcode) {
00462                         case OP_ARMD_FORMAT:
00463                                 m_format = Utils::getVal<uint32_t>(i);
00464                                 logTrace(
00465                                         TRACE_MD,
00466                                         boost::format("Got format: %d")
00467                                         % m_format
00468                                 );
00469                                 break;
00470                         case OP_ARMD_FILES:
00471                                 m_files = Utils::getVal<uint32_t>(i);
00472                                 logTrace(
00473                                         TRACE_MD,
00474                                         boost::format("Got filecount: %d")
00475                                         % m_files
00476                                 );
00477                                 break;
00478                         case OP_ARMD_UNCOMPR:
00479                                 m_uncomprsize = Utils::getVal<uint64_t>(i);
00480                                 logTrace(
00481                                         TRACE_MD,
00482                                         boost::format("Got uncomprsize: %d")
00483                                         % m_uncomprsize
00484                                 );
00485                                 break;
00486                         case OP_ARMD_RATIO:
00487                                 m_ratio = Utils::getVal<float>(i);
00488                                 logTrace(
00489                                         TRACE_MD,
00490                                         boost::format("Got ratio: %f")
00491                                         % m_ratio
00492                                 );
00493                                 break;
00494                         case OP_ARMD_COMMENT:
00495                                 setComment(Utils::getVal<std::string>(
00496                                         i, len
00497                                 ).c_str());
00498                                 logTrace(
00499                                         TRACE_MD,
00500                                         boost::format("Got comment: %s")
00501                                         % m_comment
00502                                 );
00503                                 break;
00504                         case OP_ARMD_PASSWORD:
00505                                 m_password = Utils::getVal<uint8_t>(i);
00506                                 logTrace(
00507                                         TRACE_MD,
00508                                         boost::format("Got password: %s")
00509                                         % (m_password ? "true" : "false")
00510                                 );
00511                                 break;
00512                         default:
00513                                 logWarning(
00514                                         boost::format(
00515                                                 "Unhandled tag %s found at "
00516                                                 "offset %s while parsing "
00517                                                 "ArchiveMetaData stream."
00518                                         ) % Utils::hexDump(opcode)
00519                                         % Utils::hexDump(-3+i.tellg())
00520                                 );
00521                                 i.seekg(len, std::ios::cur);
00522                                 break;
00523                 }
00524                 if (!i) {
00525                         logError(
00526                                 "Unexpected end of stream while parsing "
00527                                 "ArchiveMetaData stream."
00528                         );
00529                         break;
00530                 }
00531         }
00532 }
00533 
00534 // Write to stream
00535 std::ostream& operator<<(std::ostream &o, const ArchiveMetaData &amd) {
00536         logTrace(TRACE_MD, "Writing ArchiveMetaData to stream.");
00537         Utils::putVal<uint8_t>(o, OP_ARMD);
00538         uint16_t tagcount = 0;
00539         std::ostringstream str;
00540         if (amd.m_format) {
00541                 Utils::putVal<uint8_t>(str, OP_ARMD_FORMAT);
00542                 Utils::putVal<uint16_t>(str, 4);
00543                 Utils::putVal(str, amd.m_format);
00544                 ++tagcount;
00545         }
00546         if (amd.m_files) {
00547                 Utils::putVal<uint8_t>(str, OP_ARMD_FILES);
00548                 Utils::putVal<uint16_t>(str, 4);
00549                 Utils::putVal<uint32_t>(str, amd.m_files);
00550                 ++tagcount;
00551         }
00552         if (amd.m_uncomprsize) {
00553                 Utils::putVal<uint8_t>(str, OP_ARMD_UNCOMPR);
00554                 Utils::putVal<uint16_t>(str, 8);
00555                 Utils::putVal<uint64_t>(str, amd.m_uncomprsize);
00556                 ++tagcount;
00557         }
00558         if (amd.m_ratio) {
00559                 Utils::putVal<uint8_t>(str, OP_ARMD_RATIO);
00560                 Utils::putVal<uint16_t>(str, 4);
00561                 Utils::putVal<float>(str, amd.m_ratio);
00562                 ++tagcount;
00563         }
00564         if (amd.m_comment) {
00565                 Utils::putVal<uint8_t>(str, OP_ARMD_COMMENT);
00566                 Utils::putVal<std::string>(str, amd.m_comment);
00567                 ++tagcount;
00568         }
00569         if (amd.m_password) {
00570                 Utils::putVal<uint8_t>(str, OP_ARMD_PASSWORD);
00571                 Utils::putVal<uint16_t>(str, 1);
00572                 Utils::putVal<uint8_t>(str, amd.m_password);
00573                 ++tagcount;
00574         }
00575         Utils::putVal<uint16_t>(o, str.str().size() + 2);
00576         Utils::putVal<uint16_t>(o, tagcount);
00577         Utils::putVal(o, str.str(), str.str().size());
00578         logTrace(
00579                 TRACE_MD,
00580                 boost::format("ArchiveMetaData: %d tags written.") % tagcount
00581         );
00582         return o;
00583 }
00584 
00585 // ImageMetaData
00586 // -------------
00587 // Default constructor
00588 ImageMetaData::ImageMetaData() : m_format(0), m_width(0), m_height(0),
00589 m_comment(0), m_created(0) {
00590 }
00591 
00592 // Construct and load
00593 ImageMetaData::ImageMetaData(std::istream &i) : m_format(0), m_width(0),
00594 m_height(0), m_comment(0), m_created(0) {
00595         logTrace(TRACE_MD, "Reading ImageMetaData from stream.");
00596         uint16_t tagcount = Utils::getVal<uint16_t>(i);
00597         logTrace(TRACE_MD, boost::format("%d tags to read.") % tagcount);
00598         while (tagcount--) {
00599                 uint8_t opcode = Utils::getVal<uint8_t>(i);
00600                 uint16_t len = Utils::getVal<uint16_t>(i);
00601                 switch (opcode) {
00602                         case OP_IMD_FORMAT:
00603                                 m_format = Utils::getVal<uint32_t>(i);
00604                                 logTrace(
00605                                         TRACE_MD,
00606                                         boost::format("Got format: %d")
00607                                         % m_format
00608                                 );
00609                                 break;
00610                         case OP_IMD_WIDTH:
00611                                 m_width = Utils::getVal<uint32_t>(i);
00612                                 logTrace(
00613                                         TRACE_MD,
00614                                         boost::format("Got width: %d")
00615                                         % m_width
00616                                 );
00617                                 break;
00618                         case OP_IMD_HEIGHT:
00619                                 m_height = Utils::getVal<uint32_t>(i);
00620                                 logTrace(
00621                                         TRACE_MD,
00622                                         boost::format("Got height: %d")
00623                                         % m_height
00624                                 );
00625                                 break;
00626                         case OP_IMD_DATE:
00627                                 m_created = Utils::getVal<uint32_t>(i);
00628                                 logTrace(
00629                                         TRACE_MD,
00630                                         boost::format("Got creation date: %d")
00631                                         % m_created
00632                                 );
00633                                 break;
00634                         case OP_IMD_COMMENT:
00635                                 setComment(Utils::getVal<std::string>(
00636                                         i, len
00637                                 ).c_str());
00638                                 logTrace(
00639                                         TRACE_MD,
00640                                         boost::format("Got comment: %s")
00641                                         % m_comment
00642                                 );
00643                                 break;
00644                         default:
00645                                 logWarning(
00646                                         boost::format(
00647                                                 "Unhandled tag %s found at "
00648                                                 "offset %s while parsing "
00649                                                 "ImageMetaData stream."
00650                                         ) % Utils::hexDump(opcode)
00651                                         % Utils::hexDump(-3+i.tellg())
00652                                 );
00653                                 i.seekg(len, std::ios::cur);
00654                                 break;
00655                 }
00656                 if (!i) {
00657                         logError(
00658                                 "Unexpected end of stream while parsing "
00659                                 "ImageMetaData stream."
00660                         );
00661                         break;
00662                 }
00663         }
00664 }
00665 
00666 // Write to stream
00667 std::ostream& operator<<(std::ostream &o, const ImageMetaData &imd) {
00668         logTrace(TRACE_MD, "Writing ImageMetaData to stream.");
00669         Utils::putVal<uint8_t>(o, OP_IMD);
00670         uint16_t tagcount = 0;
00671         std::ostringstream str;
00672         if (imd.m_format) {
00673                 Utils::putVal<uint8_t>(str, OP_IMD_FORMAT);
00674                 Utils::putVal<uint16_t>(str, 4);
00675                 Utils::putVal<uint32_t>(str, imd.m_format);
00676                 ++tagcount;
00677         }
00678         if (imd.m_width) {
00679                 Utils::putVal<uint8_t>(str, OP_IMD_WIDTH);
00680                 Utils::putVal<uint16_t>(str, 4);
00681                 Utils::putVal<uint32_t>(str, imd.m_width);
00682                 ++tagcount;
00683         }
00684         if (imd.m_height) {
00685                 Utils::putVal<uint8_t>(str, OP_IMD_HEIGHT);
00686                 Utils::putVal<uint16_t>(str, 4);
00687                 Utils::putVal<uint32_t>(str, imd.m_height);
00688                 ++tagcount;
00689         }
00690         if (imd.m_comment) {
00691                 Utils::putVal<uint8_t>(str, OP_IMD_COMMENT);
00692                 Utils::putVal<std::string>(str, imd.m_comment);
00693                 ++tagcount;
00694         }
00695         if (imd.m_created) {
00696                 Utils::putVal<uint8_t>(str, OP_IMD_DATE);
00697                 Utils::putVal<uint16_t>(str, 4);
00698                 Utils::putVal<uint32_t>(str, imd.m_created);
00699                 ++tagcount;
00700         }
00701         Utils::putVal<uint16_t>(o, str.str().size() + 2);
00702         Utils::putVal<uint16_t>(o, tagcount);
00703         Utils::putVal(o, str.str(), str.str().size());
00704         logTrace(
00705                 TRACE_MD,
00706                 boost::format("ImageMetaData: %d tags written.") % tagcount
00707         );
00708         return o;
00709 }
00710 
00711 // MetaData
00712 // --------
00713 IMPLEMENT_EVENT_TABLE(MetaData, MetaData*, int);
00714 
00715 //! Constructor
00716 MetaData::MetaData(uint64_t fileSize, FileType type, bool typeGuessed)
00717 : m_archiveData(0), m_imageData(0), m_fileSize(fileSize), m_modDate(0),
00718 m_fileType(type), m_typeGuessed(typeGuessed) {
00719 }
00720 
00721 //! Default constructor
00722 MetaData::MetaData() : m_archiveData(0), m_imageData(0), m_fileSize(0),
00723 m_modDate(0), m_fileType(FT_UNKNOWN), m_typeGuessed(0) {}
00724 
00725 // Construct & load
00726 MetaData::MetaData(std::istream &i) : m_archiveData(0), m_imageData(0),
00727 m_fileSize(0), m_modDate(0), m_fileType(FT_UNKNOWN), m_typeGuessed(0) {
00728         logTrace(TRACE_MD, "Reading MetaData from stream.");
00729         uint16_t tagcount = Utils::getVal<uint16_t>(i);
00730         logTrace(TRACE_MD, boost::format("%d tags to read.") % tagcount);
00731         while (tagcount--) {
00732                 uint8_t opcode = Utils::getVal<uint8_t>(i);
00733                 uint16_t len = Utils::getVal<uint16_t>(i);
00734                 switch (opcode) {
00735                         case OP_AMD:
00736                                 m_audioData.push_back(new AudioMetaData(i));
00737                                 logTrace(TRACE_MD, "Got AudioMetaData.");
00738                                 break;
00739                         case OP_VMD:
00740                                 m_videoData.push_back(new VideoMetaData(i));
00741                                 logTrace(TRACE_MD, "Got VideoMetaData.");
00742                                 break;
00743                         case OP_ARMD:
00744                                 m_archiveData = new ArchiveMetaData(i);
00745                                 logTrace(TRACE_MD, "Got ArchiveMetaData.");
00746                                 break;
00747                         case OP_IMD:
00748                                 m_imageData = new ImageMetaData(i);
00749                                 logTrace(TRACE_MD, "Got ImageMetaData.");
00750                                 break;
00751                         case OP_HASHSET:
00752                                 m_hashsets.push_back(loadHashSet(i));
00753                                 logTrace(TRACE_MD, "Got Hashset.");
00754                                 break;
00755                         case OP_MD_FILENAME:
00756                                 m_fileNames.push_back(
00757                                         Utils::getVal<std::string>(i, len)
00758                                 );
00759                                 logTrace(
00760                                         TRACE_MD,
00761                                         boost::format("Got filename: %s")
00762                                         % m_fileNames.back()
00763                                 );
00764                                 break;
00765                         case OP_MD_FILESIZE:
00766                                 m_fileSize = Utils::getVal<uint64_t>(i);
00767                                 logTrace(
00768                                         TRACE_MD,
00769                                         boost::format("Got size: %d")
00770                                         % m_fileSize
00771                                 );
00772                                 break;
00773                         case OP_MD_MODDATE:
00774                                 m_modDate = Utils::getVal<uint32_t>(i);
00775                                 logTrace(
00776                                         TRACE_MD,
00777                                         boost::format("Got moddate: %d")
00778                                         % m_modDate
00779                                 );
00780                                 break;
00781                         case OP_MD_FILETYPE:
00782                                 m_fileType = static_cast<FileType>(
00783                                         Utils::getVal<uint32_t>(i)
00784                                 );
00785                                 logTrace(
00786                                         TRACE_MD,
00787                                         boost::format("Got filetype: %d")
00788                                         % m_fileType
00789                                 );
00790                                 break;
00791                         case OP_MD_TYPEGUESSED:
00792                                 m_typeGuessed = Utils::getVal<uint8_t>(i);
00793                                 logTrace(
00794                                         TRACE_MD,
00795                                         boost::format("Got typeguessed: %s")
00796                                         % (m_typeGuessed ? "true" : "false")
00797                                 );
00798                                 break;
00799                         default:
00800                                 logWarning(
00801                                         boost::format(
00802                                                 "Unknown tag %s found at "
00803                                                 "offset %s while parsing "
00804                                                 "MetaData stream."
00805                                         ) % Utils::hexDump(opcode)
00806                                         % Utils::hexDump(-3+i.tellg())
00807                                 );
00808                                 i.seekg(len, std::ios::cur);
00809                                 break;
00810                 }
00811                 if (!i) {
00812                         logError(
00813                                 "Unexpected end of stream while parsing "
00814                                 "MetaData stream."
00815                         );
00816                         break;
00817                 }
00818         }
00819 }
00820 
00821 //! Destructor
00822 MetaData::~MetaData() {
00823         if (m_archiveData) {
00824                 delete m_archiveData;
00825         }
00826         if (m_imageData) {
00827                 delete m_imageData;
00828         }
00829         while (m_videoData.size() > 0) {
00830                 delete m_videoData.back();
00831                 m_videoData.pop_back();
00832         }
00833         while (m_audioData.size() > 0) {
00834                 delete m_audioData.back();
00835                 m_audioData.pop_back();
00836         }
00837         while (m_hashsets.size() > 0) {
00838                 delete m_hashsets.back();
00839                 m_hashsets.pop_back();
00840         }
00841 }
00842 
00843 std::ostream& operator<<(std::ostream &o, const MetaData &md) {
00844         logTrace(TRACE_MD, "Writing MetaData to stream.");
00845         Utils::putVal<uint8_t>(o, OP_METADATA);
00846 
00847         uint16_t tagcount = 0;
00848         std::ostringstream str;
00849 
00850         Utils::putVal<uint8_t>(str, OP_MD_FILESIZE);
00851         Utils::putVal<uint16_t>(str, 8);
00852         Utils::putVal<uint64_t>(str, md.m_fileSize);
00853         ++tagcount;
00854         Utils::putVal<uint8_t>(str, OP_MD_MODDATE);
00855         Utils::putVal<uint16_t>(str, 4);
00856         Utils::putVal<uint32_t>(str, md.m_modDate);
00857         ++tagcount;
00858         Utils::putVal<uint8_t>(str, OP_MD_FILETYPE);
00859         Utils::putVal<uint16_t>(str, 4);
00860         Utils::putVal<uint32_t>(str, md.m_fileType);
00861         ++tagcount;
00862         Utils::putVal<uint8_t>(str, OP_MD_TYPEGUESSED);
00863         Utils::putVal<uint16_t>(str, 1);
00864         Utils::putVal<uint8_t>(str, md.m_typeGuessed);
00865         ++tagcount;
00866 
00867         for (uint32_t i = 0; i < md.getFileNameCount(); i++) {
00868                 Utils::putVal<uint8_t>(str, OP_MD_FILENAME);
00869                 Utils::putVal(str, md.getFileName(i));
00870                 ++tagcount;
00871         }
00872         for (uint32_t i = 0; i < md.m_videoData.size(); ++i) {
00873                 str << *md.m_videoData[i];
00874                 ++tagcount;
00875         }
00876         for (uint32_t i = 0; i < md.m_audioData.size(); ++i) {
00877                 str << *md.m_audioData[i];
00878                 ++tagcount;
00879         }
00880         if (md.m_archiveData != 0) {
00881                 str << *md.m_archiveData;
00882                 ++tagcount;
00883         }
00884         if (md.m_imageData != 0) {
00885                 str << *md.m_imageData;
00886                 ++tagcount;
00887         }
00888         for (uint32_t i = 0; i < md.m_hashsets.size(); ++i) {
00889                 str << *md.m_hashsets[i];
00890                 ++tagcount;
00891         }
00892         Utils::putVal<uint16_t>(o, str.str().size() + 2);
00893         Utils::putVal<uint16_t>(o, tagcount);
00894         Utils::putVal(o, str.str(), str.str().size());
00895         logTrace(
00896                 TRACE_MD,
00897                 boost::format("MetaData: %d tags written.") % tagcount
00898         );
00899         return o;
00900 }