示例#1
0
文件: TagTree.cpp 项目: SSE4/vmf-1
void TagTree::addOffset(LFA_FileRef file)
{
	// 3 points for doing it here: shortness, convenience, 64bit forks needed 
	#if WIN_ENV
		addComment( "offset: 0x%I64X", LFA_Tell( file ) );
	#else
		addComment( "offset: 0x%ll.16X", LFA_Tell( file ) );
	#endif
}
示例#2
0
//*** kind of a hack, TOTEST
bool LFA_isEof( LFA_FileRef file )
{
	#if XMP_MacBuild
		long refNum = (long)file;	// ! Use long to avoid size warnings for SInt16 cast.

		XMP_Int64 position, length;
		OSErr err = FSGetForkPosition( refNum, &position );
		if ( err != noErr )
			LFA_Throw ( "LFA_isEOF:FSGetForkPosition failure", kLFAErr_ExternalFailure );

		err = FSGetForkSize ( refNum, &length );
		if ( err != noErr )
			LFA_Throw ( "LFA_isEof: FSGetForkSize failure", kLFAErr_ExternalFailure );

		return position==length;
	#endif

	#if XMP_WinBuild
		HANDLE handle = (HANDLE)file;

		XMP_Int64 filepos = LFA_Tell(file);

		DWORD lowWord, highWord;
		lowWord = GetFileSize(handle, &highWord);
		XMP_Int64 filesize = ( ((XMP_Int64)highWord) << 32 | lowWord );

		return filesize == filepos;
	#endif

	#if XMP_UNIXBuild || XMP_iOSBuild
		int descr = (int)file;

		struct stat info;
		if (fstat(descr,&info) == -1)
		  LFA_Throw ( "LFA_isEof: fstat failed.", kLFAErr_ExternalFailure );

		return LFA_Tell(file) == info.st_size;
	#endif
}
示例#3
0
// =================================================================================================
// MP3_MetaHandler::CacheFileData
// ==============================
void MP3_MetaHandler::CacheFileData()
{
	//*** abort procedures
	this->containsXMP = false;		//assume no XMP for now

	LFA_FileRef file = this->parent->fileRef;
	XMP_PacketInfo &packetInfo = this->packetInfo;

	LFA_Rewind(file);

	hasID3Tag = id3Header.read( file );
	majorVersion = id3Header.fields[ID3Header::o_version_major];
	minorVersion = id3Header.fields[ID3Header::o_version_minor];
	hasExtHeader = (0 != ( 0x40 & id3Header.fields[ID3Header::o_flags])); //'naturally' false if no ID3Tag
	hasFooter = ( 0 != ( 0x10 & id3Header.fields[ID3Header::o_flags])); //'naturally' false if no ID3Tag

	// stored size is w/o initial header (thus adding 10)
	// + but extended header (if existing)
	// + padding + frames after unsynchronisation (?)
	// (if no ID3 tag existing, constructed default correctly sets size to 10.)
	oldTagSize = 10 + synchToInt32(GetUns32BE( &id3Header.fields[ID3Header::o_size] ));

	if (hasExtHeader)
	{
		extHeaderSize = synchToInt32( LFA_ReadInt32_BE( file));
		XMP_Uns8 extHeaderNumFlagBytes = LFA_ReadUns8( file );

		// v2.3 doesn't include the size, while v2.4 does
		if ( majorVersion < 4 ) extHeaderSize += 4; 
		XMP_Validate( extHeaderSize >= 6, "extHeader size too small", kXMPErr_BadFileFormat );

		bool ok;
		LFA_Seek(file, extHeaderSize - 6, SEEK_CUR , &ok);
		XMP_Assert(ok);
	}
	else
	{
		extHeaderSize = 0; // := there is no such header.
	}

	this->framesVector.clear(); //mac precaution
	ID3v2Frame* curFrame = 0; // reusable

	////////////////////////////////////////////////////
	// read frames
	while ( LFA_Tell(file) < oldTagSize )
	{
		curFrame = new ID3v2Frame();

		try {
			XMP_Int64 frameSize = curFrame->read( file, majorVersion );
			if (frameSize == 0) // no more frames coming => proceed to padding
			{
				delete curFrame; // ..since not becoming part of vector for latter delete.
				break;			 // not a throw. There's nothing wrong with padding.
			}
			this->containsXMP = true;
		} catch( XMP_Error e)
		{
			delete curFrame;
			XMP_Throw( e.GetErrMsg(), e.GetID()); // rethrow
		}

		// these are both pointer assignments, no (copy) construction
		// (MemLeak Note: for all things pushed, memory cleanup is taken care of in destructor.)
		this->framesVector.push_back( curFrame );

		//remember XMP-Frame, if it occurs:
		if ( CheckBytes( &curFrame->fields[ID3v2Frame::o_id], "PRIV", 4 ))
			if( curFrame->contentSize > 8 ) // to avoid adress violation on very small non-XMP PRIV frames
				if( CheckBytes( &curFrame->content[0], "XMP\0", 4 ))
				{
					// be sure that this is the first packet (all else would be illegal format)
					XMP_Validate( framesMap[ XMP_FRAME_ID] == 0, "two XMP packets in one file", kXMPErr_BadFileFormat );
					//add this to map, needed on reconciliation
					framesMap[ XMP_FRAME_ID ] = curFrame;

					this->packetInfo.length = curFrame->contentSize - 4; // content minus "XMP\0"
					this->packetInfo.offset = ( LFA_Tell(file) - this->packetInfo.length );

					this->xmpPacket.erase(); //safety
					this->xmpPacket.assign( &curFrame->content[4], curFrame->contentSize - 4 );
					this->containsXMP = true; // do this last, after all possible failure
				}

				// No space for another frame? => assume into ID3v2.4 padding.
				if ( LFA_Tell(file) + 10 >= oldTagSize )
					break;
	}

	////////////////////////////////////////////////////
	// padding
	oldPadding = oldTagSize - LFA_Tell( file );
	oldFramesSize = oldTagSize - 10 - oldPadding;

	XMP_Validate( oldPadding >= 0, "illegal oldTagSize or padding value", kXMPErr_BadFileFormat );

	for ( XMP_Int64 i = oldPadding; i > 0;)
	{
		if ( i >= 8 ) // worthwhile optimization
		{
			if ( LFA_ReadInt64_BE(file) != 0 )
				XMP_Throw ( "padding not nulled out.", kXMPErr_BadFileFormat );
			i -= 8;
			continue;
		}
		if ( LFA_ReadUns8(file) != 0)
			XMP_Throw ( "padding(2) not nulled out.", kXMPErr_BadFileFormat );
		i--;
	}

	//// read ID3v1 tag
	if ( ! this->containsXMP ) // all else has priority
	{
		this->containsXMP = id3v1Tag.read( file, &this->xmpObj );
	}

}	// MP3_MetaHandler::CacheFileData