All pastes #1587977 Raw Edit

sai

public text v1 · immutable
#1587977 ·published 2009-10-01 17:03 UTC
rendered paste body
/**caudiotags.cpp: implementation of the AudioTag componentauthor: ksk*/#include "../../inc/caudiotags.hpp"// checks for a valid ID3 frame// valid ID3 frames are alphanumsinline bool isValidFrame(char frame[]){	return( isalnum(frame[0]) && isalnum(frame[1]) && isalnum(frame[2]) && isalnum(frame[3]) );}// compares a non-terminated char* with a null-terminated char*inline bool compareFrame(char data[], char frame[]){	return( data[0]==frame[0] && data[1]==frame[1] && data[2]==frame[2] && data[3]==frame[3] );}// converts an encoded std::string to an unsigned intunsigned int toUnsigned(std::string data){	unsigned int value;	sscanf(data.c_str(), "%*c%u", &value);	return value;}void AudioTag::ID3v23TagReader::renderFile(std::string file) throw (TagException){	char data[4], size[4], flags[2], temp;		tag_size = 0;		// ID3v2.3 frames	char FRAME_COMM[] = "COMM", FRAME_TALB[] = "TALB", FRAME_TPE1[] = "TPE1",	     FRAME_TIT2[] = "TIT2", FRAME_TRCK[] = "TRCK", FRAME_TYER[] = "TYER",	     FRAME_APIC[] = "APIC";		// reset tag	tag.title = "";	tag.artist = "";	tag.album = "";	tag.track = 0;	tag.year = 0;	tag.artfile = "";			instream.open( file.c_str(), std::ios::in | std::ios::binary );	if( !instream.is_open() )		throw TagException(AudioTag::FILE_NOT_FOUND);		// read ID3 header	instream.read(data, 3); 		if( !(data[0] == 'I' && data[1] == 'D' && data[2] == '3') )	{		instream.close();		throw TagException(AudioTag::NO_TAG);	}		// read version	// must be 2.3.0 or 2.4.0	instream.read(flags, 2);		if( (int)flags[0] != 3 && (int)flags[0] != 4 && (int)flags[1] != 0 )	{		instream.close();		throw TagException(AudioTag::INVALID_TAG);	}		// read flags		instream.read(&temp, 1);	// check for extended header or experimental header	// and for a valid flag	if( temp & (1<<6) || temp & (1<<5) || temp & 0x1F) 	{		instream.close();		throw TagException(AudioTag::UNSUPPORTED_TAG);	}			// read size of tag	// buggy	instream.read(size, 4); 	for(int i=3; i>=0; i--)	{			unsigned char _size = (unsigned char)size[i];		if( _size > 0x80 )		{		    instream.close();			throw TagException(AudioTag::INVALID_TAG);		}		tag_size += (_size)<<(7*i);		}			// read frame		while(tag_size--)	{		instream.read(data, 4); // obtain next frame		if( !isValidFrame(data) ) break; // break if no valid frame was found				instream.read(size, 4); // read frame size		instream.read(flags, 2); // read flags				// calculate frame size in bytes		frame_size = 0;		for(int i=0; i<=3; i++)				{			unsigned char _size = (unsigned char) size[i];			frame_size |= (_size)<<(8 * (3-i));				}		tag_size -= frame_size;		if( tag_size <= 0 )			break;		// process frame		if( compareFrame(data, FRAME_COMM) ) // comment			tag.comment = readCOMMFrame();		else if( compareFrame(data, FRAME_TALB) ) // album			tag.album = readTXXXFrame();		else if( compareFrame(data, FRAME_TPE1) ) // artist			tag.artist = readTXXXFrame();		else if( compareFrame(data, FRAME_TIT2) ) // title			tag.title = readTXXXFrame();		else if( compareFrame(data, FRAME_TRCK) ) // track			tag.track = toUnsigned(readTXXXFrame());				else if( compareFrame(data, FRAME_TYER) ) // year								tag.year = toUnsigned(readTXXXFrame());		else if( compareFrame(data, FRAME_APIC) ) // album art			tag.artfile = readAPICFrame();		else		{			// unknown/boring frame			while(frame_size--)			{				instream.read(&temp, 1);			}		}	}	instream.close();}// frame processing functionsstd::string AudioTag::ID3v23TagReader::readCOMMFrame(){		char temp, buff[3], *comm, enc;		instream.read(&enc, 1); // text-encoding	instream.read(buff, 3); // language	instream.read(&temp, 1); // has to be 0x00			try	{		comm = new char[frame_size - 5 + 2];	}	catch(std::bad_alloc &ba)	{		// skip this frame		while(frame_size--)		{			instream.read(&temp, 1);		}		return "";	}		comm[0] = enc + 1;	comm++;	instream.read(comm, frame_size - 5);		comm[frame_size - 5]='\0';		comm--;	std::string comment(comm, frame_size - 5 + 2);	delete []comm;		return comment;}std::string AudioTag::ID3v23TagReader::readTXXXFrame(){    char temp, *data, enc;		instream.read(&enc, 1); //text-encoding		try	{		data = new char[frame_size + 1];			}	catch(std::bad_alloc &ba)	{		// skip this frame		while(frame_size--)		{			instream.read(&temp, 1);		}		return "";	}		data[0] = enc + 1;	data++;		instream.read(data, frame_size - 1);		data[frame_size - 1]='\0';		data--;	std::string tx_data(data, frame_size + 1);			delete []data;		return tx_data;	}std::string AudioTag::ID3v23TagReader::readAPICFrame(){	char temp, *picture_data;	unsigned int bytes_read = 0;		instream.read(&temp, 1); // text-encoding	bytes_read++;		do	{		instream.read(&temp, 1); // get MIME type		bytes_read++;	}	while( temp != 0 );		instream.read(&temp, 1); // get picture type	bytes_read++;	if( temp != 0 )	{		do		{			instream.read(&temp, 1); // get picture description			bytes_read++;		}		while(temp != 0);	}		try	{		picture_data = new char[frame_size - bytes_read]; // picture data	}	catch(std::bad_alloc &ba)	{		// skip this frame		while(frame_size--)		{			instream.read(&temp, 1);		}		return "";	}			instream.read(picture_data, frame_size - bytes_read);		srand( time(NULL) );	unsigned int _random_num = rand();	char filename[20];	sprintf(filename, "%u.jpg", _random_num);		std::ofstream out(filename, std::ios::out | std::ios::binary );	if( !out.is_open() ) return "";	out.write( picture_data, frame_size - 14);	out.close();		delete []picture_data;	return filename;}AudioTag::GenericTag AudioTag::ID3v23TagReader::getTag(){	return tag;}	void AudioTag::TagReader::renderFile(std::string file) throw (TagException){	std::ifstream in( file.c_str(), std::ios::in | std::ios::binary );	if( !in.is_open() )		throw TagException(AudioTag::FILE_NOT_FOUND);		std::string ext = file.substr(file.length()-3);		if( 0 == stricmp(ext.c_str(), "mp3") )		reader = &id3v23_reader;	else		throw TagException(AudioTag::UNSUPPORTED_TAG);			try	{		reader->renderFile(file);	}	catch(AudioTag::TagException &tex)	{		throw(tex);	}}AudioTag::GenericTag AudioTag::TagReader::getTag(){	return reader->getTag();}