BonkEnc::InputFilter *BonkEnc::Utilities::CreateInputFilter(const String &iFile, Track *trackInfo)
{
	Array<String>	 extensions;
	Array<Int>	 indexes;

	String		 file = iFile.ToLower();

	for (Int i = 0; i < DLLInterfaces::winamp_in_plugins.Length(); i++)
	{
		Int	 n = 1;
		Int	 k = 0;
		String	 extension;

		for (Int j = 0; true; j++)
		{
			if (!(n & 1))
			{
				if (DLLInterfaces::winamp_in_modules.GetNth(i)->FileExtensions[j] == 0) n++;
			}
			else
			{
				extension[k++] = DLLInterfaces::winamp_in_modules.GetNth(i)->FileExtensions[j];

				if (DLLInterfaces::winamp_in_modules.GetNth(i)->FileExtensions[j] == 0)
				{
					String	 extension2 = extension;
					Int	 o = 0;		

					for (Int m = 0; m <= extension2.Length(); m++)
					{
						if (extension2[m] == ';' || extension2[m] == 0)
						{
							extension[m - o] = 0;

							extensions.Add(extension);
							indexes.Add(i);

							o = m + 1;
						}
						else
						{
							extension[m - o] = tolower(extension2[m]);
						}
					}

					k = 0;
					n++;
					extension = "";
				}
			}

			if (DLLInterfaces::winamp_in_modules.GetNth(i)->FileExtensions[j] == 0 && DLLInterfaces::winamp_in_modules.GetNth(i)->FileExtensions[j + 1] == 0) break;
		}
	}

	Int	 found = -1;

	for (Int j = 0; j < extensions.Length(); j++)
	{
		if (file.EndsWith(extensions.GetNth(j)))
		{
			found = j;

			break;
		}
	}

	InputFilter	*filter_in = NIL;

	if ((file.StartsWith("/cda") || file.EndsWith(".cda")) && BonkEnc::currentConfig->enable_cdrip && BonkEnc::currentConfig->cdrip_numdrives >= 1)
	{
		filter_in = new FilterInCDRip(BonkEnc::currentConfig, trackInfo);
	}
	else if ((file.EndsWith(".mp1") || file.EndsWith(".mp2") || file.EndsWith(".mp3")) && BonkEnc::currentConfig->enable_mad)
	{
		filter_in = new FilterInMAD(BonkEnc::currentConfig, trackInfo);
	}
	else if ((file.EndsWith(".mp4") || file.EndsWith(".m4a") || file.EndsWith(".m4b")) && BonkEnc::currentConfig->enable_mp4 && BonkEnc::currentConfig->enable_faad2)
	{
		filter_in = new FilterInMP4(BonkEnc::currentConfig, trackInfo);
	}
	else if (file.EndsWith(".ogg") && BonkEnc::currentConfig->enable_vorbis)
	{
		filter_in = new FilterInVORBIS(BonkEnc::currentConfig, trackInfo);
	}
	else if (file.EndsWith(".aac") && BonkEnc::currentConfig->enable_faad2)
	{
		filter_in = new FilterInFAAD2(BonkEnc::currentConfig, trackInfo);
	}
	else if (file.EndsWith(".bonk") && BonkEnc::currentConfig->enable_bonk)
	{
		filter_in = new FilterInBONK(BonkEnc::currentConfig, trackInfo);
	}
	else if (file.EndsWith(".flac") && BonkEnc::currentConfig->enable_flac)
	{
		filter_in = new FilterInFLAC(BonkEnc::currentConfig, trackInfo);
	}
	else if (file.EndsWith(".wma") && BonkEnc::currentConfig->enable_wma)
	{
		filter_in = new FilterInWMA(BonkEnc::currentConfig, trackInfo);
	}
	else if (found != -1)
	{
		filter_in = new FilterInWinamp(BonkEnc::currentConfig, trackInfo, DLLInterfaces::winamp_in_modules.GetNth(indexes.GetNth(found)));
	}
	else
	{
		InStream	*f_in = new InStream(STREAM_FILE, file, IS_READONLY);
		Int		 magic = f_in->InputNumber(4);

		delete f_in;

		switch (magic)
		{
			case 1297239878:
				filter_in = new FilterInAIFF(BonkEnc::currentConfig, trackInfo);
				break;
			case 1684960046:
				filter_in = new FilterInAU(BonkEnc::currentConfig, trackInfo);
				break;
			case 1634038339:
				filter_in = new FilterInVOC(BonkEnc::currentConfig, trackInfo);
				break;
			case 1179011410:
				filter_in = new FilterInWAVE(BonkEnc::currentConfig, trackInfo);
				break;
		}
	}

	return filter_in;
}
Int BonkEnc::OutputFilter::RenderID3Tag(Int version, Buffer<unsigned char> &buffer)
{
	ID3Tag		*tag = ex_ID3Tag_New();

	ex_ID3Tag_SetPadding(tag, false);

	ID3_TextEnc	 encoding = ID3TE_NONE;
	String		 encString = (version == 1 ? currentConfig->id3v1_encoding : currentConfig->id3v2_encoding);

	if (encString == "UTF-8")		encoding = ID3TE_UTF8;
	else if (encString == "ISO-8859-1")	encoding = ID3TE_ISO8859_1;
	else if (encString == "UTF-16" ||
		 encString == "UTF-16LE" ||
		 encString == "UCS-2" ||
		 encString == "UCS-2LE")	encoding = ID3TE_UTF16;
	else if (encString == "UTF-16BE" ||
		 encString == "UCS-2BE")	encoding = ID3TE_UTF16BE;

	String		 prevOutFormat = String::SetOutputFormat(encString);
	String		 leBOM;

	leBOM[0] = 0xFEFF;

	ID3Frame	*artist = ex_ID3Frame_NewID(ID3FID_LEADARTIST);

	if (format->artist != NIL)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(artist, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(artist, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(artist, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(format->artist).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(artist, ID3FN_TEXT), (unicode_t *) format->artist.ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(artist, ID3FN_TEXT), format->artist);

		ex_ID3Tag_AddFrame(tag, artist);
	}

	ID3Frame	*title = ex_ID3Frame_NewID(ID3FID_TITLE);

	if (format->title != NIL)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(title, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(title, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(title, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(format->title).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(title, ID3FN_TEXT), (unicode_t *) format->title.ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(title, ID3FN_TEXT), format->title);

		ex_ID3Tag_AddFrame(tag, title);
	}

	ID3Frame	*album = ex_ID3Frame_NewID(ID3FID_ALBUM);

	if (format->album != NIL)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(album, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(album, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(album, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(format->album).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(album, ID3FN_TEXT), (unicode_t *) format->album.ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(album, ID3FN_TEXT), format->album);

		ex_ID3Tag_AddFrame(tag, album);
	}

	ID3Frame	*track = ex_ID3Frame_NewID(ID3FID_TRACKNUM);

	if (format->track > 0)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(track, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(track, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(track, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(String(format->track < 10 ? "0" : "").Append(String::FromInt(format->track))).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(track, ID3FN_TEXT), (unicode_t *) String(format->track < 10 ? "0" : "").Append(String::FromInt(format->track)).ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(track, ID3FN_TEXT), String(format->track < 10 ? "0" : "").Append(String::FromInt(format->track)));

		ex_ID3Tag_AddFrame(tag, track);
	}

	ID3Frame	*year = ex_ID3Frame_NewID(ID3FID_YEAR);

	if (format->year > 0)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(year, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(year, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(year, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(String::FromInt(format->year)).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(year, ID3FN_TEXT), (unicode_t *) String::FromInt(format->year).ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(year, ID3FN_TEXT), String::FromInt(format->year));

		ex_ID3Tag_AddFrame(tag, year);
	}

	ID3Frame	*genre = ex_ID3Frame_NewID(ID3FID_CONTENTTYPE);

	if (format->genre != NIL)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(genre, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(genre, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(genre, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(format->genre).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(genre, ID3FN_TEXT), (unicode_t *) format->genre.ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(genre, ID3FN_TEXT), format->genre);

		ex_ID3Tag_AddFrame(tag, genre);
	}

	ID3Frame	*comment = ex_ID3Frame_NewID(ID3FID_COMMENT);

	if (format->comment != NIL && !currentConfig->overwriteComments)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(comment, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(comment, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(comment, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(format->comment).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(comment, ID3FN_TEXT), (unicode_t *) format->comment.ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(comment, ID3FN_TEXT), format->comment);

		ex_ID3Tag_AddFrame(tag, comment);
	}
	else if (currentConfig->default_comment != NIL) 
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(comment, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(comment, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(comment, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(currentConfig->default_comment).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(comment, ID3FN_TEXT), (unicode_t *) currentConfig->default_comment.ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(comment, ID3FN_TEXT), currentConfig->default_comment);

		ex_ID3Tag_AddFrame(tag, comment);
	}

	ID3Frame	*label = ex_ID3Frame_NewID(ID3FID_PUBLISHER);

	if (format->label != NIL)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(label, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(label, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(label, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(format->label).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(label, ID3FN_TEXT), (unicode_t *) format->label.ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(label, ID3FN_TEXT), format->label);

		ex_ID3Tag_AddFrame(tag, label);
	}

	ID3Frame	*isrc = ex_ID3Frame_NewID(ID3FID_ISRC);

	if (format->isrc != NIL)
	{
		ex_ID3Field_SetINT(ex_ID3Frame_GetField(isrc, ID3FN_TEXTENC), encoding);
		ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(isrc, ID3FN_TEXT), encoding);

		if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(isrc, ID3FN_TEXT), (unicode_t *) String(leBOM).Append(format->isrc).ConvertTo("UTF-16LE"));
		else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(isrc, ID3FN_TEXT), (unicode_t *) format->isrc.ConvertTo("UTF-16BE"));
		else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(isrc, ID3FN_TEXT), format->isrc);

		ex_ID3Tag_AddFrame(tag, isrc);
	}

	Array<ID3Frame *>	 pictures;

	if (currentConfig->copy_picture_tags)
	{
		for (Int i = 0; i < format->pictures.Length(); i++)
		{
			ID3Frame	*picture = ex_ID3Frame_NewID(ID3FID_PICTURE);
			Picture		*picInfo = format->pictures.GetNth(i);

			ex_ID3Field_SetINT(ex_ID3Frame_GetField(picture, ID3FN_TEXTENC), encoding);
			ex_ID3Field_SetEncoding(ex_ID3Frame_GetField(picture, ID3FN_DESCRIPTION), encoding);

			if (encoding == ID3TE_UTF16)		ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(picture, ID3FN_DESCRIPTION), (unicode_t *) String(leBOM).Append(picInfo->description).ConvertTo("UTF-16LE"));
			else if (encoding == ID3TE_UTF16BE)	ex_ID3Field_SetUNICODE(ex_ID3Frame_GetField(picture, ID3FN_DESCRIPTION), (unicode_t *) picInfo->description.ConvertTo("UTF-16BE"));
			else					ex_ID3Field_SetASCII(ex_ID3Frame_GetField(picture, ID3FN_DESCRIPTION), picInfo->description);

			ex_ID3Field_SetASCII(ex_ID3Frame_GetField(picture, ID3FN_MIMETYPE), picInfo->mime.ConvertTo("ISO-8859-1"));
			ex_ID3Field_SetINT(ex_ID3Frame_GetField(picture, ID3FN_PICTURETYPE), picInfo->type);
			ex_ID3Field_SetBINARY(ex_ID3Frame_GetField(picture, ID3FN_DATA), picInfo->data, picInfo->data.Size());

			ex_ID3Tag_AddFrame(tag, picture);

			pictures.Add(picture);
		}
	}

	String::SetOutputFormat(prevOutFormat.ConvertTo("ISO-8859-1"));

	buffer.Resize(ex_ID3Tag_Size(tag));

	Int	 size = ex_ID3Tag_Render(tag, buffer, version == 1 ? ID3TT_ID3V1 : ID3TT_ID3V2);

	ex_ID3Tag_Delete(tag);
	ex_ID3Frame_Delete(artist);
	ex_ID3Frame_Delete(title);
	ex_ID3Frame_Delete(album);
	ex_ID3Frame_Delete(track);
	ex_ID3Frame_Delete(year);
	ex_ID3Frame_Delete(genre);
	ex_ID3Frame_Delete(label);
	ex_ID3Frame_Delete(isrc);
	ex_ID3Frame_Delete(comment);

	for (Int j = 0; j < format->pictures.Length(); j++)
	{
		ex_ID3Frame_Delete(pictures.GetNth(j));
	}

	return size;
}