/*
 * $Id: MediaFormats.cpp 815 2008-10-02 05:52:50Z Aleksoid $
 *
 * (C) 2003-2006 Gabest
 * (C) 2006-2007 see AUTHORS
 *
 * This file is part of mplayerc.
 *
 * Mplayerc is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Mplayerc is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "stdafx.h"
#include <atlbase.h>
#include "MediaFormats.h"
#include "resource.h"

CString			g_strPrefix			   = _T("mplayerc.");

//
// CMediaFormatCategory
//

CMediaFormatCategory::CMediaFormatCategory()
	: m_fAudioOnly(false)
{
}

CMediaFormatCategory::CMediaFormatCategory(
	CString label, CString CommonExt, CAtlList<CString>& exts, int iconIndex, bool fAudioOnly,
	CString specreqnote, engine_t engine)
{
	m_iconIndex = iconIndex;
	m_label = label;
	m_exts.AddTailList(&exts);
	m_backupexts.AddTailList(&m_exts);
	m_specreqnote = specreqnote;
	m_fAudioOnly = fAudioOnly;
	m_engine = engine;
	m_progid = g_strPrefix + CommonExt;
}

CMediaFormatCategory::CMediaFormatCategory(
	CString label, CString CommonExt, CString exts, int iconIndex, bool fAudioOnly,
	CString specreqnote, engine_t engine)
{
	m_iconIndex = iconIndex;
	m_label = label;
	ExplodeMin(exts, m_exts, ' ');
	POSITION pos = m_exts.GetHeadPosition();
	while(pos) m_exts.GetNext(pos).TrimLeft('.');

	m_backupexts.AddTailList(&m_exts);
	m_specreqnote = specreqnote;
	m_fAudioOnly = fAudioOnly;
	m_engine = engine;
	m_progid = g_strPrefix + CommonExt;
}

CMediaFormatCategory::~CMediaFormatCategory()
{
}

void CMediaFormatCategory::UpdateData(bool fSave)
{
	if(fSave)
	{
		AfxGetApp()->WriteProfileString(_T("FileFormats"), m_label, GetExts(true));
	}
	else
	{
		SetExts(AfxGetApp()->GetProfileString(_T("FileFormats"), m_label, GetExts(true)));
	}
}

CMediaFormatCategory::CMediaFormatCategory(const CMediaFormatCategory& mfc)
{
	*this = mfc;
}

CMediaFormatCategory& CMediaFormatCategory::operator = (const CMediaFormatCategory& mfc)
{
	m_iconIndex = mfc.m_iconIndex;
	m_label = mfc.m_label;
	m_specreqnote = mfc.m_specreqnote;
	m_exts.RemoveAll();
	m_exts.AddTailList(&mfc.m_exts);
	m_backupexts.RemoveAll();
	m_backupexts.AddTailList(&mfc.m_backupexts);
	m_fAudioOnly = mfc.m_fAudioOnly;
	m_engine = mfc.m_engine;
	m_progid = mfc.m_progid;
	return *this;
}

void CMediaFormatCategory::RestoreDefaultExts()
{
	m_exts.RemoveAll();
	m_exts.AddTailList(&m_backupexts);
}

void CMediaFormatCategory::SetExts(CAtlList<CString>& exts)
{
	m_exts.RemoveAll();
	m_exts.AddTailList(&exts);
}

void CMediaFormatCategory::SetExts(CString exts)
{
	m_exts.RemoveAll();
	ExplodeMin(exts, m_exts, ' ');
	POSITION pos = m_exts.GetHeadPosition();
	while(pos)
	{
		POSITION cur = pos;
		CString& ext = m_exts.GetNext(pos);
		if(ext[0] == '\\') {m_engine = (engine_t)_tcstol(ext.TrimLeft('\\'), NULL, 10); m_exts.RemoveAt(cur);}
		else ext.TrimLeft('.');
	}
}

CString CMediaFormatCategory::GetFilter()
{
	CString filter;
	POSITION pos = m_exts.GetHeadPosition();
	while(pos) filter += _T("*.") + m_exts.GetNext(pos) + _T(";");
	filter.TrimRight(_T(";")); // cheap...
	return(filter);
}

CString CMediaFormatCategory::GetExts(bool fAppendEngine)
{
	CString exts = Implode(m_exts, ' ');
	if(fAppendEngine) exts += CString(_T(" \\")) + (TCHAR)(0x30 + (int)m_engine);
	return(exts);
}

CString CMediaFormatCategory::GetExtsWithPeriod(bool fAppendEngine)
{
	CString exts;
	POSITION pos = m_exts.GetHeadPosition();
	while(pos) exts += _T(".") + m_exts.GetNext(pos) + _T(" ");
	exts.TrimRight(_T(" ")); // cheap...
	if(fAppendEngine) exts += CString(_T(" \\")) + (TCHAR)(0x30 + (int)m_engine);
	return(exts);
}

CString CMediaFormatCategory::GetBackupExtsWithPeriod(bool fAppendEngine)
{
	CString exts;
	POSITION pos = m_backupexts.GetHeadPosition();
	while(pos) exts += _T(".") + m_backupexts.GetNext(pos) + _T(" ");
	exts.TrimRight(_T(" ")); // cheap...
	if(fAppendEngine) exts += CString(_T(" \\")) + (TCHAR)(0x30 + (int)m_engine);
	return(exts);
}

//
// 	CMediaFormats
//

CMediaFormats::CMediaFormats()
{
}

CMediaFormats::~CMediaFormats()
{
}

void CMediaFormats::UpdateData(bool fSave)
{
	if(fSave)
	{
		AfxGetApp()->WriteProfileString(_T("FileFormats"), NULL, NULL);

		AfxGetApp()->WriteProfileInt(_T("FileFormats"), _T("RtspHandler"), m_iRtspHandler);
		AfxGetApp()->WriteProfileInt(_T("FileFormats"), _T("RtspFileExtFirst"), m_fRtspFileExtFirst);
	}
	else
	{
		RemoveAll();
		int iconIndex = 0;

#define ADDFMT(f) Add(CMediaFormatCategory##f)
		ADDFMT((ResStr(IDS_MEDIAFORMATS_0),		_T("wmv"),	_T("wmv wmp wm asf"), iconIndex++));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_1),		_T("wma"),	_T("wma"), iconIndex++, true));
		ADDFMT((ResStr(IDS_AG_VIDEO_FILE),		_T("avi"),	_T("avi"), iconIndex++));
		ADDFMT((ResStr(IDS_AG_AUDIO_FILE),		_T("wav"),	_T("wav"), iconIndex++, true));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_4),		_T("mpg"),	_T("mpg mpeg mpe m1v m2v mpv2 mp2v ts tp tpr pva pss m2ts m2t mts evo"), iconIndex++));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_5),		_T("mpa"),	_T("mpa mp2 m1a m2a"), iconIndex++, true));
		ADDFMT((ResStr(IDS_AG_DVD_FILE),		_T("dvdf"),	_T("vob ifo"), iconIndex++));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_7),		_T("dvda"),	_T("ac3 dts"), iconIndex++, true));
		ADDFMT((_T("MP3 Format Sound"),			_T("mp3"),	_T("mp3"), iconIndex++, true));
		ADDFMT((ResStr(IDS_AG_MIDI_FILE),		_T("mid"),	_T("mid midi rmi"), iconIndex++, true));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_9),		_T("ivf"),	_T("ivf"), iconIndex++));
		ADDFMT((_T("AIFF Format Sound"),		_T("aiff"),	_T("aif aifc aiff"), iconIndex++, true));
		ADDFMT((_T("AU Format Sound"),			_T("au"),	_T("au snd"), iconIndex++, true));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_10),	_T("ogm"),	_T("ogm ogv"), iconIndex++));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_11),	_T("ogg"),	_T("ogg oga"), iconIndex++, true));
		ADDFMT((_T("CD Audio Track"),			_T("cda"),	_T("cda"), iconIndex++, true, ResStr(IDS_MEDIAFORMATS_12)));
		ADDFMT((ResStr(IDS_AG_FLIC_FILE),		_T("flic"),	_T("fli flc flic"), iconIndex++));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_14),	_T("d2v"),	_T("d2v"), iconIndex++));
		ADDFMT((ResStr(IDS_AG_MPEG4_FILE),		_T("mp4"),	_T("mp4 m4v hdmov 3gp 3gpp"), iconIndex++));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_16),	_T("aac"),	_T("m4a m4b aac"), iconIndex++, true));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_17),	_T("mkv"),	_T("mkv"), iconIndex++));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_18),	_T("mka"),	_T("mka"), iconIndex++, true));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_19),	_T("bik"),	_T("smk bik"), iconIndex++, false, _T("smackw32/binkw32.dll in dll path")));
		ADDFMT((ResStr(IDS_AG_RATDVD_FILE),		_T("ratdvd"),_T("ratdvd"), iconIndex++, false, _T("ratdvd media file")));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_21),	_T("roq"),	_T("roq"), iconIndex++, false));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_22),	_T("rm"),	_T("rm ram rpm rmm"), iconIndex++, false, _T("RealPlayer or Real Alternative"), RealMedia));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_23),	_T("ra"),	_T("ra"), iconIndex++, true, _T("RealPlayer or Real Alternative"), RealMedia));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_24),	_T("rt"),	_T("rt rp smi smil"), iconIndex++, false, _T("RealPlayer or Real Alternative"), RealMedia));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_25),	_T("drc"),	_T("drc"), iconIndex++, false));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_26),	_T("dsm"),	_T("dsm dsv dsa dss"), iconIndex++));
		ADDFMT((ResStr(IDS_AG_MUSEPACK_FILE),	_T("mpc"),	_T("mpc"), iconIndex++, true));
		ADDFMT((_T("FLAC Audio file"),        _T("flac"),	_T("flac"), iconIndex++, true));
		ADDFMT((_T("ALAC Audio file"),        _T("alac"),	_T("alac"), iconIndex++, true));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_28),	_T("flv"),	_T("flv"), iconIndex++));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_29),	_T("swf"),	_T("swf"), iconIndex++, false, _T("ShockWave ActiveX control"), ShockWave));
		ADDFMT((ResStr(IDS_MEDIAFORMATS_30),	_T("mov"),	_T("mov qt amr 3g2 3gp2"), iconIndex++, false, _T("QuickTime (Alternative)"), QuickTime));
		ADDFMT((ResStr(IDS_AG_IMAGE_FILE),		_T("jpeg"),	_T("jpeg jpg bmp gif pic png dib tiff tif"), iconIndex++));
		ADDFMT((ResStr(IDS_AG_PLAYLIST_FILE),	_T("pls"),	_T("asx m3u pls wvx wax wmx mpcpl"), iconIndex++));
		ADDFMT((ResStr(IDS_AG_OTHER),			_T("other"),_T("divx vp6 rmvb amv"), iconIndex++));
#undef ADDFMT

		m_iRtspHandler = (engine_t)AfxGetApp()->GetProfileInt(_T("FileFormats"), _T("RtspHandler"), (int)RealMedia);
		m_fRtspFileExtFirst = !!AfxGetApp()->GetProfileInt(_T("FileFormats"), _T("RtspFileExtFirst"), 1);
	}

	for(int i = 0; i < GetCount(); i++)
		GetAt(i).UpdateData(fSave);
}

engine_t CMediaFormats::GetRtspHandler(bool& fRtspFileExtFirst)
{
	fRtspFileExtFirst = m_fRtspFileExtFirst;
	return m_iRtspHandler;
}

void CMediaFormats::SetRtspHandler(engine_t e, bool fRtspFileExtFirst)
{
	m_iRtspHandler = e;
	m_fRtspFileExtFirst = fRtspFileExtFirst;
}

bool CMediaFormats::IsUsingEngine(CString path, engine_t e)
{
	return(GetEngine(path) == e);
}

engine_t CMediaFormats::GetEngine(CString path)
{
	path.Trim().MakeLower();

	if(!m_fRtspFileExtFirst && path.Find(_T("rtsp://")) == 0)
		return m_iRtspHandler;

	CString ext = CPath(path).GetExtension();
	ext.MakeLower();
	if(!ext.IsEmpty())
	{
		if(path.Find(_T("rtsp://")) == 0)
		{
			if(ext == _T(".ram") || ext == _T(".rm") || ext == _T(".ra"))
				return RealMedia;
			if(ext == _T(".qt") || ext == _T(".mov"))
				return QuickTime;
		}

		for(int i = 0; i < GetCount(); i++)
		{
			CMediaFormatCategory& mfc = GetAt(i);
			if(mfc.FindExt(ext))
				return mfc.GetEngineType();
		}
	}

	if(m_fRtspFileExtFirst && path.Find(_T("rtsp://")) == 0)
		return m_iRtspHandler;

	return DirectShow;
}

bool CMediaFormats::FindExt(CString ext, bool fAudioOnly)
{
	ext.TrimLeft(_T("."));

	if(!ext.IsEmpty())
	{
		for(int i = 0; i < GetCount(); i++)
		{
			CMediaFormatCategory& mfc = GetAt(i);
			if((!fAudioOnly || mfc.IsAudioOnly()) && mfc.FindExt(ext)) 
				return(true);
		}
	}

	return(false);
}

void CMediaFormats::GetFilter(CString& filter, CAtlArray<CString>& mask)
{
	CString		strTemp;

	filter += ResStr(IDS_MEDIAFORMATS_34);
	mask.Add(_T(""));

	for(int i = 0; i < GetCount(); i++) 
	{
		strTemp  = GetAt(i).GetFilter() + _T(";");;
		mask[0] += strTemp;
		filter  += strTemp;
	}
	mask[0].TrimRight(_T(";"));
	filter.TrimRight(_T(";"));
	filter += _T("|");

	for(int i = 0; i < GetCount(); i++)
	{
		CMediaFormatCategory& mfc = GetAt(i);
		filter += mfc.GetLabel() + _T("|" + GetAt(i).GetFilter() + _T("|"));
		mask.Add(mfc.GetFilter());
	}

	filter += ResStr(IDS_MEDIAFORMATS_35);
	mask.Add(_T("*.*"));

	filter += _T("|");
}

void CMediaFormats::GetAudioFilter(CString& filter, CAtlArray<CString>& mask)
{
	CString		strTemp;
	filter += ResStr(IDS_MEDIAFORMATS_36);
	mask.Add(_T(""));

	for(int i = 0; i < GetCount(); i++)
	{
		CMediaFormatCategory& mfc = GetAt(i);
		if(!mfc.IsAudioOnly() || mfc.GetEngineType() != DirectShow) continue;
		strTemp  = GetAt(i).GetFilter() + _T(";");
		mask[0] += strTemp;
		filter  += strTemp;
	}

	mask[0].TrimRight(_T(";"));
	filter.TrimRight(_T(";"));
	filter += _T("|");

	for(int i = 0; i < GetCount(); i++)
	{
		CMediaFormatCategory& mfc = GetAt(i);
		if(!mfc.IsAudioOnly() || mfc.GetEngineType() != DirectShow) continue;
		filter += mfc.GetLabel() + _T("|") + GetAt(i).GetFilter() + _T("|");
		mask.Add(mfc.GetFilter());
	}

	filter += ResStr(IDS_MEDIAFORMATS_35);
	mask.Add(_T("*.*"));

	filter += _T("|");
}
