shithub: aacenc

Download patch

ref: dafceb5d10544e890f75d4a044e32c71f1a3d33a
parent: 1edfbd1a0483ccceedb051d7b1748e23e0395897
author: menno <menno>
date: Wed Mar 14 06:58:56 EST 2001

New GUI application

diff: cannot open b/wingui/res//null: file does not exist: 'b/wingui/res//null' diff: cannot open b/wingui//null: file does not exist: 'b/wingui//null'
--- /dev/null
+++ b/wingui/.cvsignore
@@ -1,0 +1,8 @@
+*.ncb
+*.plg
+*.aps
+*.opt
+*.aac
+*.wav
+Release
+Debug
\ No newline at end of file
--- /dev/null
+++ b/wingui/AbstractJob.cpp
@@ -1,0 +1,28 @@
+// AbstractJob.cpp: implementation of the CAbstractJob class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "AbstractJob.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CAbstractJob::CAbstractJob()
+{
+
+}
+
+CAbstractJob::~CAbstractJob()
+{
+
+}
--- /dev/null
+++ b/wingui/AbstractJob.h
@@ -1,0 +1,33 @@
+// AbstractJob.h: interface for the CAbstractJob class.
+// Author: Torsten Landmann
+//
+// This is the base class for all job types
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ABSTRACTJOB_H__DFE38E74_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ABSTRACTJOB_H__DFE38E74_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "SupportedPropertyPagesData.h"
+
+class CAbstractJob  
+{
+public:
+	CAbstractJob();
+	virtual ~CAbstractJob();
+
+	virtual CSupportedPropertyPagesData GetSupportedPropertyPages() const=0;
+
+	// returns if the job was completely and successfully process
+	virtual bool ProcessJob() const=0;
+
+	// is used during the processing of the job to give the user a
+	// feedback what exactly is done; may use up to 3 lines
+	virtual CString GetDetailedDescriptionForStatusDialog() const=0;
+};
+
+#endif // !defined(AFX_ABSTRACTJOB_H__DFE38E74_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/AbstractPageCtrlContent.cpp
@@ -1,0 +1,44 @@
+// AbstractPageCtrlContent.cpp: implementation of the CAbstractPageCtrlContent class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "AbstractPageCtrlContent.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CAbstractPageCtrlContent::CAbstractPageCtrlContent():
+	m_b3rdStateContent(true)			// it's essential that this is initialized to true;
+										// otherwise changes could be commited from pages even
+										// if there had been detected errors
+{
+
+}
+
+CAbstractPageCtrlContent::~CAbstractPageCtrlContent()
+{
+
+}
+
+CAbstractPageCtrlContent& CAbstractPageCtrlContent::operator*=(
+	const CAbstractPageCtrlContent &oRight)
+{
+	if (Is3rdState()) return *this;		// 3rd state can't be left by multiplication operator
+
+	if (GetHashString()!=oRight.GetHashString())
+	{
+		SetIs3rdState(true);
+	}
+
+	return *this;
+}
--- /dev/null
+++ b/wingui/AbstractPageCtrlContent.h
@@ -1,0 +1,43 @@
+// AbstractPageCtrlContent.h: interface for the CAbstractPageCtrlContent class.
+// Author: Torsten Landmann
+//
+// This is the base class for classes that are able to hold a piece
+// of data from a property page; this is useful for "merging" the
+// data of several selected jobs so that differing data isn't overwritten
+// if not desired
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ABSTRACTPAGECTRLCONTENT_H__7B47B268_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ABSTRACTPAGECTRLCONTENT_H__7B47B268_0FF8_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CAbstractPageCtrlContent  
+{
+public:
+	CAbstractPageCtrlContent();
+	virtual ~CAbstractPageCtrlContent();
+
+	bool Is3rdState() const					{ return m_b3rdStateContent; }
+	void SetIs3rdState(bool b3rdState)		{ m_b3rdStateContent=b3rdState; }
+
+	// all derived classes must implement this method;
+	// it's important that identical hash strings always
+	// mean identical content - also across class boundries;
+	// that's why there is the following convention:
+	// classes return a string <class name>-<A>
+	// where <A> is the unique content in this object
+	virtual CString GetHashString() const=0;
+
+	// this operator connects the underlying objects so that
+	// the 3rd state flag is correctly kept track of
+	CAbstractPageCtrlContent& operator*=(const CAbstractPageCtrlContent &oRight);
+
+private:
+	bool m_b3rdStateContent;
+};
+
+#endif // !defined(AFX_ABSTRACTPAGECTRLCONTENT_H__7B47B268_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/AbstractPropertyPageContents.cpp
@@ -1,0 +1,27 @@
+// AbstractPropertyPageContents.cpp: implementation of the CAbstractPropertyPageContents class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "AbstractPropertyPageContents.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CAbstractPropertyPageContents::CAbstractPropertyPageContents()
+{
+
+}
+
+CAbstractPropertyPageContents::~CAbstractPropertyPageContents()
+{
+
+}
--- /dev/null
+++ b/wingui/AbstractPropertyPageContents.h
@@ -1,0 +1,21 @@
+// AbstractPropertyPageContents.h: interface for the CAbstractPropertyPageContents class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ABSTRACTPROPERTYPAGECONTENTS_H__7B47B265_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ABSTRACTPROPERTYPAGECONTENTS_H__7B47B265_0FF8_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CAbstractPropertyPageContents  
+{
+public:
+	CAbstractPropertyPageContents();
+	virtual ~CAbstractPropertyPageContents();
+
+};
+
+#endif // !defined(AFX_ABSTRACTPROPERTYPAGECONTENTS_H__7B47B265_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/ConcreteJobBase.cpp
@@ -1,0 +1,28 @@
+// ConcreteJobBase.cpp: implementation of the CConcreteJobBase class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "ConcreteJobBase.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CConcreteJobBase::CConcreteJobBase()
+{
+
+}
+
+CConcreteJobBase::~CConcreteJobBase()
+{
+
+}
--- /dev/null
+++ b/wingui/ConcreteJobBase.h
@@ -1,0 +1,28 @@
+// ConcreteJobBase.h: interface for the CConcreteJobBase class.
+// Author: Torsten Landmann
+//
+// just a helper to simplify the class hierarchy
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CONCRETEJOBBASE_H__442115CF_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_CONCRETEJOBBASE_H__442115CF_0FD4_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "JobListCtrlDescribable.h"
+#include "AbstractJob.h"
+#include "FileSerializable.h"
+
+class CConcreteJobBase : public CJobListCtrlDescribable,  public CAbstractJob,
+							public CFileSerializable
+{
+public:
+	CConcreteJobBase();
+	virtual ~CConcreteJobBase();
+
+};
+
+#endif // !defined(AFX_CONCRETEJOBBASE_H__442115CF_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/EncoderGeneralPageDialog.cpp
@@ -1,0 +1,495 @@
+// EncoderGeneralPageDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "EncoderGeneralPageDialog.h"
+#include "EncoderGeneralPropertyPageContents.h"
+#include "FolderDialog.h"
+#include "FilePathCalc.h"
+#include "FileMaskAssembler.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderGeneralPageDialog dialog
+
+
+CEncoderGeneralPageDialog::CEncoderGeneralPageDialog(
+	const TItemList<CJob*> &oJobsToConfigure,
+	CJobListUpdatable *poListContainer,
+	CWnd* pParent /*=NULL*/):
+	m_bInitialized(false),
+	m_oJobsToConfigure(oJobsToConfigure),
+	m_poListContainer(poListContainer),
+	m_eCurCheckBox(eNone),
+	m_bIgnoreUpdates(false)
+{
+	//{{AFX_DATA_INIT(CEncoderGeneralPageDialog)
+	m_oEditSourceDir = _T("");
+	m_oEditSourceFile = _T("");
+	m_oEditTargetDir = _T("");
+	m_oEditTargetFile = _T("");
+	//}}AFX_DATA_INIT
+
+	Create(CEncoderGeneralPageDialog::IDD, pParent);
+}
+
+CEncoderGeneralPageDialog::~CEncoderGeneralPageDialog()
+{
+	UpdateJobs();
+}
+
+void CEncoderGeneralPageDialog::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CEncoderGeneralPageDialog)
+	DDX_Control(pDX, IDC_CHECKRECURSIVE, m_ctrlCheckRecursive);
+	DDX_Control(pDX, IDC_BUTTONBROWSETARGETFILE, m_ctrlButtonBrowseTargetFile);
+	DDX_Control(pDX, IDC_BUTTONBROWSESOURCEFILE, m_ctrlButtonBrowseSourceFile);
+	DDX_Text(pDX, IDC_EDITSOURCEDIR, m_oEditSourceDir);
+	DDX_Text(pDX, IDC_EDITSOURCEFILE, m_oEditSourceFile);
+	DDX_Text(pDX, IDC_EDITTARGETDIR, m_oEditTargetDir);
+	DDX_Text(pDX, IDC_EDITTARGETFILE, m_oEditTargetFile);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CEncoderGeneralPageDialog, CDialog)
+	//{{AFX_MSG_MAP(CEncoderGeneralPageDialog)
+	ON_EN_KILLFOCUS(IDC_EDITSOURCEDIR, OnKillfocusEditSourceDir)
+	ON_EN_KILLFOCUS(IDC_EDITSOURCEFILE, OnKillfocusEditSourceFile)
+	ON_EN_KILLFOCUS(IDC_EDITTARGETDIR, OnKillfocusEditTargetDir)
+	ON_EN_KILLFOCUS(IDC_EDITTARGETFILE, OnKillfocusEditTargetFile)
+	ON_BN_CLICKED(IDC_BUTTONBROWSESOURCEDIR, OnButtonBrowseSourceDir)
+	ON_BN_CLICKED(IDC_BUTTONBROWSETARGETDIR, OnButtonBrowseTargetDir)
+	ON_BN_CLICKED(IDC_BUTTONBROWSESOURCEFILE, OnButtoBrowseSourceFile)
+	ON_BN_CLICKED(IDC_BUTTONBROWSETARGETFILE, OnButtonBrowseTargetFile)
+	ON_EN_CHANGE(IDC_EDITSOURCEFILE, OnChangeEditSourceFile)
+	ON_BN_CLICKED(IDC_CHECKRECURSIVE, OnCheckRecursive)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderGeneralPageDialog message handlers
+
+BOOL CEncoderGeneralPageDialog::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	// TODO: Add extra initialization here
+	m_bInitialized=true;
+
+	if (m_oJobsToConfigure.GetNumber()>1)
+	{
+		// have several jobs
+		//m_ctrlButtonBrowseSourceFile.ShowWindow(SW_HIDE);
+		m_ctrlButtonBrowseTargetFile.ShowWindow(SW_HIDE);
+	}
+
+	// show our contents
+	ApplyPageContents(ParseJobs());
+
+	// not appropriate here (also ApplyPageContents() has done the job anyway)
+	//OnChangeEditSourceFile();
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+bool CEncoderGeneralPageDialog::GetPageContents(CEncoderGeneralPropertyPageContents &oTarget)
+{
+	if (!UpdateData(TRUE)) return false;
+
+	oTarget.m_oSourceDirectory.SetContent(m_oEditSourceDir);
+	oTarget.m_oSourceFile.SetContent(m_oEditSourceFile);
+	oTarget.m_oTargetDirectory.SetContent(m_oEditTargetDir);
+	oTarget.m_oTargetFile.SetContent(m_oEditTargetFile);
+	oTarget.m_oSourceFileFilterIsRecursive.SetCheckCode(m_ctrlCheckRecursive.GetCheck());
+
+	// not relevant
+	oTarget.m_oSourceFilterRecursiveCheckboxVisible.SetIs3rdState(true);
+
+	return true;
+}
+
+void CEncoderGeneralPageDialog::ApplyPageContents(const CEncoderGeneralPropertyPageContents &oPageContents)
+{
+	// disabled since it could cause error messages - we're overwriting everything anyway
+	//UpdateData(TRUE);
+
+	m_oEditSourceDir=oPageContents.m_oSourceDirectory.GetContent();
+	m_oEditSourceFile=oPageContents.m_oSourceFile.GetContent();
+	m_oEditTargetDir=oPageContents.m_oTargetDirectory.GetContent();
+	m_oEditTargetFile=oPageContents.m_oTargetFile.GetContent();
+	oPageContents.m_oSourceFileFilterIsRecursive.ApplyCheckCodeToButton(&m_ctrlCheckRecursive);
+
+	if (m_bInitialized)
+	{
+		UpdateData(FALSE);
+
+		if (m_oEditSourceFile.IsEmpty())
+		{
+			if (!oPageContents.m_oSourceFilterRecursiveCheckboxVisible.Is3rdState() &&
+				oPageContents.m_oSourceFilterRecursiveCheckboxVisible.GetCheckMark())
+			{
+				m_ctrlCheckRecursive.ShowWindow(SW_SHOW);
+			}
+			else
+			{
+				m_ctrlCheckRecursive.ShowWindow(SW_HIDE);
+			}
+		}
+		else
+		{
+			OnChangeEditSourceFile();
+		}
+	}
+}
+
+CEncoderGeneralPropertyPageContents CEncoderGeneralPageDialog::ParseJobs()
+{
+	CEncoderGeneralPropertyPageContents oToReturn;
+	bool bFirstRun=true;
+
+	CBListReader oReader(m_oJobsToConfigure);
+	CJob *poCurJob;
+	while (m_oJobsToConfigure.GetNextElemContent(oReader, poCurJob))
+	{
+		if (!poCurJob->GetJobType()==CJob::eEncoderJob)
+		{
+			// must all be encoder jobs
+			ASSERT(false);
+		}
+		CEncoderJob *poEncoderJob=poCurJob->GetEncoderJob();
+		if (bFirstRun)
+		{
+			oToReturn=poEncoderJob->GetGeneralPageContents();
+			bFirstRun=false;
+		}
+		else
+		{
+			oToReturn*=poEncoderJob->GetGeneralPageContents();
+		}
+	}
+
+	return oToReturn;
+}
+
+void CEncoderGeneralPageDialog::ModifyJobs(const CEncoderGeneralPropertyPageContents &oPageContents)
+{
+	CBListReader oReader(m_oJobsToConfigure);
+	CJob *poCurJob;
+	while (m_oJobsToConfigure.GetNextElemContent(oReader, poCurJob))
+	{
+		if (!poCurJob->GetJobType()==CJob::eEncoderJob)
+		{
+			// must all be encoder jobs
+			ASSERT(false);
+		}
+		CEncoderJob *poEncoderJob=poCurJob->GetEncoderJob();
+		poEncoderJob->ApplyGeneralPageContents(oPageContents);
+	}
+}
+
+void CEncoderGeneralPageDialog::UpdateJobs(bool bFinishCheckBoxSessions, bool bDlgDestructUpdate)
+{
+	if (::IsWindow(*this) && !m_bIgnoreUpdates)
+	{
+		CEncoderGeneralPropertyPageContents oPageContents;
+		if (GetPageContents(oPageContents))
+		{
+			if (bFinishCheckBoxSessions)
+			{
+				FinishCurrentCheckBoxSessionIfNecessary();
+			}
+
+			ModifyJobs(oPageContents);
+
+			// make changes visible
+			m_poListContainer->ReFillInJobListCtrl();
+		}
+	}
+
+	if (bDlgDestructUpdate)
+	{
+		m_bIgnoreUpdates=true;
+	}
+}
+
+void CEncoderGeneralPageDialog::OnKillfocusEditSourceDir() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderGeneralPageDialog::OnKillfocusEditSourceFile() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderGeneralPageDialog::OnKillfocusEditTargetDir() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderGeneralPageDialog::OnKillfocusEditTargetFile() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderGeneralPageDialog::OnButtonBrowseSourceDir() 
+{
+	CString oCaption;
+	oCaption.LoadString(IDS_SelectSourceDirDlgCaption);
+	CFolderDialog oFolderDialog(this, oCaption);
+	if (oFolderDialog.DoModal()==IDOK)
+	{
+		UpdateData(TRUE);
+		m_oEditSourceDir=oFolderDialog.m_oFolderPath;
+		CFilePathCalc::MakePath(m_oEditSourceDir);
+		UpdateData(FALSE);
+		UpdateJobs();
+	}
+	else
+	{
+		if (oFolderDialog.m_bError)
+		{
+			AfxMessageBox(IDS_ErrorDuringDirectorySelection);
+		}
+	}
+}
+
+void CEncoderGeneralPageDialog::OnButtonBrowseTargetDir() 
+{
+	CString oCaption;
+	oCaption.LoadString(IDS_SelectTargetDirDlgCaption);
+	CFolderDialog oFolderDialog(this, oCaption);
+	if (oFolderDialog.DoModal()==IDOK)
+	{
+		UpdateData(TRUE);
+		m_oEditTargetDir=oFolderDialog.m_oFolderPath;
+		CFilePathCalc::MakePath(m_oEditTargetDir);
+		UpdateData(FALSE);
+		UpdateJobs();
+	}
+	else
+	{
+		if (oFolderDialog.m_bError)
+		{
+			AfxMessageBox(IDS_ErrorDuringDirectorySelection);
+		}
+	}
+}
+
+void CEncoderGeneralPageDialog::OnButtoBrowseSourceFile() 
+{
+	UpdateData(TRUE);
+	// determine the standard file
+	CString *poStandardFile=0;
+	if (!(m_oEditSourceFile.IsEmpty() || m_oEditSourceDir.IsEmpty()))
+	{
+		poStandardFile=new CString(m_oEditSourceDir+m_oEditSourceFile);
+	}
+
+	// assemble the filter string
+	CString oFilter;
+	{
+		// assemble a list of allowed filters
+		TItemList<int> oFilters;
+		oFilters.AddNewElem(IDS_WavFilesFilter, 1);
+		oFilters.AddNewElem(IDS_AllFilesFilter, 2);
+		oFilter=CFileMaskAssembler::GetFileMask(oFilters);
+	}
+
+	// find out the default extension
+	CString oDefaultExt;
+	oDefaultExt.LoadString(IDS_EndSourceFileStandardExtension);
+
+	CFileDialog oOpenDialog(
+		TRUE,										// file open mode
+		oDefaultExt,								// default extension
+		(poStandardFile!=0 ? *poStandardFile : (LPCTSTR)0),	// default file
+		OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
+		oFilter);
+	if (oOpenDialog.DoModal()==IDOK)
+	{
+		// the file has been opened
+		CString oFilePath(oOpenDialog.GetPathName());
+		m_oEditSourceDir=oFilePath;
+		CFilePathCalc::MakePath(m_oEditSourceDir);
+		CFilePathCalc::ExtractFileName(oFilePath, m_oEditSourceFile);
+	}
+	else
+	{
+		// user abort or error
+		if (CommDlgExtendedError()!=0)
+		{
+			// an error occured
+			AfxMessageBox(IDS_ErrorDuringFileSelection);
+		}
+	}
+
+	UpdateData(FALSE);
+	UpdateJobs();
+	OnChangeEditSourceFile();
+}
+
+void CEncoderGeneralPageDialog::OnButtonBrowseTargetFile() 
+{
+	UpdateData(TRUE);
+	// determine the standard file
+	CString *poStandardFile=0;
+	if (!(m_oEditTargetFile.IsEmpty() || m_oEditTargetDir.IsEmpty()))
+	{
+		poStandardFile=new CString(m_oEditTargetDir+m_oEditTargetFile);
+	}
+
+	// assemble the filter string
+	CString oFilter;
+	{
+		// assemble a list of allowed filters
+		TItemList<int> oFilters;
+		oFilters.AddNewElem(IDS_AacFilesFilter, 1);
+		oFilters.AddNewElem(IDS_AllFilesFilter, 2);
+		oFilter=CFileMaskAssembler::GetFileMask(oFilters);
+	}
+
+	// find out the default extension
+	CString oDefaultExt;
+	oDefaultExt.LoadString(IDS_EndTargetFileStandardExtension);
+
+	CFileDialog oOpenDialog(
+		FALSE,										// file save mode
+		oDefaultExt,								// default extension
+		(poStandardFile!=0 ? *poStandardFile : (LPCTSTR)0),	// default file
+		OFN_HIDEREADONLY,
+		oFilter);
+	if (oOpenDialog.DoModal()==IDOK)
+	{
+		// the file has been opened
+		CString oFilePath(oOpenDialog.GetPathName());
+		m_oEditTargetDir=oFilePath;
+		CFilePathCalc::MakePath(m_oEditTargetDir);
+		CFilePathCalc::ExtractFileName(oFilePath, m_oEditTargetFile);
+	}
+	else
+	{
+		// user abort or error
+		if (CommDlgExtendedError()!=0)
+		{
+			// an error occured
+			AfxMessageBox(IDS_ErrorDuringFileSelection);
+		}
+	}
+
+	UpdateData(FALSE);
+	UpdateJobs();
+	OnChangeEditSourceFile();
+}
+
+
+void CEncoderGeneralPageDialog::OnChangeEditSourceFile() 
+{
+	// TODO: If this is a RICHEDIT control, the control will not
+	// send this notification unless you override the CDialog::OnInitDialog()
+	// function and call CRichEditCtrl().SetEventMask()
+	// with the ENM_CHANGE flag ORed into the mask.
+	
+	// TODO: Add your control notification handler code here
+	UpdateData(TRUE);
+
+	// check for a filter
+	if (CFilePathCalc::IsValidFileMask(m_oEditSourceFile))
+	{
+		// user entered a filter
+		m_ctrlCheckRecursive.ShowWindow(SW_SHOW);
+	}
+	else
+	{
+		// user did not enter a filter
+		m_ctrlCheckRecursive.ShowWindow(SW_HIDE);
+	}
+
+	UpdateData(FALSE);
+}
+
+
+void CEncoderGeneralPageDialog::ProcessCheckBoxClick(CButton *poCheckBox, ETypeOfCheckBox eTypeOfCheckBox)
+{
+	int iCheckState=poCheckBox->GetCheck();
+	if (iCheckState==2)
+	{
+		// 3rd state
+		if (m_eCurCheckBox!=eTypeOfCheckBox)
+		{
+			// must not be like this
+			ASSERT(false);
+		}
+		else
+		{
+			m_oCheckStateChangeStateSaver.RestoreJobs(m_oJobsToConfigure);
+			FinishCurrentCheckBoxSessionIfNecessary();
+		}
+	}
+	else
+	{
+		if (m_eCurCheckBox!=eTypeOfCheckBox)
+		{
+			FinishCurrentCheckBoxSessionIfNecessary();
+		
+			// current checkbox is now set to eNone
+
+			m_eCurCheckBox=eTypeOfCheckBox;
+
+			m_oCheckStateChangeStateSaver.SaveJobs(m_oJobsToConfigure);
+		}
+	}
+
+	UpdateJobs(false);
+}
+
+void CEncoderGeneralPageDialog::FinishCurrentCheckBoxSessionIfNecessary()
+{
+	switch (m_eCurCheckBox)
+	{
+	case eRecursive:
+		{
+			FinishCheckBoxSessionIfNecessary(&m_ctrlCheckRecursive);
+			break;
+		}
+	case eNone:
+		{
+			// nothing
+			break;
+		}
+	default:
+		{
+			// unkown type of check box
+			break;
+		}
+	}
+	m_eCurCheckBox=eNone;
+}
+
+void CEncoderGeneralPageDialog::FinishCheckBoxSessionIfNecessary(CButton *poCheckBox)
+{
+	int iCurCheck=poCheckBox->GetCheck();
+	if (iCurCheck<2)
+	{
+		poCheckBox->SetButtonStyle(BS_AUTOCHECKBOX);
+	}
+}
+
+void CEncoderGeneralPageDialog::OnCheckRecursive() 
+{
+	// TODO: Add your control notification handler code here
+	ProcessCheckBoxClick(&m_ctrlCheckRecursive, eRecursive);
+}
--- /dev/null
+++ b/wingui/EncoderGeneralPageDialog.h
@@ -1,0 +1,99 @@
+#if !defined(AFX_ENCODERGENERALPAGEDIALOG_H__442115C6_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ENCODERGENERALPAGEDIALOG_H__442115C6_0FD4_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// EncoderGeneralPageDialog.h : header file
+//
+
+#include "JobListUpdatable.h"
+#include "JobListsToConfigureSaver.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderGeneralPageDialog dialog
+
+class CEncoderGeneralPageDialog : public CDialog
+{
+// Construction
+public:
+	CEncoderGeneralPageDialog(const TItemList<CJob*> &oJobsToConfigure, CJobListUpdatable *poListContainer, CWnd* pParent = NULL);   // standard constructor
+	virtual ~CEncoderGeneralPageDialog();
+
+// Dialog Data
+	//{{AFX_DATA(CEncoderGeneralPageDialog)
+	enum { IDD = IDD_ENCODERGENERALPAGEDIALOG };
+	CButton	m_ctrlCheckRecursive;
+	CButton	m_ctrlButtonBrowseTargetFile;
+	CButton	m_ctrlButtonBrowseSourceFile;
+	CString	m_oEditSourceDir;
+	CString	m_oEditSourceFile;
+	CString	m_oEditTargetDir;
+	CString	m_oEditTargetFile;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CEncoderGeneralPageDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+public:
+	// returns false in case of errors
+	bool GetPageContents(CEncoderGeneralPropertyPageContents &oTarget);
+	void ApplyPageContents(const CEncoderGeneralPropertyPageContents &oPageContents);
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CEncoderGeneralPageDialog)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnKillfocusEditSourceDir();
+	afx_msg void OnKillfocusEditSourceFile();
+	afx_msg void OnKillfocusEditTargetDir();
+	afx_msg void OnKillfocusEditTargetFile();
+	afx_msg void OnButtonBrowseSourceDir();
+	afx_msg void OnButtonBrowseTargetDir();
+	afx_msg void OnButtoBrowseSourceFile();
+	afx_msg void OnButtonBrowseTargetFile();
+	afx_msg void OnChangeEditSourceFile();
+	afx_msg void OnCheckRecursive();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+private:
+	bool m_bInitialized;
+
+	TItemList<CJob*> m_oJobsToConfigure;
+
+	CJobListUpdatable *m_poListContainer;
+
+	CEncoderGeneralPropertyPageContents ParseJobs();
+	void ModifyJobs(const CEncoderGeneralPropertyPageContents &oPageContents);
+
+
+	// called when changes have been made in the dialog and are to
+	// be synchronized with both "data holders"
+	void UpdateJobs(bool bFinishCheckBoxSessions=true, bool bDlgDestructUpdate=false);
+	bool m_bIgnoreUpdates;
+
+	// these members are used for managing the check box controls and the
+	// changes that are made with them in the dialog
+	enum ETypeOfCheckBox
+	{
+		eNone,
+		eRecursive,
+	} m_eCurCheckBox;
+	CJobListsToConfigureSaver m_oCheckStateChangeStateSaver;
+	void ProcessCheckBoxClick(CButton *poCheckBox, ETypeOfCheckBox eTypeOfCheckBox);
+	void FinishCurrentCheckBoxSessionIfNecessary();
+	void FinishCheckBoxSessionIfNecessary(CButton *poCheckBox);
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ENCODERGENERALPAGEDIALOG_H__442115C6_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/EncoderGeneralPropertyPageContents.cpp
@@ -1,0 +1,47 @@
+// EncoderGeneralPropertyPageContents.cpp: implementation of the CEncoderGeneralPropertyPageContents class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "EncoderGeneralPropertyPageContents.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CEncoderGeneralPropertyPageContents::CEncoderGeneralPropertyPageContents()
+{
+
+}
+
+CEncoderGeneralPropertyPageContents::CEncoderGeneralPropertyPageContents(const CEncoderGeneralPropertyPageContents &oSource)
+{
+	*this=oSource;
+}
+
+CEncoderGeneralPropertyPageContents::~CEncoderGeneralPropertyPageContents()
+{
+
+}
+
+CEncoderGeneralPropertyPageContents& CEncoderGeneralPropertyPageContents::operator*=(
+	const CEncoderGeneralPropertyPageContents &oRight)
+{
+	m_oSourceDirectory*=oRight.m_oSourceDirectory;
+	m_oSourceFile*=oRight.m_oSourceFile;
+	m_oTargetDirectory*=oRight.m_oTargetDirectory;
+	m_oTargetFile*=oRight.m_oTargetFile;
+	m_oSourceFileFilterIsRecursive*=oRight.m_oSourceFileFilterIsRecursive;
+
+	m_oSourceFilterRecursiveCheckboxVisible*=oRight.m_oSourceFilterRecursiveCheckboxVisible;
+
+	return *this;
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/EncoderGeneralPropertyPageContents.h
@@ -1,0 +1,40 @@
+// EncoderGeneralPropertyPageContents.h: interface for the CEncoderGeneralPropertyPageContents class.
+// Author: Torsten Landmann
+//
+// encapsulates the content of the property page "general" including
+// possible 3rd states of all controls
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ENCODERGENERALPROPERTYPAGECONTENTS_H__7B47B266_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ENCODERGENERALPROPERTYPAGECONTENTS_H__7B47B266_0FF8_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "AbstractPropertyPageContents.h"
+#include "PageEditCtrlContent.h"
+#include "PageCheckboxCtrlContent.h"
+
+class CEncoderGeneralPropertyPageContents : public CAbstractPropertyPageContents  
+{
+public:
+	CEncoderGeneralPropertyPageContents();
+	CEncoderGeneralPropertyPageContents(const CEncoderGeneralPropertyPageContents &oSource);	// copy constructor
+	virtual ~CEncoderGeneralPropertyPageContents();
+
+	CPageEditCtrlContent m_oSourceDirectory;
+	CPageEditCtrlContent m_oSourceFile;
+	CPageEditCtrlContent m_oTargetDirectory;
+	CPageEditCtrlContent m_oTargetFile;
+	CPageCheckboxCtrlContent m_oSourceFileFilterIsRecursive;
+
+	// not represented by real controls; just a tracker
+	CPageCheckboxCtrlContent m_oSourceFilterRecursiveCheckboxVisible;
+
+	// with this operator pages for several jobs can be "merged"
+	CEncoderGeneralPropertyPageContents& operator*=(const CEncoderGeneralPropertyPageContents &oRight);
+};
+
+#endif // !defined(AFX_ENCODERGENERALPROPERTYPAGECONTENTS_H__7B47B266_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/EncoderId3PageDialog.cpp
@@ -1,0 +1,381 @@
+// EncoderId3PageDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "EncoderId3PageDialog.h"
+#include "WindowUtil.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderId3PageDialog dialog
+
+
+CEncoderId3PageDialog::CEncoderId3PageDialog(
+	const TItemList<CJob*> &oJobsToConfigure,
+	CJobListUpdatable *poListContainer,
+	CWnd* pParent /*=NULL*/):
+	m_bInitialized(false),
+	m_oJobsToConfigure(oJobsToConfigure),
+	m_poListContainer(poListContainer),
+	m_eCurCheckBox(eNone),
+	m_bIgnoreUpdates(false)
+{
+	//{{AFX_DATA_INIT(CEncoderId3PageDialog)
+	m_oEditAlbum = _T("");
+	m_oEditArtist = _T("");
+	m_oEditComment = _T("");
+	m_oEditComposer = _T("");
+	m_oEditEncodedBy = _T("");
+	m_oEditOriginalArtist = _T("");
+	m_oEditTitle = _T("");
+	m_oEditTrack = _T("");
+	m_oEditUrl = _T("");
+	m_oEditYear = _T("");
+	//}}AFX_DATA_INIT
+
+	Create(CEncoderId3PageDialog::IDD, pParent);
+}
+
+CEncoderId3PageDialog::~CEncoderId3PageDialog()
+{
+	UpdateJobs();
+}
+
+
+void CEncoderId3PageDialog::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CEncoderId3PageDialog)
+	DDX_Control(pDX, IDC_EDITYEAR, m_ctrlEditYear);
+	DDX_Control(pDX, IDC_EDITTRACK, m_ctrlEditTrack);
+	DDX_Control(pDX, IDC_COMBOGENRE, m_ctrlComboGenre);
+	DDX_Control(pDX, IDC_CHECKCOPYRIGHT, m_ctrlCheckCopyright);
+	DDX_Text(pDX, IDC_EDITALBUM, m_oEditAlbum);
+	DDX_Text(pDX, IDC_EDITARTIST, m_oEditArtist);
+	DDX_Text(pDX, IDC_EDITCOMMENT, m_oEditComment);
+	DDX_Text(pDX, IDC_EDITCOMPOSER, m_oEditComposer);
+	DDX_Text(pDX, IDC_EDITENCODEDBY, m_oEditEncodedBy);
+	DDX_Text(pDX, IDC_EDITORIGINALARTIST, m_oEditOriginalArtist);
+	DDX_Text(pDX, IDC_EDITTITLE, m_oEditTitle);
+	DDX_Text(pDX, IDC_EDITTRACK, m_oEditTrack);
+	DDX_Text(pDX, IDC_EDITURL, m_oEditUrl);
+	DDX_Text(pDX, IDC_EDITYEAR, m_oEditYear);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CEncoderId3PageDialog, CDialog)
+	//{{AFX_MSG_MAP(CEncoderId3PageDialog)
+	ON_CBN_KILLFOCUS(IDC_COMBOGENRE, OnKillfocusComboGenre)
+	ON_EN_KILLFOCUS(IDC_EDITALBUM, OnKillfocusEditAlbum)
+	ON_EN_KILLFOCUS(IDC_EDITARTIST, OnKillfocusEditArtist)
+	ON_EN_KILLFOCUS(IDC_EDITCOMMENT, OnKillfocusEditComment)
+	ON_EN_KILLFOCUS(IDC_EDITCOMPOSER, OnKillfocusEditComposer)
+	ON_EN_KILLFOCUS(IDC_EDITENCODEDBY, OnKillfocusEditEncodedBy)
+	ON_EN_KILLFOCUS(IDC_EDITORIGINALARTIST, OnKillfocusEditOriginalArtist)
+	ON_EN_KILLFOCUS(IDC_EDITTITLE, OnKillfocusEditTitle)
+	ON_EN_KILLFOCUS(IDC_EDITTRACK, OnKillfocusEditTrack)
+	ON_EN_KILLFOCUS(IDC_EDITURL, OnKillfocusEditUrl)
+	ON_EN_KILLFOCUS(IDC_EDITYEAR, OnKillfocusEditYear)
+	ON_BN_CLICKED(IDC_CHECKCOPYRIGHT, OnCheckCopyright)
+	ON_EN_UPDATE(IDC_EDITTRACK, OnUpdateEditTrack)
+	ON_EN_UPDATE(IDC_EDITYEAR, OnUpdateEditYear)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderId3PageDialog message handlers
+
+BOOL CEncoderId3PageDialog::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	// TODO: Add extra initialization here
+	m_bInitialized=true;
+
+	// show our contents
+	ApplyPageContents(ParseJobs());
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+bool CEncoderId3PageDialog::GetPageContents(CEncoderId3PropertyPageContents &oTarget)
+{
+	if (!UpdateData(TRUE)) return false;
+
+	oTarget.m_oArtist.SetContent(m_oEditArtist);
+	oTarget.m_oTrackNo.SetContent(m_oEditTrack);
+	oTarget.m_oAlbum.SetContent(m_oEditAlbum);
+	oTarget.m_oYear.SetContent(m_oEditYear);
+	oTarget.m_oTitle.SetContent(m_oEditTitle);
+	oTarget.m_oCopyright.SetCheckCode(m_ctrlCheckCopyright.GetCheck());
+	oTarget.m_oOriginalArtist.SetContent(m_oEditOriginalArtist);
+	oTarget.m_oComposer.SetContent(m_oEditComposer);
+	oTarget.m_oUrl.SetContent(m_oEditUrl);
+	oTarget.m_oGenre.SetCurComboBoxSelectionText(&m_ctrlComboGenre);
+	oTarget.m_oEncodedBy.SetContent(m_oEditEncodedBy);
+	oTarget.m_oComment.SetContent(m_oEditComment);
+
+	return true;
+}
+
+void CEncoderId3PageDialog::ApplyPageContents(const CEncoderId3PropertyPageContents &oPageContents)
+{
+	// disabled since it could cause error messages - we're overwriting everything anyway
+	//UpdateData(TRUE);
+
+	m_oEditArtist=oPageContents.m_oArtist.GetContent();
+	m_oEditTrack=oPageContents.m_oTrackNo.GetContent();
+	m_oEditAlbum=oPageContents.m_oAlbum.GetContent();
+	m_oEditYear=oPageContents.m_oYear.GetContent();
+	m_oEditTitle=oPageContents.m_oTitle.GetContent();
+	oPageContents.m_oCopyright.ApplyCheckCodeToButton(&m_ctrlCheckCopyright);
+	m_oEditOriginalArtist=oPageContents.m_oOriginalArtist.GetContent();
+	m_oEditComposer=oPageContents.m_oComposer.GetContent();
+	m_oEditUrl=oPageContents.m_oUrl.GetContent();
+	oPageContents.m_oGenre.ApplyToComboBoxPointer(&m_ctrlComboGenre);
+	m_oEditEncodedBy=oPageContents.m_oEncodedBy.GetContent();
+	m_oEditComment=oPageContents.m_oComment.GetContent();
+
+	if (m_bInitialized)
+	{
+		UpdateData(FALSE);
+	}
+}
+
+CEncoderId3PropertyPageContents CEncoderId3PageDialog::ParseJobs()
+{
+	CEncoderId3PropertyPageContents oToReturn;
+	bool bFirstRun=true;
+
+	CBListReader oReader(m_oJobsToConfigure);
+	CJob *poCurJob;
+	while (m_oJobsToConfigure.GetNextElemContent(oReader, poCurJob))
+	{
+		if (!poCurJob->GetJobType()==CJob::eEncoderJob)
+		{
+			// must all be encoder jobs
+			ASSERT(false);
+		}
+		CEncoderJob *poEncoderJob=poCurJob->GetEncoderJob();
+		if (bFirstRun)
+		{
+			oToReturn=poEncoderJob->GetId3PageContents();
+			bFirstRun=false;
+		}
+		else
+		{
+			oToReturn*=poEncoderJob->GetId3PageContents();
+		}
+	}
+
+	return oToReturn;
+}
+
+void CEncoderId3PageDialog::ModifyJobs(const CEncoderId3PropertyPageContents &oPageContents)
+{
+	CBListReader oReader(m_oJobsToConfigure);
+	CJob *poCurJob;
+	while (m_oJobsToConfigure.GetNextElemContent(oReader, poCurJob))
+	{
+		if (!poCurJob->GetJobType()==CJob::eEncoderJob)
+		{
+			// must all be encoder jobs
+			ASSERT(false);
+		}
+		CEncoderJob *poEncoderJob=poCurJob->GetEncoderJob();
+		poEncoderJob->ApplyId3PageContents(oPageContents);
+	}
+}
+
+void CEncoderId3PageDialog::UpdateJobs(bool bFinishCheckBoxSessions, bool bDlgDestructUpdate)
+{
+	if (::IsWindow(*this) && !m_bIgnoreUpdates)
+	{
+		CEncoderId3PropertyPageContents oPageContents;
+		if (GetPageContents(oPageContents))
+		{
+			if (bFinishCheckBoxSessions)
+			{
+				FinishCurrentCheckBoxSessionIfNecessary();
+			}
+
+			ModifyJobs(oPageContents);
+
+			// make changes visible
+			m_poListContainer->ReFillInJobListCtrl();
+		}
+	}
+
+	if (bDlgDestructUpdate)
+	{
+		m_bIgnoreUpdates=true;
+	}
+}
+
+void CEncoderId3PageDialog::OnKillfocusComboGenre() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditAlbum() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditArtist() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditComment() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditComposer() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditEncodedBy() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditOriginalArtist() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditTitle() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditTrack() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditUrl() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnKillfocusEditYear() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderId3PageDialog::OnCheckCopyright() 
+{
+	// TODO: Add your control notification handler code here
+	ProcessCheckBoxClick(&m_ctrlCheckCopyright, eCopyright);
+}
+
+void CEncoderId3PageDialog::ProcessCheckBoxClick(CButton *poCheckBox, ETypeOfCheckBox eTypeOfCheckBox)
+{
+	int iCheckState=poCheckBox->GetCheck();
+	if (iCheckState==2)
+	{
+		// 3rd state
+		if (m_eCurCheckBox!=eTypeOfCheckBox)
+		{
+			// must not be like this
+			ASSERT(false);
+		}
+		else
+		{
+			m_oCheckStateChangeStateSaver.RestoreJobs(m_oJobsToConfigure);
+			FinishCurrentCheckBoxSessionIfNecessary();
+		}
+	}
+	else
+	{
+		if (m_eCurCheckBox!=eTypeOfCheckBox)
+		{
+			FinishCurrentCheckBoxSessionIfNecessary();
+		
+			// current checkbox is now set to eNone
+
+			m_eCurCheckBox=eTypeOfCheckBox;
+
+			m_oCheckStateChangeStateSaver.SaveJobs(m_oJobsToConfigure);
+		}
+	}
+
+	UpdateJobs(false);
+}
+
+void CEncoderId3PageDialog::FinishCurrentCheckBoxSessionIfNecessary()
+{
+	switch (m_eCurCheckBox)
+	{
+	case eCopyright:
+		{
+			FinishCheckBoxSessionIfNecessary(&m_ctrlCheckCopyright);
+			break;
+		}
+	case eNone:
+		{
+			// nothing
+			break;
+		}
+	default:
+		{
+			// unkown type of check box
+			break;
+		}
+	}
+	m_eCurCheckBox=eNone;
+}
+
+void CEncoderId3PageDialog::FinishCheckBoxSessionIfNecessary(CButton *poCheckBox)
+{
+	int iCurCheck=poCheckBox->GetCheck();
+	if (iCurCheck<2)
+	{
+		poCheckBox->SetButtonStyle(BS_AUTOCHECKBOX);
+	}
+}
+
+void CEncoderId3PageDialog::OnUpdateEditTrack() 
+{
+	// TODO: If this is a RICHEDIT control, the control will not
+	// send this notification unless you override the CDialog::OnInitDialog()
+	// function to send the EM_SETEVENTMASK message to the control
+	// with the ENM_UPDATE flag ORed into the lParam mask.
+	
+	// TODO: Add your control notification handler code here
+	CWindowUtil::ForceNumericContent(&m_ctrlEditTrack, false);
+}
+
+void CEncoderId3PageDialog::OnUpdateEditYear() 
+{
+	// TODO: If this is a RICHEDIT control, the control will not
+	// send this notification unless you override the CDialog::OnInitDialog()
+	// function to send the EM_SETEVENTMASK message to the control
+	// with the ENM_UPDATE flag ORed into the lParam mask.
+	
+	// TODO: Add your control notification handler code here
+	CWindowUtil::ForceNumericContent(&m_ctrlEditYear, false);
+}
--- /dev/null
+++ b/wingui/EncoderId3PageDialog.h
@@ -1,0 +1,108 @@
+#if !defined(AFX_ENCODERID3PAGEDIALOG_H__442115D0_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ENCODERID3PAGEDIALOG_H__442115D0_0FD4_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// EncoderId3PageDialog.h : header file
+//
+
+#include "JobListUpdatable.h"
+#include "JobListsToConfigureSaver.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderId3PageDialog dialog
+
+class CEncoderId3PageDialog : public CDialog
+{
+// Construction
+public:
+	CEncoderId3PageDialog(const TItemList<CJob*> &oJobsToConfigure, CJobListUpdatable *poListContainer, CWnd* pParent = NULL);   // standard constructor
+	virtual ~CEncoderId3PageDialog();
+
+// Dialog Data
+	//{{AFX_DATA(CEncoderId3PageDialog)
+	enum { IDD = IDD_ENCODERID3PAGEDIALOG };
+	CEdit	m_ctrlEditYear;
+	CEdit	m_ctrlEditTrack;
+	CComboBox	m_ctrlComboGenre;
+	CButton	m_ctrlCheckCopyright;
+	CString	m_oEditAlbum;
+	CString	m_oEditArtist;
+	CString	m_oEditComment;
+	CString	m_oEditComposer;
+	CString	m_oEditEncodedBy;
+	CString	m_oEditOriginalArtist;
+	CString	m_oEditTitle;
+	CString	m_oEditTrack;
+	CString	m_oEditUrl;
+	CString	m_oEditYear;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CEncoderId3PageDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+public:
+	// returns false in case of errors
+	bool GetPageContents(CEncoderId3PropertyPageContents &oTarget);
+	void ApplyPageContents(const CEncoderId3PropertyPageContents &oPageContents);
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CEncoderId3PageDialog)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnKillfocusComboGenre();
+	afx_msg void OnKillfocusEditAlbum();
+	afx_msg void OnKillfocusEditArtist();
+	afx_msg void OnKillfocusEditComment();
+	afx_msg void OnKillfocusEditComposer();
+	afx_msg void OnKillfocusEditEncodedBy();
+	afx_msg void OnKillfocusEditOriginalArtist();
+	afx_msg void OnKillfocusEditTitle();
+	afx_msg void OnKillfocusEditTrack();
+	afx_msg void OnKillfocusEditUrl();
+	afx_msg void OnKillfocusEditYear();
+	afx_msg void OnCheckCopyright();
+	afx_msg void OnUpdateEditTrack();
+	afx_msg void OnUpdateEditYear();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+	bool m_bInitialized;
+
+	TItemList<CJob*> m_oJobsToConfigure;
+
+	CJobListUpdatable *m_poListContainer;
+
+	CEncoderId3PropertyPageContents ParseJobs();
+	void ModifyJobs(const CEncoderId3PropertyPageContents &oPageContents);
+
+	// called when changes have been made in the dialog and are to
+	// be synchronized with both "data holders"
+	void UpdateJobs(bool bFinishCheckBoxSessions=true, bool bDlgDestructUpdate=false);
+	bool m_bIgnoreUpdates;
+
+
+	// these members are used for managing the check box controls and the
+	// changes that are made with them in the dialog
+	enum ETypeOfCheckBox
+	{
+		eNone,
+		eCopyright,
+	} m_eCurCheckBox;
+	CJobListsToConfigureSaver m_oCheckStateChangeStateSaver;
+	void ProcessCheckBoxClick(CButton *poCheckBox, ETypeOfCheckBox eTypeOfCheckBox);
+	void FinishCurrentCheckBoxSessionIfNecessary();
+	void FinishCheckBoxSessionIfNecessary(CButton *poCheckBox);
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ENCODERID3PAGEDIALOG_H__442115D0_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/EncoderId3PropertyPageContents.cpp
@@ -1,0 +1,46 @@
+// EncoderId3PropertyPageContents.cpp: implementation of the CEncoderId3PropertyPageContents class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "EncoderId3PropertyPageContents.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CEncoderId3PropertyPageContents::CEncoderId3PropertyPageContents()
+{
+
+}
+
+CEncoderId3PropertyPageContents::~CEncoderId3PropertyPageContents()
+{
+
+}
+
+CEncoderId3PropertyPageContents& CEncoderId3PropertyPageContents::operator*=(const CEncoderId3PropertyPageContents &oRight)
+{
+	m_oArtist*=oRight.m_oArtist;
+	m_oTrackNo*=oRight.m_oTrackNo;
+	m_oAlbum*=oRight.m_oAlbum;
+	m_oYear*=oRight.m_oYear;
+	m_oTitle*=oRight.m_oTitle;
+	m_oCopyright*=oRight.m_oCopyright;
+	m_oOriginalArtist*=oRight.m_oOriginalArtist;
+	m_oComposer*=oRight.m_oComposer;
+	m_oUrl*=oRight.m_oUrl;
+	m_oGenre*=oRight.m_oGenre;
+	m_oEncodedBy*=oRight.m_oEncodedBy;
+	m_oComment*=oRight.m_oComment;
+
+	return *this;
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/EncoderId3PropertyPageContents.h
@@ -1,0 +1,44 @@
+// EncoderId3PropertyPageContents.h: interface for the CEncoderId3PropertyPageContents class.
+// Author: Torsten Landmann
+//
+// encapsulates the content of the property page "id3" including
+// possible 3rd states of all controls
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ENCODERID3PROPERTYPAGECONTENTS_H__0C2E1C01_10AE_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ENCODERID3PROPERTYPAGECONTENTS_H__0C2E1C01_10AE_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "AbstractPropertyPageContents.h"
+#include "PageEditCtrlContent.h"
+#include "PageCheckboxCtrlContent.h"
+#include "PageComboBoxCtrlContent.h"
+
+class CEncoderId3PropertyPageContents : public CAbstractPropertyPageContents  
+{
+public:
+	CEncoderId3PropertyPageContents();
+	virtual ~CEncoderId3PropertyPageContents();
+
+	CPageEditCtrlContent m_oArtist;
+	CPageEditCtrlContent m_oTrackNo;
+	CPageEditCtrlContent m_oAlbum;
+	CPageEditCtrlContent m_oYear;
+	CPageEditCtrlContent m_oTitle;
+	CPageCheckboxCtrlContent m_oCopyright;
+	CPageEditCtrlContent m_oOriginalArtist;
+	CPageEditCtrlContent m_oComposer;
+	CPageEditCtrlContent m_oUrl;
+	CPageComboBoxCtrlContent m_oGenre;
+	CPageEditCtrlContent m_oEncodedBy;
+	CPageEditCtrlContent m_oComment;
+
+	// with this operator pages for several jobs can be "merged"
+	CEncoderId3PropertyPageContents& operator*=(const CEncoderId3PropertyPageContents &oRight);
+};
+
+#endif // !defined(AFX_ENCODERID3PROPERTYPAGECONTENTS_H__0C2E1C01_10AE_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/EncoderJob.cpp
@@ -1,0 +1,443 @@
+// EncoderJob.cpp: implementation of the CEncoderJob class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "EncoderJob.h"
+#include "EncoderJobProcessingManager.h"
+#include "ProcessJobStatusDialog.h"
+#include "RecursiveDirectoryTraverser.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CEncoderJob::CEncoderJob():
+	m_bAllowMidSide(false),
+	m_bUseTns(false),
+	m_bUseLtp(false),
+	m_bUseLfe(false),
+	m_eAacProfile(eAacProfileMain),
+	m_ulBitRate(128000),
+	m_ulBandwidth(22500)
+{
+
+}
+
+CEncoderJob::CEncoderJob(const CEncoderJob &oSource)
+{
+	*this=oSource;
+}
+
+CEncoderJob::~CEncoderJob()
+{
+
+}
+
+
+CEncoderJob& CEncoderJob::operator=(const CEncoderJob &oRight)
+{
+	m_oFiles=oRight.m_oFiles;
+	m_bSourceFileFilterIsRecursive=oRight.m_bSourceFileFilterIsRecursive;
+	m_oTargetFileId3Info=oRight.m_oTargetFileId3Info;
+
+	m_bAllowMidSide=oRight.m_bAllowMidSide;
+	m_bUseTns=oRight.m_bUseTns;
+	m_bUseLtp=oRight.m_bUseLtp;
+	m_bUseLfe=oRight.m_bUseLfe;
+	m_eAacProfile=oRight.m_eAacProfile;
+
+	m_ulBitRate=oRight.m_ulBitRate;
+
+	m_ulBandwidth=oRight.m_ulBandwidth;
+
+	return *this;
+}
+
+CString CEncoderJob::DescribeJobTypeShort() const
+{
+	CString oEncoderJob;
+	oEncoderJob.LoadString(IDS_EncoderJobShort);
+	return oEncoderJob;
+}
+
+CString CEncoderJob::DescribeJobTypeLong() const
+{
+	CString oEncoderJob;
+	oEncoderJob.LoadString(IDS_EncoderJobLong);
+	return oEncoderJob;
+}
+
+CString CEncoderJob::DescribeJob() const
+{
+	CString oToReturn;
+	oToReturn.Format("%s - %s - %.0f kbit/s - %.0f kHz", GetFiles().GetSourceFileName(), TranslateAacProfileToShortString(GetAacProfile()), (double)GetBitRate()/1000, (double)GetBandwidth()/1000);
+	if (GetAllowMidside())
+	{
+		CString oMidSide;
+		oMidSide.LoadString(IDS_MidSide);
+		oToReturn+=CString(" - ")+oMidSide;
+	}
+	if (GetUseTns())
+	{
+		CString oTns;
+		oTns.LoadString(IDS_UseTns);
+		oToReturn+=CString(" - ")+oTns;
+	}
+	if (GetUseLtp())
+	{
+		CString oLtp;
+		oLtp.LoadString(IDS_UseLtp);
+		oToReturn+=CString(" - ")+oLtp;
+	}
+	if (GetUseLfe())
+	{
+		CString oLfe;
+		oLfe.LoadString(IDS_UseLfe);
+		oToReturn+=CString(" - ")+oLfe;
+	}
+	return oToReturn;
+}
+
+CSupportedPropertyPagesData CEncoderJob::GetSupportedPropertyPages() const
+{
+	CSupportedPropertyPagesData toReturn;
+	toReturn.ShowPage(ePageTypeEncoderGeneral);
+	toReturn.ShowPage(ePageTypeEncoderQuality);
+	toReturn.ShowPage(ePageTypeEncoderID3);
+
+	return toReturn;
+}
+
+bool CEncoderJob::ProcessJob() const
+{
+	if (!CFilePathCalc::IsValidFileMask(GetFiles().GetSourceFileName()))
+	{
+		// it's a regular single file encoder job
+
+		// create the manager that manages and performs the processing
+		CEncoderJobProcessingManager oManager(this);
+
+		// create the status dialog
+		CProcessJobStatusDialog oDlg(&oManager);
+		return oDlg.DoModal()==IDOK;
+	}
+	else
+	{
+		// it's a filter encoder job
+
+		// first find out all files that actually belong to the job
+		TItemList<CString> oFiles=
+			CRecursiveDirectoryTraverser::FindFiles(
+			GetFiles().GetSourceFileDirectory(),
+			GetFiles().GetSourceFileName(),
+			GetSourceFileFilterIsRecursive());
+
+		if (oFiles.GetNumber()==0)
+		{
+			CString oError;
+			oError.Format(IDS_FilterDidntFindFiles, GetFiles().GetCompleteSourceFilePath());
+			AfxMessageBox(oError);
+			return false;
+		}
+
+		CBListReader oReader(oFiles);
+		CString oCurrentFilePath;
+		while (oFiles.GetNextElemContent(oReader, oCurrentFilePath))
+		{
+			CEncoderJob oNewJob(*this);
+			if (!oNewJob.GetFiles().SetCompleteSourceFilePath(oCurrentFilePath))
+			{
+				CString oError;
+				oError.Format(IDS_ErrorCreatingNestedEncoderJob, oCurrentFilePath, GetFiles().GetCompleteSourceFilePath());
+				if (AfxMessageBox(oError, MB_YESNO)!=IDYES)
+				{
+					return false;
+				}
+			}
+			// assemble the target file name and apply it to the new job
+			{
+				// find out the long name of the source file directory
+				CString oSourceFileDir;
+				{
+					oSourceFileDir=GetFiles().GetSourceFileDirectory();
+					if (oSourceFileDir[oSourceFileDir.GetLength()-1]=='\\')
+					{
+						oSourceFileDir.Delete(oSourceFileDir.GetLength()-1);
+					}
+					CString oTemp;
+					LPTSTR pDummy;
+					::GetFullPathName(oSourceFileDir,
+						MAX_PATH, oTemp.GetBuffer(MAX_PATH),
+						&pDummy);
+					oTemp.ReleaseBuffer();
+
+					oSourceFileDir=oTemp;
+				}
+
+				// find out the suffix to append to the target directory
+				// for our particular file
+				CString oDirSuffix;
+				{
+					CString oFileDir(oCurrentFilePath);
+					CFilePathCalc::MakePath(oFileDir);
+					int iLength=oFileDir.GetLength();
+					oDirSuffix=oFileDir.Right(iLength-oSourceFileDir.GetLength());
+					oDirSuffix.Delete(0);
+				}
+
+				// determine the target directory for that particular file
+				CString oTargetDir(GetFiles().GetTargetFileDirectory());
+				CFilePathCalc::MakePath(oTargetDir, true);
+				oTargetDir+=oDirSuffix;
+				if (!CRecursiveDirectoryTraverser::MakeSureDirectoryExists(oTargetDir))
+				{
+					CString oError;
+					oError.Format(IDS_ErrorCreatingNestedEncoderJob, oCurrentFilePath, GetFiles().GetCompleteSourceFilePath());
+					AfxMessageBox("Error creating target directory", MB_OK | MB_ICONSTOP);		// XXX insert resource string and ask user what to do
+					return false;
+				}
+
+				CString oSourceFileName;
+				CFilePathCalc::ExtractFileName(oCurrentFilePath, oSourceFileName);
+				CString oSourceFileNameRaw;
+				CString oSourceFileExtension;
+				CFilePathCalc::SplitFileAndExtension(oSourceFileName, oSourceFileNameRaw, oSourceFileExtension);
+				oNewJob.GetFiles().SetTargetFileDirectory(oTargetDir);
+				CString oDefaultExtension;
+				oDefaultExtension.LoadString(IDS_EndTargetFileStandardExtension);
+				oNewJob.GetFiles().SetTargetFileName(oSourceFileNameRaw+"."+oDefaultExtension);
+			}
+
+			// process the new job
+			if (!oNewJob.ProcessJob())
+			{
+				CString oError;
+				oError.Format(IDS_ErrorCreatingNestedEncoderJob, oCurrentFilePath, GetFiles().GetCompleteSourceFilePath());
+				if (AfxMessageBox(oError, MB_YESNO)!=IDYES)
+				{
+					return false;
+				}
+			}
+		}
+
+		return true;
+	}
+}
+
+CString CEncoderJob::GetDetailedDescriptionForStatusDialog() const
+{
+	CString oToReturn;
+	oToReturn.Format(IDS_DetailedEncoderJobDescriptionString, GetFiles().GetCompleteSourceFilePath(), GetFiles().GetCompleteTargetFilePath(), TranslateAacProfileToShortString(GetAacProfile()), GetBitRate(), GetBandwidth());
+	if (GetAllowMidside())
+	{
+		CString oMidSide;
+		oMidSide.LoadString(IDS_MidSide);
+		oToReturn+=CString(" - ")+oMidSide;
+	}
+	if (GetUseTns())
+	{
+		CString oTns;
+		oTns.LoadString(IDS_UseTns);
+		oToReturn+=CString(" - ")+oTns;
+	}
+	if (GetUseLtp())
+	{
+		CString oLtp;
+		oLtp.LoadString(IDS_UseLtp);
+		oToReturn+=CString(" - ")+oLtp;
+	}
+	if (GetUseLfe())
+	{
+		CString oLfe;
+		oLfe.LoadString(IDS_UseLfe);
+		oToReturn+=CString(" - ")+oLfe;
+	}
+	return oToReturn;
+}
+
+bool CEncoderJob::PutToArchive(CArchive &oArchive) const
+{
+	// put a class version flag
+	int iVersion=1;
+	oArchive << iVersion;
+
+	if (!m_oFiles.PutToArchive(oArchive)) return false;
+	CFileSerializable::SerializeBool(oArchive, m_bSourceFileFilterIsRecursive);
+	if (!m_oTargetFileId3Info.PutToArchive(oArchive)) return false;
+
+	oArchive << m_eAacProfile;
+	CFileSerializable::SerializeBool(oArchive, m_bAllowMidSide);
+	CFileSerializable::SerializeBool(oArchive, m_bUseTns);
+	CFileSerializable::SerializeBool(oArchive, m_bUseLtp);
+	CFileSerializable::SerializeBool(oArchive, m_bUseLfe);
+	oArchive << m_ulBitRate;
+	oArchive << m_ulBandwidth;
+
+	return true;
+}
+
+bool CEncoderJob::GetFromArchive(CArchive &oArchive)
+{
+	// fetch the class version flag
+	int iVersion;
+	oArchive >> iVersion;
+
+	switch (iVersion)
+	{
+	case 1:
+		{
+			if (!m_oFiles.GetFromArchive(oArchive)) return false;
+			CFileSerializable::DeSerializeBool(oArchive, m_bSourceFileFilterIsRecursive);
+			if (!m_oTargetFileId3Info.GetFromArchive(oArchive)) return false;
+
+			oArchive >> (int&)m_eAacProfile;
+			CFileSerializable::DeSerializeBool(oArchive, m_bAllowMidSide);
+			CFileSerializable::DeSerializeBool(oArchive, m_bUseTns);
+			CFileSerializable::DeSerializeBool(oArchive, m_bUseLtp);
+			CFileSerializable::DeSerializeBool(oArchive, m_bUseLfe);
+			oArchive >> m_ulBitRate;
+			oArchive >> m_ulBandwidth;
+
+			return true;
+		}
+	default:
+		{
+			// unknown file format version
+			return false;
+		}
+	}
+}
+
+CString CEncoderJob::TranslateAacProfileToShortString(EAacProfile eAacProfile)
+{
+	int iStringId;
+	switch (eAacProfile)
+	{
+	case eAacProfileLc:
+		{
+			iStringId=IDS_AacProfileLc;
+			break;
+		}
+	case eAacProfileMain:
+		{
+			iStringId=IDS_AacProfileMain;
+			break;
+		}
+	case eAacProfileSsr:
+		{
+			iStringId=IDS_AacProfileSsr;
+			break;
+		}
+	default:
+		{
+			// unknown aac profile
+			ASSERT(false);
+			iStringId=0;
+			break;
+		}
+	}
+
+	CString oToReturn;
+	oToReturn.Format(iStringId);
+	return oToReturn;
+}
+
+CEncoderGeneralPropertyPageContents CEncoderJob::GetGeneralPageContents() const
+{
+	CEncoderGeneralPropertyPageContents oToReturn;
+	oToReturn.m_oSourceDirectory.SetContent(GetFiles().GetSourceFileDirectory());
+	oToReturn.m_oSourceFile.SetContent(GetFiles().GetSourceFileName());
+	oToReturn.m_oTargetDirectory.SetContent(GetFiles().GetTargetFileDirectory());
+	oToReturn.m_oTargetFile.SetContent(GetFiles().GetTargetFileName());
+	oToReturn.m_oSourceFileFilterIsRecursive.SetCheckMark(GetSourceFileFilterIsRecursive());
+
+	// save if this job would have the "recursive" check box enabled
+	oToReturn.m_oSourceFilterRecursiveCheckboxVisible.SetCheckMark(CFilePathCalc::IsValidFileMask(GetFiles().GetSourceFileName()));
+
+	return oToReturn;
+}
+
+void CEncoderJob::ApplyGeneralPageContents(const CEncoderGeneralPropertyPageContents &oPageContents)
+{
+	// note: the use of getters on the righthand side is correct since they return references
+	oPageContents.m_oSourceDirectory.ApplyToJob(GetFiles().GetSourceFileDirectory());
+	oPageContents.m_oSourceFile.ApplyToJob(GetFiles().GetSourceFileName());
+	oPageContents.m_oTargetDirectory.ApplyToJob(GetFiles().GetTargetFileDirectory());
+	oPageContents.m_oTargetFile.ApplyToJob(GetFiles().GetTargetFileName());
+	oPageContents.m_oSourceFileFilterIsRecursive.ApplyToJob(m_bSourceFileFilterIsRecursive);
+
+	// ignore oPageContents.m_oSourceFilterRecursiveCheckboxVisible
+}
+
+CEncoderQualityPropertyPageContents CEncoderJob::GetQualityPageContents() const
+{
+	CEncoderQualityPropertyPageContents oToReturn;
+	oToReturn.m_oBitRate.SetContent(GetBitRateL());
+	oToReturn.m_oBandwidth.SetContent(GetBandwidthL());
+	oToReturn.m_oAllowMidSide.SetCheckMark(GetAllowMidside());
+	oToReturn.m_oUseTns.SetCheckMark(GetUseTns());
+	oToReturn.m_oUseLtp.SetCheckMark(GetUseLtp());
+	oToReturn.m_oUseLfe.SetCheckMark(GetUseLfe());
+	oToReturn.m_oAacProfile.SetContent(GetAacProfileL(), true);
+
+	return oToReturn;
+}
+
+void CEncoderJob::ApplyQualityPageContents(const CEncoderQualityPropertyPageContents &oPageContents)
+{
+	// note: the use of getters on the righthand side is correct since they return references
+	oPageContents.m_oBitRate.ApplyToJob((long&)m_ulBitRate);
+	oPageContents.m_oBandwidth.ApplyToJob((long&)m_ulBandwidth);
+	oPageContents.m_oAllowMidSide.ApplyToJob(m_bAllowMidSide);
+	oPageContents.m_oUseTns.ApplyToJob(m_bUseTns);
+	oPageContents.m_oUseLtp.ApplyToJob(m_bUseLtp);
+	oPageContents.m_oUseLfe.ApplyToJob(m_bUseLfe);
+	long lTemp=-1;
+	oPageContents.m_oAacProfile.ApplyToJob(lTemp);
+	if (lTemp>=0) SetAacProfile(lTemp);
+}
+
+CEncoderId3PropertyPageContents CEncoderJob::GetId3PageContents() const
+{
+	CEncoderId3PropertyPageContents oToReturn;
+	oToReturn.m_oArtist.SetContent(GetTargetFileId3Info().GetArtist());
+	oToReturn.m_oTrackNo.SetContent(GetTargetFileId3Info().GetTrackNo(), true);
+	oToReturn.m_oAlbum.SetContent(GetTargetFileId3Info().GetAlbum());
+	oToReturn.m_oYear.SetContent(GetTargetFileId3Info().GetYear(), true);
+	oToReturn.m_oTitle.SetContent(GetTargetFileId3Info().GetSongTitle());
+	oToReturn.m_oCopyright.SetCheckMark(GetTargetFileId3Info().GetCopyright());
+	oToReturn.m_oOriginalArtist.SetContent(GetTargetFileId3Info().GetOriginalArtist());
+	oToReturn.m_oComposer.SetContent(GetTargetFileId3Info().GetComposer());
+	oToReturn.m_oUrl.SetContent(GetTargetFileId3Info().GetUrl());
+	oToReturn.m_oGenre.SetContentText(GetTargetFileId3Info().GetGenre());
+	oToReturn.m_oEncodedBy.SetContent(GetTargetFileId3Info().GetEncodedBy());
+	oToReturn.m_oComment.SetContent(GetTargetFileId3Info().GetComment());
+
+	return oToReturn;
+}
+
+void CEncoderJob::ApplyId3PageContents(const CEncoderId3PropertyPageContents &oPageContents)
+{
+	// note: the use of getters on the righthand side is correct since they return references
+	oPageContents.m_oArtist.ApplyToJob(GetTargetFileId3Info().GetArtist());
+	oPageContents.m_oTrackNo.ApplyToJob(GetTargetFileId3Info().GetTrackNoRef());
+	oPageContents.m_oAlbum.ApplyToJob(GetTargetFileId3Info().GetAlbum());
+	oPageContents.m_oYear.ApplyToJob(GetTargetFileId3Info().GetYearRef());
+	oPageContents.m_oTitle.ApplyToJob(GetTargetFileId3Info().GetSongTitle());
+	oPageContents.m_oCopyright.ApplyToJob(GetTargetFileId3Info().GetCopyrightRef());
+	oPageContents.m_oOriginalArtist.ApplyToJob(GetTargetFileId3Info().GetOriginalArtist());
+	oPageContents.m_oComposer.ApplyToJob(GetTargetFileId3Info().GetComposer());
+	oPageContents.m_oUrl.ApplyToJob(GetTargetFileId3Info().GetUrl());
+	oPageContents.m_oGenre.ApplyToJob(GetTargetFileId3Info().GetGenre());
+	oPageContents.m_oEncodedBy.ApplyToJob(GetTargetFileId3Info().GetEncodedBy());
+	oPageContents.m_oComment.ApplyToJob(GetTargetFileId3Info().GetComment());
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/EncoderJob.h
@@ -1,0 +1,119 @@
+// EncoderJob.h: interface for the CEncoderJob class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ENCODERJOB_H__DFE38E70_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ENCODERJOB_H__DFE38E70_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "SourceTargetFilePair.h"
+#include "Id3TagInfo.h"
+#include "ConcreteJobBase.h"
+#include "EncoderGeneralPropertyPageContents.h"
+#include "EncoderQualityPropertyPageContents.h"
+#include "EncoderId3PropertyPageContents.h"
+
+// do not derive this class from CJob;
+// rather let CJob objects contain instances of this class
+class CEncoderJob : public CConcreteJobBase
+{
+public:
+	CEncoderJob();
+	CEncoderJob(const CEncoderJob &oSource);		// copy constructor
+	virtual ~CEncoderJob();
+
+	enum EAacProfile
+	{
+		eAacProfileLc=0,			// the values of the enumerated constants
+		eAacProfileMain=1,			// must reflect the order of the radio
+		eAacProfileSsr=2,			// controls on the property page, starting with 0
+	};
+
+	// property getters
+	const CSourceTargetFilePair& GetFiles() const						{ return m_oFiles; }
+	CSourceTargetFilePair& GetFiles()									{ return m_oFiles; }
+	CSourceTargetFilePair* GetFilesPointer()							{ return &m_oFiles; }
+	bool GetSourceFileFilterIsRecursive() const							{ return m_bSourceFileFilterIsRecursive; }
+	const CId3TagInfo& GetTargetFileId3Info() const						{ return m_oTargetFileId3Info; }
+	CId3TagInfo& GetTargetFileId3Info()									{ return m_oTargetFileId3Info; }
+	CId3TagInfo* GetTargetFileId3InfoPointer()							{ return &m_oTargetFileId3Info; }
+	bool GetAllowMidside() const										{ return m_bAllowMidSide; }
+	bool GetUseTns() const												{ return m_bUseTns; }
+	bool GetUseLtp() const												{ return m_bUseLtp; }
+	bool GetUseLfe() const												{ return m_bUseLfe; }
+	EAacProfile GetAacProfile() const									{ return m_eAacProfile; }
+	long GetAacProfileL() const											{ return m_eAacProfile; }
+	unsigned long GetBitRate() const									{ return m_ulBitRate; }
+	long GetBitRateL() const											{ return (long)m_ulBitRate; }
+	unsigned long GetBandwidth() const									{ return m_ulBandwidth; }
+	long GetBandwidthL() const											{ return (long)m_ulBandwidth; }
+					
+	// property setters
+	void SetFiles(const CSourceTargetFilePair &oFiles)					{ m_oFiles=oFiles; }
+	void SetSourceFileFilterIsRecursive(bool bIsRecursive)				{ m_bSourceFileFilterIsRecursive=bIsRecursive; }
+	void SetTargetFileId3Info(const CId3TagInfo &oTargetFileId3Info)	{ m_oTargetFileId3Info=oTargetFileId3Info; }
+	void SetAllowMidside(bool bAllowMidSide)							{ m_bAllowMidSide=bAllowMidSide; }
+	void SetUseTns(bool bUseTns)										{ m_bUseTns=bUseTns; }
+	void SetUseLtp(bool bUseLtp)										{ m_bUseLtp=bUseLtp; }
+	void SetUseLfe(bool bUseLfe) 										{ m_bUseLfe=bUseLfe; }
+	void SetAacProfile(EAacProfile eAacProfile)							{ m_eAacProfile=eAacProfile; }
+	void SetAacProfile(long lAacProfile)								{ m_eAacProfile=(EAacProfile)lAacProfile; }
+	void SetBitRate(unsigned long ulBitRate)							{ m_ulBitRate=ulBitRate; }
+	void SetBitRate(long lBitRate)										{ ASSERT(lBitRate>=0); m_ulBitRate=(unsigned long)lBitRate; }
+	void SetBandwidth(unsigned long ulBandwidth)						{ m_ulBandwidth=ulBandwidth; }
+	void SetBandwidth(long lBandwidth)									{ ASSERT(lBandwidth>=0); m_ulBandwidth=lBandwidth; }
+
+	CEncoderJob& operator=(const CEncoderJob &oRight);
+
+	// property page interaction
+	CEncoderGeneralPropertyPageContents GetGeneralPageContents() const;
+	void ApplyGeneralPageContents(const CEncoderGeneralPropertyPageContents &oPageContents);
+	CEncoderQualityPropertyPageContents GetQualityPageContents() const;
+	void ApplyQualityPageContents(const CEncoderQualityPropertyPageContents &oPageContents);
+	CEncoderId3PropertyPageContents GetId3PageContents() const;
+	void ApplyId3PageContents(const CEncoderId3PropertyPageContents &oPageContents);
+
+	// implementations to CJobListCtrlDescribable
+	virtual CString DescribeJobTypeShort() const;
+	virtual CString DescribeJobTypeLong() const;
+	virtual CString DescribeJob() const;
+
+	// implementations to CAbstractJob
+	virtual CSupportedPropertyPagesData GetSupportedPropertyPages() const;
+	virtual bool ProcessJob() const;
+	virtual CString GetDetailedDescriptionForStatusDialog() const;
+
+	// implementations to CFileSerializable
+	virtual bool PutToArchive(CArchive &oArchive) const;
+	virtual bool GetFromArchive(CArchive &oArchive);
+
+	static CString TranslateAacProfileToShortString(EAacProfile eAacProfile);
+
+private:
+	CSourceTargetFilePair m_oFiles;
+	bool m_bSourceFileFilterIsRecursive;
+	CId3TagInfo m_oTargetFileId3Info;
+
+	/* AAC profile */
+	EAacProfile m_eAacProfile;
+	/* Allow mid/side coding */
+	bool m_bAllowMidSide;
+	/* Use Temporal Noise Shaping */
+	bool m_bUseTns;
+	/* Use Long Term Prediction */
+	bool m_bUseLtp;
+	/* Use one of the channels as LFE channel */
+	bool m_bUseLfe;
+
+	/* bitrate / channel of AAC file */
+	unsigned long m_ulBitRate;
+
+	/* AAC file frequency bandwidth */
+	unsigned long m_ulBandwidth;
+};
+
+#endif // !defined(AFX_ENCODERJOB_H__DFE38E70_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/EncoderJobProcessingManager.cpp
@@ -1,0 +1,355 @@
+// EncoderJobProcessingManager.cpp: implementation of the CEncoderJobProcessingManager class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "EncoderJobProcessingManager.h"
+#include "WindowUtil.h"
+
+#include <sndfile.h>
+#include "faac.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//#define DUMMY_ENCODERJOB_PROCESSING
+
+// constants copied from reference implementation in VC project faacgui
+#define PCMBUFSIZE 1024
+#define BITBUFSIZE 8192
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CEncoderJobProcessingManager::CEncoderJobProcessingManager(const CEncoderJob *poJobToProcess):
+	m_poJobToProcess(poJobToProcess),
+	m_poInfoTarget(0),
+	m_eCurrentWorkingState(eInitial)
+{
+}
+
+CEncoderJobProcessingManager::~CEncoderJobProcessingManager()
+{
+}
+
+void CEncoderJobProcessingManager::Start(
+	CProcessingStatusDialogInfoFeedbackCallbackInterface *poInfoTarget)
+{
+	if (poInfoTarget!=0)
+	{
+		m_poInfoTarget=poInfoTarget;
+	}
+
+	switch (m_eCurrentWorkingState)
+	{
+	case eInitial:
+		{
+			m_poInfoTarget->SetAvailableActions(true, false);
+			m_eCurrentWorkingState=eRunning;
+			m_poInfoTarget->ReturnToCaller(DoProcessing());
+			break;
+		}
+	case ePaused:
+		{
+			m_eCurrentWorkingState=eRunning;
+			break;
+		}
+	default:
+		{
+			// call to Start() is invalid except in the above two cases
+			ASSERT(false);
+		}
+	}
+}
+
+void CEncoderJobProcessingManager::Stop()
+{
+	switch (m_eCurrentWorkingState)
+	{
+	case eRunning:
+	case ePaused:
+		{
+			m_eCurrentWorkingState=eStopped;
+			break;
+		}
+	case eCleanup:
+		{
+			// ignore
+			break;
+		}
+	default:
+		{
+			// call to Stop() is invalid except in the above two cases
+			ASSERT(false);
+		}
+	}
+}
+
+void CEncoderJobProcessingManager::Pause()
+{
+	switch (m_eCurrentWorkingState)
+	{
+	case eRunning:
+		{
+			m_eCurrentWorkingState=ePaused;
+			break;
+		}
+	default:
+		{
+			// call to Pause() is invalid except in the above case
+			ASSERT(false);
+		}
+	}
+}
+
+#ifdef DUMMY_ENCODERJOB_PROCESSING
+bool CEncoderJobProcessingManager::DoProcessing()
+{
+	long lStartTimeMillis=::GetTickCount();
+
+	long lMaxCount=250*64000/(5+m_poJobToProcess->GetBitRate());
+	for (long lPos=0; lPos<lMaxCount; lPos++)
+	{
+		long lMultiplicationDummy;
+		for (long lPosInner=0; lPosInner<10000000; lPosInner++)
+		{
+			// just a pause to simulate work
+			lMultiplicationDummy=234985;
+			lMultiplicationDummy*=301872;
+		}
+
+		switch (m_eCurrentWorkingState)
+		{
+		case eRunning:
+			{
+				// just report our current state
+				WriteProgress(lStartTimeMillis, lMaxCount, lPos);
+				m_poInfoTarget->ProcessUserMessages();
+				break;
+			}
+		case ePaused:
+			{
+				// must wait
+				while (m_eCurrentWorkingState==ePaused)
+				{
+					// be idle
+					m_poInfoTarget->ProcessUserMessages();
+					Sleep(200);
+				}
+				break;
+			}
+		case eStopped:
+			{
+				// must interrupt
+				return false;
+			}
+		}
+	}
+
+	m_eCurrentWorkingState=eCleanup;
+
+	return true;
+}
+
+#else
+bool CEncoderJobProcessingManager::DoProcessing()
+{
+	long lStartTimeMillis=::GetTickCount();
+	const CEncoderJob *poJob=m_poJobToProcess;
+	bool bInterrupted=false;
+
+	// TEMP: added to make it work, these values need to be used
+	unsigned long inputSamples, maxOutputSize;
+	//
+
+	SNDFILE *infile;
+	SF_INFO sfinfo;
+
+	// open the input file
+	if ((infile = sf_open_read(poJob->GetFiles().GetCompleteSourceFilePath(), &sfinfo)) != NULL)
+	{
+		// determine input file parameters
+		unsigned int sampleRate = sfinfo.samplerate;
+		unsigned int numChannels = sfinfo.channels;
+
+		// open and setup the encoder
+		faacEncHandle hEncoder = faacEncOpen(sampleRate, numChannels, &inputSamples,
+			&maxOutputSize);
+		if (hEncoder)
+		{
+			HANDLE hOutfile;
+
+			// set encoder configuration
+			faacEncConfigurationPtr config = faacEncGetCurrentConfiguration(hEncoder);
+
+			config->allowMidside = poJob->GetAllowMidside() ? 1 : 0;
+			config->useTns = poJob->GetUseTns() ? 1 : 0;
+			config->useLtp = poJob->GetUseLtp() ? 1 : 0;
+			config->useLfe = poJob->GetUseLfe() ? 1 : 0;
+			config->bitRate = poJob->GetBitRate();
+			config->bandWidth = poJob->GetBandwidth();
+			config->aacProfile = GetAacProfileConstant(poJob->GetAacProfile());
+
+			if (!faacEncSetConfiguration(hEncoder, config))
+			{
+				faacEncClose(hEncoder);
+				sf_close(infile);
+
+				AfxMessageBox("faacEncSetConfiguration failed!", MB_OK | MB_ICONSTOP);
+
+				return false;
+			}
+
+			// open the output file
+			hOutfile = CreateFile(poJob->GetFiles().GetCompleteTargetFilePath(), GENERIC_WRITE, 0, NULL,
+				CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+			if (hOutfile != INVALID_HANDLE_VALUE)
+			{
+				UINT startTime = GetTickCount(), lastUpdated = 0;
+				DWORD totalBytesRead = 0;
+
+				unsigned int bytesInput = 0, bytesConsumed = 0;
+				DWORD numberOfBytesWritten = 0;
+				short *pcmbuf;
+				unsigned char *bitbuf;
+
+				pcmbuf = (short*)malloc(PCMBUFSIZE*numChannels*sizeof(short));
+				bitbuf = (unsigned char*)malloc(BITBUFSIZE*sizeof(unsigned char));
+
+				while (true)
+				{
+					int bytesWritten;
+					int samplesToRead = PCMBUFSIZE;
+
+					bytesInput = sf_read_short(infile, pcmbuf, numChannels*PCMBUFSIZE) * sizeof(short);
+					
+					//SendDlgItemMessage (hWnd, IDC_PROGRESS, PBM_SETPOS, (unsigned long)((float)totalBytesRead * 1024.0f / (sfinfo.samples*2*numChannels)), 0);
+					
+					totalBytesRead += bytesInput;
+
+					// call the actual encoding routine
+					bytesWritten = faacEncEncode(hEncoder,
+						pcmbuf,
+						bytesInput/2,
+						bitbuf,
+						BITBUFSIZE);
+
+					switch (m_eCurrentWorkingState)
+					{
+					case eRunning:
+						{
+							// just report our current state and process waiting window messages
+							WriteProgress(lStartTimeMillis, (sfinfo.samples*2*numChannels), totalBytesRead);
+							m_poInfoTarget->ProcessUserMessages();
+							break;
+						}
+					case ePaused:
+						{
+							// must wait
+							while (m_eCurrentWorkingState==ePaused)
+							{
+								// be idle
+								m_poInfoTarget->ProcessUserMessages();
+								Sleep(200);
+							}
+							break;
+						}
+					case eStopped:
+						{
+							// must interrupt
+							bInterrupted=true;
+							break;
+						}
+					}
+					
+					if (bInterrupted) 
+					{
+						// Stop Pressed
+						break;
+					}
+
+					if (!bytesInput && !bytesWritten)
+					{
+						// all done, bail out
+						break;
+					}
+
+					if (bytesWritten < 0)
+					{
+						AfxMessageBox("faacEncEncodeFrame failed!", MB_OK | MB_ICONSTOP);
+						bInterrupted=true;
+						break;
+					}
+
+					WriteFile(hOutfile, bitbuf, bytesWritten, &numberOfBytesWritten, NULL);
+				}
+
+				CloseHandle(hOutfile);
+				if (pcmbuf) free(pcmbuf);
+				if (bitbuf) free(bitbuf);
+			}
+
+			faacEncClose(hEncoder);
+		}
+
+		sf_close(infile);
+		MessageBeep(1);
+	}
+	else
+	{
+		AfxMessageBox("Couldn't open input file!", MB_OK | MB_ICONSTOP);
+		bInterrupted=true;
+	}
+
+	return !bInterrupted;
+}
+#endif
+
+void CEncoderJobProcessingManager::WriteProgress(long lOperationStartTickCount, long lMaxSteps, long lCurSteps)
+{
+	long lCurTime=::GetTickCount();
+	double dProgress=100.*lCurSteps/lMaxSteps;
+	if (dProgress>100) dProgress=100;		// just security
+	if (dProgress<0) dProgress=0;			// just security
+	CString oTopStatusText=m_poJobToProcess->GetDetailedDescriptionForStatusDialog();
+
+	long lElapsedTime=lCurTime-lOperationStartTickCount;
+	long lEstimateEntireTime=(long)((double)(lElapsedTime)/(dProgress/100));
+	long lETA=lEstimateEntireTime-lElapsedTime;
+	CString oElapsedTime(CWindowUtil::GetTimeDescription(lElapsedTime));
+	CString oEntireTime(CWindowUtil::GetTimeDescription(lEstimateEntireTime));
+	CString oETA(CWindowUtil::GetTimeDescription(lETA));
+	CString oBottomStatusText;
+	oBottomStatusText.Format("%.1f %%\n\n%s / %s   -   %s", dProgress, oElapsedTime, oEntireTime, oETA);
+
+	m_poInfoTarget->SetStatus(dProgress, oTopStatusText, oBottomStatusText);
+}
+
+int CEncoderJobProcessingManager::GetAacProfileConstant(CEncoderJob::EAacProfile eAacProfile)
+{
+	switch (eAacProfile)
+	{
+	case CEncoderJob::eAacProfileLc:
+		{
+			return LOW;
+		}
+	default:
+		{
+			ASSERT(false);
+		}
+	case CEncoderJob::eAacProfileMain:
+		{
+			return MAIN;
+		}
+	case CEncoderJob::eAacProfileSsr:
+		{
+			return SSR;
+		}
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/EncoderJobProcessingManager.h
@@ -1,0 +1,52 @@
+// EncoderJobProcessingManager.h: interface for the CEncoderJobProcessingManager class.
+// Author: Torsten Landmann
+//
+// manages the actual processing of one encoder job at a time. Note that this
+// class doesn't properly process encoder jobs that have a file mask set
+// as input file. Callers must filter out these jobs before using this class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ENCODERJOBPROCESSINGMANAGER_H__A1444E93_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ENCODERJOBPROCESSINGMANAGER_H__A1444E93_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "EncoderJob.h"
+#include "ProcessingStartStopPauseInteractable.h"
+
+class CEncoderJobProcessingManager : public CProcessingStartStopPauseInteractable  
+{
+public:
+	CEncoderJobProcessingManager(const CEncoderJob *poJobToProcess);
+	virtual ~CEncoderJobProcessingManager();
+
+	virtual void Start(CProcessingStatusDialogInfoFeedbackCallbackInterface *poInfoTarget);
+
+	virtual void Stop();
+	virtual void Pause();
+
+	enum ECurrentWorkingState
+	{
+		eInitial,
+		eRunning,
+		ePaused,
+		eStopped,
+		eCleanup,
+	} m_eCurrentWorkingState;
+
+private:
+	const CEncoderJob *m_poJobToProcess;
+	CProcessingStatusDialogInfoFeedbackCallbackInterface *m_poInfoTarget;
+
+	// returns true if the job has been completely processed
+	bool DoProcessing();
+
+	void WriteProgress(long lOperationStartTickCount, long lMaxSteps, long lCurSteps);
+
+	static int GetAacProfileConstant(CEncoderJob::EAacProfile eAacProfile);
+};
+
+#endif // !defined(AFX_ENCODERJOBPROCESSINGMANAGER_H__A1444E93_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/EncoderQualityPageDialog.cpp
@@ -1,0 +1,354 @@
+// EncoderQualityPageDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "EncoderQualityPageDialog.h"
+#include "EncoderQualityPropertyPageContents.h"
+#include "WindowUtil.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderQualityPageDialog dialog
+
+
+CEncoderQualityPageDialog::CEncoderQualityPageDialog(
+	const TItemList<CJob*> &oJobsToConfigure,
+	CJobListUpdatable *poListContainer, 
+	CWnd* pParent /*=NULL*/):
+	m_bInitialized(false),
+	m_oJobsToConfigure(oJobsToConfigure),
+	m_poListContainer(poListContainer),
+	m_bIgnoreUpdates(false)
+{
+	//{{AFX_DATA_INIT(CEncoderQualityPageDialog)
+	m_oEditBandwidth = _T("");
+	m_oEditBitRate = _T("");
+	m_iRadioAacProfile = -1;
+	//}}AFX_DATA_INIT
+
+	Create(CEncoderQualityPageDialog::IDD, pParent);
+}
+
+CEncoderQualityPageDialog::~CEncoderQualityPageDialog()
+{
+	UpdateJobs(true, true);
+}
+
+
+void CEncoderQualityPageDialog::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CEncoderQualityPageDialog)
+	DDX_Control(pDX, IDC_CHECKUSETNS, m_ctrlCheckUseTns);
+	DDX_Control(pDX, IDC_CHECKUSELTP, m_ctrlCheckUseLtp);
+	DDX_Control(pDX, IDC_EDITBANDWIDTH, m_ctrlEditBandwidth);
+	DDX_Control(pDX, IDC_EDITBITRATE, m_ctrlEditBitRate);
+	DDX_Control(pDX, IDC_CHECKUSELFE, m_ctrlCheckUseLfe);
+	DDX_Control(pDX, IDC_CHECKMIDSIDE, m_ctrlCheckMidSide);
+	DDX_Text(pDX, IDC_EDITBANDWIDTH, m_oEditBandwidth);
+	DDX_Text(pDX, IDC_EDITBITRATE, m_oEditBitRate);
+	DDX_Radio(pDX, IDC_RADIOAACPROFILELC, m_iRadioAacProfile);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CEncoderQualityPageDialog, CDialog)
+	//{{AFX_MSG_MAP(CEncoderQualityPageDialog)
+	ON_EN_UPDATE(IDC_EDITBITRATE, OnUpdateEditBitRate)
+	ON_EN_UPDATE(IDC_EDITBANDWIDTH, OnUpdateEditBandwidth)
+	ON_EN_KILLFOCUS(IDC_EDITBANDWIDTH, OnKillfocusEditBandWidth)
+	ON_EN_KILLFOCUS(IDC_EDITBITRATE, OnKillfocusEditBitRate)
+	ON_BN_CLICKED(IDC_CHECKMIDSIDE, OnCheckMidSide)
+	ON_BN_CLICKED(IDC_CHECKUSELFE, OnCheckUseLfe)
+	ON_BN_CLICKED(IDC_CHECKUSELTP, OnCheckUseLtp)
+	ON_BN_CLICKED(IDC_CHECKUSETNS, OnCheckUseTns)
+	ON_BN_CLICKED(IDC_RADIOAACPROFILELC, OnRadioAacProfileLc)
+	ON_BN_CLICKED(IDC_RADIOAACPROFILEMAIN, OnRadioAacProfileMain)
+	ON_BN_CLICKED(IDC_RADIOAACPROFILESSR, OnRadioAacProfileSsr)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderQualityPageDialog message handlers
+
+BOOL CEncoderQualityPageDialog::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	// TODO: Add extra initialization here
+	m_bInitialized=true;
+
+	// show our contents
+	ApplyPageContents(ParseJobs());
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CEncoderQualityPageDialog::OnUpdateEditBitRate() 
+{
+	// TODO: If this is a RICHEDIT control, the control will not
+	// send this notification unless you override the CDialog::OnInitDialog()
+	// function to send the EM_SETEVENTMASK message to the control
+	// with the ENM_UPDATE flag ORed into the lParam mask.
+	
+	// TODO: Add your control notification handler code here
+	CWindowUtil::ForceNumericContent(&m_ctrlEditBitRate, false);
+}
+
+void CEncoderQualityPageDialog::OnUpdateEditBandwidth() 
+{
+	// TODO: If this is a RICHEDIT control, the control will not
+	// send this notification unless you override the CDialog::OnInitDialog()
+	// function to send the EM_SETEVENTMASK message to the control
+	// with the ENM_UPDATE flag ORed into the lParam mask.
+	
+	// TODO: Add your control notification handler code here
+	CWindowUtil::ForceNumericContent(&m_ctrlEditBandwidth, false);
+}
+
+
+bool CEncoderQualityPageDialog::GetPageContents(CEncoderQualityPropertyPageContents &oTarget)
+{
+	if (!UpdateData(TRUE)) return false;
+
+	oTarget.m_oBitRate.SetContent(m_oEditBitRate);
+	oTarget.m_oBandwidth.SetContent(m_oEditBandwidth);
+	oTarget.m_oAllowMidSide.SetCheckCode(m_ctrlCheckMidSide.GetCheck());
+	oTarget.m_oUseTns.SetCheckCode(m_ctrlCheckUseTns.GetCheck());
+	oTarget.m_oUseLtp.SetCheckCode(m_ctrlCheckUseLtp.GetCheck());
+	oTarget.m_oUseLfe.SetCheckCode(m_ctrlCheckUseLfe.GetCheck());
+	oTarget.m_oAacProfile.GetFromRadioGroupVariable(m_iRadioAacProfile, 3);
+
+	return true;
+}
+
+void CEncoderQualityPageDialog::ApplyPageContents(const CEncoderQualityPropertyPageContents &oPageContents)
+{
+	// disabled since it could cause error messages - we're overwriting everything anyway
+	//UpdateData(TRUE);
+
+	m_oEditBitRate=oPageContents.m_oBitRate.GetContent();
+	m_oEditBandwidth=oPageContents.m_oBandwidth.GetContent();
+	oPageContents.m_oAllowMidSide.ApplyCheckCodeToButton(&m_ctrlCheckMidSide);
+	oPageContents.m_oUseTns.ApplyCheckCodeToButton(&m_ctrlCheckUseTns);
+	oPageContents.m_oUseLtp.ApplyCheckCodeToButton(&m_ctrlCheckUseLtp);
+	oPageContents.m_oUseLfe.ApplyCheckCodeToButton(&m_ctrlCheckUseLfe);
+	oPageContents.m_oAacProfile.ApplyToRadioGroupVariable(m_iRadioAacProfile);
+
+	if (m_bInitialized)
+	{
+		UpdateData(FALSE);
+	}
+}
+
+CEncoderQualityPropertyPageContents CEncoderQualityPageDialog::ParseJobs()
+{
+	CEncoderQualityPropertyPageContents oToReturn;
+	bool bFirstRun=true;
+
+	CBListReader oReader(m_oJobsToConfigure);
+	CJob *poCurJob;
+	while (m_oJobsToConfigure.GetNextElemContent(oReader, poCurJob))
+	{
+		if (!poCurJob->GetJobType()==CJob::eEncoderJob)
+		{
+			// must all be encoder jobs
+			ASSERT(false);
+		}
+		CEncoderJob *poEncoderJob=poCurJob->GetEncoderJob();
+		if (bFirstRun)
+		{
+			oToReturn=poEncoderJob->GetQualityPageContents();
+			bFirstRun=false;
+		}
+		else
+		{
+			oToReturn*=poEncoderJob->GetQualityPageContents();
+		}
+	}
+
+	return oToReturn;
+}
+
+void CEncoderQualityPageDialog::ModifyJobs(const CEncoderQualityPropertyPageContents &oPageContents)
+{
+	CBListReader oReader(m_oJobsToConfigure);
+	CJob *poCurJob;
+	while (m_oJobsToConfigure.GetNextElemContent(oReader, poCurJob))
+	{
+		if (!poCurJob->GetJobType()==CJob::eEncoderJob)
+		{
+			// must all be encoder jobs
+			ASSERT(false);
+		}
+		CEncoderJob *poEncoderJob=poCurJob->GetEncoderJob();
+		poEncoderJob->ApplyQualityPageContents(oPageContents);
+	}
+}
+
+void CEncoderQualityPageDialog::UpdateJobs(bool bFinishCheckBoxSessions, bool bDlgDestructUpdate)
+{
+	if (::IsWindow(*this) && !m_bIgnoreUpdates)
+	{
+		CEncoderQualityPropertyPageContents oPageContents;
+		if (GetPageContents(oPageContents))
+		{
+			if (bFinishCheckBoxSessions)
+			{
+				FinishCurrentCheckBoxSessionIfNecessary();
+			}
+
+			ModifyJobs(oPageContents);
+
+			// make changes visible
+			m_poListContainer->ReFillInJobListCtrl();
+		}
+	}
+
+	if (bDlgDestructUpdate)
+	{
+		m_bIgnoreUpdates=true;
+	}
+}
+
+void CEncoderQualityPageDialog::OnKillfocusEditBandWidth() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderQualityPageDialog::OnKillfocusEditBitRate() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderQualityPageDialog::OnCheckMidSide() 
+{
+	// TODO: Add your control notification handler code here
+	ProcessCheckBoxClick(&m_ctrlCheckMidSide, eAllowMidSide);
+}
+
+void CEncoderQualityPageDialog::OnCheckUseLfe() 
+{
+	// TODO: Add your control notification handler code here
+	ProcessCheckBoxClick(&m_ctrlCheckUseLfe, eUseLfe);
+}
+
+void CEncoderQualityPageDialog::ProcessCheckBoxClick(CButton *poCheckBox, ETypeOfCheckBox eTypeOfCheckBox)
+{
+	int iCheckState=poCheckBox->GetCheck();
+	if (iCheckState==2)
+	{
+		// 3rd state
+		if (m_eCurCheckBox!=eTypeOfCheckBox)
+		{
+			// must not be like this
+			ASSERT(false);
+		}
+		else
+		{
+			m_oCheckStateChangeStateSaver.RestoreJobs(m_oJobsToConfigure);
+			FinishCurrentCheckBoxSessionIfNecessary();
+		}
+	}
+	else
+	{
+		if (m_eCurCheckBox!=eTypeOfCheckBox)
+		{
+			FinishCurrentCheckBoxSessionIfNecessary();
+			// current checkbox is now set to eNone
+
+			m_eCurCheckBox=eTypeOfCheckBox;
+
+			m_oCheckStateChangeStateSaver.SaveJobs(m_oJobsToConfigure);
+		}
+	}
+
+	UpdateJobs(false);
+}
+
+void CEncoderQualityPageDialog::FinishCurrentCheckBoxSessionIfNecessary()
+{
+	switch (m_eCurCheckBox)
+	{
+	case eAllowMidSide:
+		{
+			FinishCheckBoxSessionIfNecessary(&m_ctrlCheckMidSide);
+			break;
+		}
+	case eUseTns:
+		{
+			FinishCheckBoxSessionIfNecessary(&m_ctrlCheckUseTns);
+			break;
+		}
+	case eUseLtp:
+		{
+			FinishCheckBoxSessionIfNecessary(&m_ctrlCheckUseLtp);
+			break;
+		}
+	case eUseLfe:
+		{
+			FinishCheckBoxSessionIfNecessary(&m_ctrlCheckUseLfe);
+			break;
+		}
+	case eNone:
+		{
+			// nothing
+			break;
+		}
+	default:
+		{
+			// unkown type of check box
+			break;
+		}
+	}
+	m_eCurCheckBox=eNone;
+}
+
+void CEncoderQualityPageDialog::FinishCheckBoxSessionIfNecessary(CButton *poCheckBox)
+{
+	int iCurCheck=poCheckBox->GetCheck();
+	if (iCurCheck<2)
+	{
+		poCheckBox->SetButtonStyle(BS_AUTOCHECKBOX);
+	}
+}
+
+void CEncoderQualityPageDialog::OnCheckUseLtp() 
+{
+	// TODO: Add your control notification handler code here
+	ProcessCheckBoxClick(&m_ctrlCheckUseLtp, eUseLtp);
+}
+
+void CEncoderQualityPageDialog::OnCheckUseTns() 
+{
+	// TODO: Add your control notification handler code here
+	ProcessCheckBoxClick(&m_ctrlCheckUseTns, eUseTns);
+}
+
+void CEncoderQualityPageDialog::OnRadioAacProfileLc() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderQualityPageDialog::OnRadioAacProfileMain() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
+void CEncoderQualityPageDialog::OnRadioAacProfileSsr() 
+{
+	// TODO: Add your control notification handler code here
+	UpdateJobs();
+}
+
--- /dev/null
+++ b/wingui/EncoderQualityPageDialog.h
@@ -1,0 +1,109 @@
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ENCODERQUALITYPAGEDIALOG_H__7B47B264_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ENCODERQUALITYPAGEDIALOG_H__7B47B264_0FF8_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// EncoderQualityPageDialog.h : header file
+//
+
+#include "JobListUpdatable.h"
+#include "JobListsToConfigureSaver.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CEncoderQualityPageDialog dialog
+
+class CEncoderQualityPageDialog : public CDialog
+{
+// Construction
+public:
+	CEncoderQualityPageDialog(const TItemList<CJob*> &oJobsToConfigure, CJobListUpdatable *poListContainer, CWnd* pParent = NULL);   // standard constructor
+	virtual ~CEncoderQualityPageDialog();
+
+// Dialog Data
+	//{{AFX_DATA(CEncoderQualityPageDialog)
+	enum { IDD = IDD_ENCODERQUALITYPAGEDIALOG };
+	CButton	m_ctrlCheckUseTns;
+	CButton	m_ctrlCheckUseLtp;
+	CEdit	m_ctrlEditBandwidth;
+	CEdit	m_ctrlEditBitRate;
+	CButton	m_ctrlCheckUseLfe;
+	CButton	m_ctrlCheckMidSide;
+	CString	m_oEditBandwidth;
+	CString	m_oEditBitRate;
+	int		m_iRadioAacProfile;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CEncoderQualityPageDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+public:
+	// returns false in case of errors
+	bool GetPageContents(CEncoderQualityPropertyPageContents &oTarget);
+	void ApplyPageContents(const CEncoderQualityPropertyPageContents &oPageContents);
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CEncoderQualityPageDialog)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnUpdateEditBitRate();
+	afx_msg void OnUpdateEditBandwidth();
+	afx_msg void OnKillfocusEditBandWidth();
+	afx_msg void OnKillfocusEditBitRate();
+	afx_msg void OnCheckMidSide();
+	afx_msg void OnCheckUseLfe();
+	afx_msg void OnCheckUseLtp();
+	afx_msg void OnCheckUseTns();
+	afx_msg void OnRadioAacProfileLc();
+	afx_msg void OnRadioAacProfileMain();
+	afx_msg void OnRadioAacProfileSsr();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+private:
+	bool m_bInitialized;
+
+	TItemList<CJob*> m_oJobsToConfigure;
+
+	CJobListUpdatable *m_poListContainer;
+
+	CEncoderQualityPropertyPageContents ParseJobs();
+	void ModifyJobs(const CEncoderQualityPropertyPageContents &oPageContents);
+
+	// called when changes have been made in the dialog and are to
+	// be synchronized with both "data holders"
+	void UpdateJobs(bool bFinishCheckBoxSessions=true, bool bDlgDestructUpdate=false);
+	bool m_bIgnoreUpdates;
+
+
+	// these members are used for managing the check box controls and the
+	// changes that are made with them in the dialog
+	enum ETypeOfCheckBox
+	{
+		eNone,
+		eAllowMidSide,
+		eUseTns,
+		eUseLtp,
+		eUseLfe,
+	} m_eCurCheckBox;
+	CJobListsToConfigureSaver m_oCheckStateChangeStateSaver;
+	void ProcessCheckBoxClick(CButton *poCheckBox, ETypeOfCheckBox eTypeOfCheckBox);
+	void FinishCurrentCheckBoxSessionIfNecessary();
+	void FinishCheckBoxSessionIfNecessary(CButton *poCheckBox);
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ENCODERQUALITYPAGEDIALOG_H__7B47B264_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/EncoderQualityPropertyPageContents.cpp
@@ -1,0 +1,44 @@
+// EncoderQualityPropertyPageContents.cpp: implementation of the CEncoderQualityPropertyPageContents class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "EncoderQualityPropertyPageContents.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CEncoderQualityPropertyPageContents::CEncoderQualityPropertyPageContents()
+{
+}
+
+CEncoderQualityPropertyPageContents::CEncoderQualityPropertyPageContents(const CEncoderQualityPropertyPageContents &oSource)
+{
+	*this=oSource;
+}
+
+CEncoderQualityPropertyPageContents::~CEncoderQualityPropertyPageContents()
+{
+}
+
+CEncoderQualityPropertyPageContents& CEncoderQualityPropertyPageContents::operator*=(const CEncoderQualityPropertyPageContents &oRight)
+{
+	m_oBitRate*=oRight.m_oBitRate;
+	m_oBandwidth*=oRight.m_oBandwidth;;
+	m_oAllowMidSide*=oRight.m_oAllowMidSide;
+	m_oUseTns*=oRight.m_oUseTns;
+	m_oUseLtp*=oRight.m_oUseLtp;
+	m_oUseLfe*=oRight.m_oUseLfe;
+	m_oAacProfile*=oRight.m_oAacProfile;
+
+	return *this;
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/EncoderQualityPropertyPageContents.h
@@ -1,0 +1,40 @@
+// EncoderQualityPropertyPageContents.h: interface for the CEncoderQualityPropertyPageContents class.
+// Author: Torsten Landmann
+//
+// encapsulates the content of the property page "quality" including
+// possible 3rd states of all controls
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ENCODERQUALITYPROPERTYPAGECONTENTS_H__7B47B26A_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ENCODERQUALITYPROPERTYPAGECONTENTS_H__7B47B26A_0FF8_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "AbstractPropertyPageContents.h"
+#include "PageEditCtrlContent.h"
+#include "PageCheckboxCtrlContent.h"
+#include "PageRadioGroupCtrlContent.h"
+
+class CEncoderQualityPropertyPageContents : public CAbstractPropertyPageContents  
+{
+public:
+	CEncoderQualityPropertyPageContents();
+	CEncoderQualityPropertyPageContents(const CEncoderQualityPropertyPageContents &oSource);	// copy constructor
+	virtual ~CEncoderQualityPropertyPageContents();
+
+	CPageEditCtrlContent m_oBitRate;
+	CPageEditCtrlContent m_oBandwidth;
+	CPageCheckboxCtrlContent m_oAllowMidSide;
+	CPageCheckboxCtrlContent m_oUseTns;
+	CPageCheckboxCtrlContent m_oUseLtp;
+	CPageCheckboxCtrlContent m_oUseLfe;
+	CPageRadioGroupCtrlContent m_oAacProfile;
+
+	// with this operator pages for several jobs can be "merged"
+	CEncoderQualityPropertyPageContents& operator*=(const CEncoderQualityPropertyPageContents &oRight);
+};
+
+#endif // !defined(AFX_ENCODERQUALITYPROPERTYPAGECONTENTS_H__7B47B26A_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/FaacWinguiProgramSettings.cpp
@@ -1,0 +1,83 @@
+// FaacWinguiProgramSettings.cpp: implementation of the CFaacWinguiProgramSettings class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "FaacWinguiProgramSettings.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CFaacWinguiProgramSettings::CFaacWinguiProgramSettings():
+	m_oDefaultEncSourceDir(""),
+	m_oDefaultEncTargetDir(""),
+	m_lDefaultEncBitRate(64000),
+	m_lDefaultEncBandwith(18000),
+	m_bDefaultEncAllowMidSide(true),
+	m_bDefaultEncUseTns(true),
+	m_bDefaultEncUseLtp(true),
+	m_bDefaultEncUseLfe(false),
+	m_eDefaultEncAacProfile(CEncoderJob::eAacProfileMain),
+	m_bDefaultEncCopyrightBit(false),
+	m_oDefaultEncEncodedBy(""),
+	m_oDefaultEncComment("")
+{
+	// use the temporary directory as target by standard if not otherwise
+	// specified
+	if (m_oDefaultEncTargetDir.IsEmpty())
+	{
+		CString oTempDir;
+		strcpy(oTempDir.GetBuffer(1000), getenv("TEMP"));
+		oTempDir.ReleaseBuffer();
+		m_oDefaultEncTargetDir=oTempDir;
+	}
+	if (m_oDefaultEncTargetDir.IsEmpty())
+	{
+		CString oTempDir;
+		strcpy(oTempDir.GetBuffer(1000), getenv("TMP"));
+		oTempDir.ReleaseBuffer();
+		m_oDefaultEncTargetDir=oTempDir;
+	}
+}
+
+CFaacWinguiProgramSettings::~CFaacWinguiProgramSettings()
+{
+
+}
+
+void CFaacWinguiProgramSettings::ApplyToJob(CJob &oJob) const
+{
+	CEncoderJob *poEncoderJob=oJob.GetEncoderJob();
+	if (poEncoderJob==0)
+	{
+		ASSERT(false);
+		return;
+	}
+
+	ApplyToJob(*poEncoderJob);
+}
+
+void CFaacWinguiProgramSettings::ApplyToJob(CEncoderJob &oJob) const
+{
+	oJob.GetFiles().SetSourceFileDirectory(m_oDefaultEncSourceDir);
+	oJob.GetFiles().SetTargetFileDirectory(m_oDefaultEncTargetDir);
+	oJob.SetBitRate(m_lDefaultEncBitRate);
+	oJob.SetBandwidth(m_lDefaultEncBandwith);
+	oJob.SetAllowMidside(m_bDefaultEncAllowMidSide);
+	oJob.SetUseTns(m_bDefaultEncUseTns);
+	oJob.SetUseLtp(m_bDefaultEncUseLtp);
+	oJob.SetUseLfe(m_bDefaultEncUseLfe);
+	oJob.SetAacProfile(m_eDefaultEncAacProfile);
+	oJob.GetTargetFileId3Info().SetCopyright(m_bDefaultEncCopyrightBit);
+	oJob.GetTargetFileId3Info().SetEncodedBy(m_oDefaultEncEncodedBy);
+	oJob.GetTargetFileId3Info().SetComment(m_oDefaultEncComment);
+}
--- /dev/null
+++ b/wingui/FaacWinguiProgramSettings.h
@@ -1,0 +1,42 @@
+// FaacWinguiProgramSettings.h: interface for the CFaacWinguiProgramSettings class.
+// Author: Torsten Landmann
+//
+// container for program defaults
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_FAACWINGUIPROGRAMSETTINGS_H__A1444E89_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_FAACWINGUIPROGRAMSETTINGS_H__A1444E89_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "Job.h"
+#include "EncoderJob.h"
+
+class CFaacWinguiProgramSettings  
+{
+public:
+	CFaacWinguiProgramSettings();
+	virtual ~CFaacWinguiProgramSettings();
+
+	CString m_oDefaultEncSourceDir;
+	CString m_oDefaultEncTargetDir;
+	long m_lDefaultEncBitRate;
+	long m_lDefaultEncBandwith;
+	bool m_bDefaultEncAllowMidSide;
+	bool m_bDefaultEncUseTns;
+	bool m_bDefaultEncUseLtp;
+	bool m_bDefaultEncUseLfe;
+	CEncoderJob::EAacProfile m_eDefaultEncAacProfile;
+	bool m_bDefaultEncCopyrightBit;
+	CString m_oDefaultEncEncodedBy;
+	CString m_oDefaultEncComment;
+
+	// that's just necessary quite often: copy the defaults to a (new) job
+	void ApplyToJob(CJob &oJob) const;
+	void ApplyToJob(CEncoderJob &oJob) const;
+};
+
+#endif // !defined(AFX_FAACWINGUIPROGRAMSETTINGS_H__A1444E89_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/FileListQueryManager.cpp
@@ -1,0 +1,77 @@
+// FileListQueryManager.cpp: implementation of the CFileListQueryManager class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "FileListQueryManager.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CFileListQueryManager::CFileListQueryManager()
+{
+
+}
+
+CFileListQueryManager::~CFileListQueryManager()
+{
+
+}
+
+TItemList<CString> CFileListQueryManager::GetFilePaths(bool m_bOpenMode, const CString *poDefaultFile, const CString &oDefaultExtension, const CString &oExtensions)
+{
+	TItemList<CString> toReturn;
+	if (!m_bOpenMode)
+	{
+		// not supported
+		ASSERT(false);
+		return toReturn;
+	}
+
+	CFileDialog oOpenDialog(
+		m_bOpenMode? TRUE : FALSE,					// file open mode
+		oDefaultExtension,							// default extension
+		(poDefaultFile!=0 ? *poDefaultFile : (LPCTSTR)0),	// default file
+		OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT,
+		oExtensions);
+
+	// for multi selection we must set our own target pointer
+	int iFileBufferSize=8096;
+	oOpenDialog.m_ofn.lpstrFile=new char[iFileBufferSize];
+	oOpenDialog.m_ofn.nMaxFile=iFileBufferSize;
+	// the dialog crashes if we don't zero out the buffer
+	memset(oOpenDialog.m_ofn.lpstrFile, 0, iFileBufferSize);
+
+	if (oOpenDialog.DoModal()==IDOK)
+	{
+		// the files have been opened	
+		POSITION position=oOpenDialog.GetStartPosition();
+		while (position!=0)
+		{
+			CString oCurFile=oOpenDialog.GetNextPathName(position);
+			toReturn.AddNewElem(oCurFile);
+		}
+	}
+	else
+	{
+		// user abort or error
+		if (CommDlgExtendedError()!=0)
+		{
+			// an error occured
+			AfxMessageBox(IDS_ErrorDuringFileSelection);
+		}
+	}
+
+	delete[] oOpenDialog.m_ofn.lpstrFile;
+
+	return toReturn;
+}
--- /dev/null
+++ b/wingui/FileListQueryManager.h
@@ -1,0 +1,27 @@
+// FileListQueryManager.h: interface for the CFileListQueryManager class.
+// Author: Torsten Landmann
+//
+// this class is a wrapper around CFileDialog and is used to let the user
+// select several files at a time
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_FILELISTQUERYMANAGER_H__A1444E8A_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_FILELISTQUERYMANAGER_H__A1444E8A_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "TItemList.h"
+
+class CFileListQueryManager  
+{
+public:
+	CFileListQueryManager();
+	virtual ~CFileListQueryManager();
+
+	static TItemList<CString> GetFilePaths(bool m_bOpenMode=true, const CString *poDefaultFile=0, const CString &oDefaultExtension="", const CString &oExtensions="All Files (*.*)|*.*||");
+};
+
+#endif // !defined(AFX_FILELISTQUERYMANAGER_H__A1444E8A_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/FileMaskAssembler.cpp
@@ -1,0 +1,44 @@
+// FileMaskAssembler.cpp: implementation of the CFileMaskAssembler class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "FileMaskAssembler.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CFileMaskAssembler::CFileMaskAssembler()
+{
+
+}
+
+CFileMaskAssembler::~CFileMaskAssembler()
+{
+
+}
+
+CString CFileMaskAssembler::GetFileMask(TItemList<int> &oFilterStringEntries)
+{
+	// assemble the filter string
+	CString oFilter;
+	long lCurIndex=1;
+	int iCurItem;
+	while (oFilterStringEntries.GetElemContent(lCurIndex++, iCurItem))
+	{
+		// accept aac files
+		CString oBuf;
+		oBuf.LoadString(iCurItem);
+		oFilter+=oBuf+"|";
+	}
+	oFilter+="||";
+	return oFilter;
+}
--- /dev/null
+++ b/wingui/FileMaskAssembler.h
@@ -1,0 +1,31 @@
+// FileMaskAssembler.h: interface for the CFileMaskAssembler class.
+// Author: Torsten Landmann
+//
+// This is an interesting class. It assembles a file mask for CFileDialog
+// from a list of integers. These integers point to entries in the
+// string table and have the following format: "Wav Files (*.wav)|*.wav"
+// without quotation marks; All list items are processed from index 1 until
+// the first missing index is found;
+// the string that's returned can be used without modification (provided
+// the substrings specified were okay)
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_FILEMASKASSEMBLER_H__A1444E8D_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_FILEMASKASSEMBLER_H__A1444E8D_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CFileMaskAssembler  
+{
+public:
+	CFileMaskAssembler();
+	virtual ~CFileMaskAssembler();
+
+	// see topmost comment in this file
+	static CString GetFileMask(TItemList<int> &oFilterStringEntries);
+};
+
+#endif // !defined(AFX_FILEMASKASSEMBLER_H__A1444E8D_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/FilePathCalc.cpp
@@ -1,0 +1,484 @@
+// FilePathCalc.cpp: implementation of the CFilePathCalc class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "FilePathCalc.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CFilePathCalc::CFilePathCalc()
+{
+
+}
+
+CFilePathCalc::~CFilePathCalc()
+{
+
+}
+
+bool CFilePathCalc::GetRelativePosition(const CString &oFrom, const CString &oTo, CString &oRelativePath)
+{
+	CString oFromPath(oFrom);
+	CString oToPath(oTo);
+
+	oFromPath.MakeLower();
+	oToPath.MakeLower();
+
+	// extract raw paths
+	{
+		if (!MakePath(oFromPath) || !MakePath(oToPath))
+		{
+			return false;
+		}
+	}
+
+	// compare drive letters
+	{
+		CString oFromDrive;
+		CString oToDrive;
+		if (!ExtractDrive(oFromPath, oFromDrive) ||
+			!ExtractDrive(oToPath, oToDrive))
+		{
+			return false;
+		}
+
+		if (oFromDrive!=oToDrive)
+		{
+			// drive letters are different
+
+			oRelativePath=oTo;
+			return true;
+		}
+	}
+
+	// determine relative path
+	{
+		CString oUpPath;
+		CString oDownPath;
+		CString oBuf1, oBuf2;
+
+		// make paths to same depth
+		while (CountBackSlashes(oFromPath)>CountBackSlashes(oToPath))
+		{
+			oUpPath+="..\\";
+			if (!RemoveOneDirFromEnd(oFromPath, oBuf1))
+			{
+				return false;
+			}
+		}
+		while (CountBackSlashes(oToPath)>CountBackSlashes(oFromPath))
+		{
+			if (!RemoveOneDirFromEnd(oToPath, oBuf2))
+			{
+				return false;
+			}
+
+			oDownPath=oBuf2+oDownPath;
+		}
+
+		// keep track how deep we must go back to find
+		// the directory from which we can go towards
+		// the target directory
+		while (oFromPath!=oToPath)
+		{
+			oUpPath+="..\\";
+
+			if (!RemoveOneDirFromEnd(oFromPath, oBuf1))
+			{
+				return false;
+			}
+			if (!RemoveOneDirFromEnd(oToPath, oBuf2))
+			{
+				return false;
+			}
+
+			oDownPath=oBuf2+oDownPath;
+		}
+
+		CString oToFileName;
+		if (!ExtractFileName(oTo, oToFileName))
+		{
+			return false;
+		}
+
+		oRelativePath=oUpPath+oDownPath+oToFileName;
+	}
+
+	return true;
+}
+
+bool CFilePathCalc::ApplyRelativePath(
+	const CString &oRelativePath, CString &oAbsolutePath)
+{
+	CString oRelativePathCpy(oRelativePath);
+	if (oRelativePathCpy.Find(':')==1)
+	{
+		// relative path contains a drive specificiation
+
+		oAbsolutePath=oRelativePath;
+
+		return true;
+	}
+
+	// delete ".\"s
+	{
+		while (oRelativePathCpy.Find(".\\")==0)
+		{
+			oRelativePathCpy.Delete(0, 2);
+		}
+	}
+
+	if (oRelativePathCpy.Find('\\')==0)
+	{
+		// relative path begins with a back slash
+
+		CString oDrive;
+		if (!ExtractDrive(oAbsolutePath, oDrive))
+		{
+			return false;
+		}
+
+		oAbsolutePath=oDrive+oRelativePathCpy;
+		
+		return true;
+	}
+
+	CString oBuf1;
+	while (oRelativePathCpy.Find("..\\")!=-1)
+	{
+		// delete first three characters
+		oRelativePathCpy.Delete(0, 3);
+
+		if (!RemoveOneDirFromEnd(oAbsolutePath, oBuf1))
+		{
+			return false;
+		}
+	}
+
+	oAbsolutePath+=oRelativePathCpy;
+
+	return true;
+}
+
+
+bool CFilePathCalc::MakePath(CString &oStr, bool bAssumeDirectory)
+{
+	long lCharPos, lCharPos2;
+
+	if ((lCharPos=oStr.Find(':'))!=-1)
+	{
+		// there is a colon in the string
+
+		if (oStr.Find(':', lCharPos+1)!=-1)
+		{
+			// error case: more than one colon in the string
+			return false;
+		}
+
+		if (oStr.GetAt(lCharPos+1)!='\\')
+		{
+			// the colon is not followed by a back slash
+			if (oStr.GetLength()>lCharPos+2)
+			{
+				// error case
+				// something like "c:windows" was passed on
+				return false;
+			}
+			else
+			{
+				// something like "c:" was passed on
+				oStr+="\\";
+				return true;
+			}
+		}
+		else
+		{
+			// the colon is followed by a back slash
+
+			if ((lCharPos=oStr.ReverseFind('.'))!=-1)
+			{
+				// the path description contains at least one dot
+
+				if ((lCharPos2=oStr.ReverseFind('\\'))!=-1)
+				{
+					if (lCharPos2>lCharPos || bAssumeDirectory)
+					{
+						// there is a back slash behind the last
+						// dot or we shall assume there is one
+
+						if (oStr.GetAt(oStr.GetLength()-1)!='\\')
+						{
+							// last character is not yet a backslash but
+							// it must become one
+							
+							// append a back slash
+							oStr+='\\';
+							
+							return true;
+						}
+
+						// path name is ok
+						return true;
+					}
+					else
+					{
+						// there is no back slash behind the last
+						// dot -> the path contains a file name;
+
+						// remove the file name;
+						// terminate behind last back slash
+						oStr.GetBuffer(0);
+						oStr.SetAt(lCharPos2+1, '\0');
+						oStr.ReleaseBuffer();
+						return true;
+					}
+				}
+				else
+				{
+					// error case: no backslash in path name
+					return false;
+				}
+			}
+			else
+			{
+				// the path description does not contain a dot
+
+				if (oStr.GetAt(oStr.GetLength()-1)!='\\')
+				{
+					// last character is not a back slash
+
+					// append a back slash
+					oStr+='\\';
+					return true;
+				}
+				else
+				{
+					// last character is a back slash
+					return true;
+				}
+			}
+		}
+	}
+	else
+	{
+		// error case: no colon in string
+		return false;
+	}
+}
+
+bool CFilePathCalc::ExtractFileName(const CString &oPath, CString &oFileName)
+{
+	if (&oPath!=&oFileName)
+	{
+		oFileName=oPath;
+	}
+
+	long lBackSlashPos=oFileName.ReverseFind('\\');
+	if (lBackSlashPos==-1)
+	{
+		// the path did not contain a back slash
+
+		if (oFileName.Find(':')!=-1)
+		{
+			// the path contains a drive letter
+
+			// delete first two characters
+			oFileName.Delete(0, 2);
+
+			return true;
+		}
+		else
+		{
+			// the path did not contain a colon
+
+			return true;
+		}
+	}
+	else
+	{
+		// the path contains at least one backslash
+
+		// delete all characters up to the last back slash
+		oFileName.Delete(0, lBackSlashPos+1);
+
+		return true;
+	}
+}
+
+bool CFilePathCalc::ExtractDrive(const CString &oPath, CString &oDrive)
+{
+	if (&oPath!=&oDrive)
+	{
+		oDrive=oPath;
+	}
+
+	if (oDrive.Find(':')==-1)
+	{
+		return false;
+	}
+
+	oDrive.GetBuffer(0);
+	oDrive.SetAt(2, '\0');
+	oDrive.ReleaseBuffer();
+
+	return true;
+}
+
+bool CFilePathCalc::SplitFileAndExtension(const CString &oFileName, CString &oSimpleFileName, CString &oExtension)
+{
+	int iLastBackslashPos=oFileName.ReverseFind('\\');
+	int iLastDotPos=oFileName.ReverseFind('.');
+	int iStringLength=oFileName.GetLength();
+	
+	oSimpleFileName=oFileName;
+	if (iLastBackslashPos>=0 && iLastDotPos>=0 && iLastBackslashPos>iLastDotPos)
+	{
+		// the last dot is BEFORE the last backslash
+		oExtension.Empty();
+		return true;
+	}
+	
+	if (iLastDotPos==-1)
+	{
+		// there is no dot	
+		oExtension.Empty();
+		return true;
+	}
+	else
+	{
+		// there is a dot
+		oSimpleFileName=oFileName;
+		oExtension=oSimpleFileName.Mid(iLastDotPos+1, iStringLength-iLastDotPos-1);
+		oSimpleFileName.Delete(iLastDotPos, iStringLength-iLastDotPos);
+		return true;
+	}
+
+	return false;
+}
+
+bool CFilePathCalc::IsValidFileMask(const CString &oFileMask, bool bAcceptDirectories)
+{
+	CString oFileName;
+	if (!ExtractFileName(oFileMask, oFileName)) return false;
+	if (!bAcceptDirectories && oFileName!=oFileMask) return false;		// contains a directory?
+
+	if (oFileName.IsEmpty()) return false;		// "too short"
+
+	// make sure there's at least one joker
+	CString oFileNameTemp(oFileName);
+	FilterString(oFileNameTemp, "*?");
+	if (oFileNameTemp.IsEmpty()) return false;
+
+	CString oTemp(oFileName);
+	FilterStringInverse(oTemp, "/\\:\"<>|");		// these two are invalid for files but not for filters: ?*
+	if (oFileName!=oTemp) return false;			// file path contained invalid characters
+	
+	// make sure no characters are between an asterisk and the next period
+	int iCurPos=oFileName.Find('*');
+	while (iCurPos>=0 && iCurPos<oFileName.GetLength()-1)
+	{
+		if (oFileName[iCurPos+1]!='.') return false;
+		iCurPos=oFileName.Find('*', iCurPos+1);
+	}
+
+	// make sure the file doesn't end with a period
+	if (oFileName[oFileName.GetLength()-1]=='.') return false;
+
+	// make sure the extension doesn't contain spaces
+	{
+		CString oFileNameRaw;
+		CString oExtension;
+		if (!SplitFileAndExtension(oFileName, oFileNameRaw, oExtension)) return false;
+		FilterString(oExtension, " ");
+		if (!oExtension.IsEmpty()) return false;		// extension contains spaces
+	}
+
+	// passed all tests
+	return true;
+}
+
+bool CFilePathCalc::RemoveOneDirFromEnd(CString &oPath, CString &oRemoved)
+{
+	oRemoved=oPath;
+
+	// delete last back slash
+	oPath.GetBuffer(0);
+	oPath.SetAt(oPath.ReverseFind('\\'), '\0');
+	oPath.ReleaseBuffer();
+	
+	long lLastBackSlashPos=
+		oPath.ReverseFind('\\');
+	if (lLastBackSlashPos==-1)
+	{
+		// error: no further back slash
+		return false;
+	}
+
+	// truncate behind last back slash
+	oPath.GetBuffer(0);
+	oPath.SetAt(lLastBackSlashPos+1, '\0');
+	oPath.ReleaseBuffer();
+
+	oRemoved.Delete(0, lLastBackSlashPos+1);
+
+	return true;
+}
+
+long CFilePathCalc::CountBackSlashes(const CString &oPath)
+{
+	long lCount=0;
+	long lCurPos=0;
+	CString oDummy(oPath);
+	while ((lCurPos=oDummy.Find('\\', lCurPos+1))!=-1)
+	{
+		lCount++;
+	}
+	
+	return lCount;
+}
+
+void CFilePathCalc::FilterString(CString &oString, const CString &oAcceptedChars)
+{
+	long lCurPos=0;
+	while (lCurPos<oString.GetLength())
+	{
+		if (oAcceptedChars.Find(oString.GetAt(lCurPos))!=-1)
+		{
+			// character is ok
+			lCurPos++;
+		}
+		else
+		{
+			// character is not ok
+			oString.Delete(lCurPos);
+		}
+	}
+}
+
+void CFilePathCalc::FilterStringInverse(CString &oString, const CString &oCharsToRemove)
+{
+	long lCurPos=0;
+	while (lCurPos<oString.GetLength())
+	{
+		if (oCharsToRemove.Find(oString.GetAt(lCurPos))==-1)
+		{
+			// character is ok
+			lCurPos++;
+		}
+		else
+		{
+			// character is not ok
+			oString.Delete(lCurPos);
+		}
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/FilePathCalc.h
@@ -1,0 +1,138 @@
+// FilePathCalc.h: interface for the CFilePathCalc class.
+// this class is used to provide access to certain procedures
+// for handling file paths
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_FILEPATHCALC_H__B9F42A01_49AE_11D3_A724_50DB50C10057__INCLUDED_)
+#define AFX_FILEPATHCALC_H__B9F42A01_49AE_11D3_A724_50DB50C10057__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CFilePathCalc  
+{
+public:
+	CFilePathCalc();
+	virtual ~CFilePathCalc();
+
+	// oFrom may be a path or a file name
+	// oTo should be a file name
+	// examples:
+	// 1.:	oFrom:	"c:\windows\system"
+	//		oTo:	"c:\windows\media"
+	//			->						"..\media"
+	//
+	// 2.:	oFrom:	"c:\windows\system\test.txt"
+	//		oTo:	"a:\test.txt"
+	//			->						"a:\test.txt"
+	//
+	// 3.:	oFrom:	"c:\windows\system.txt"
+	//		oTo:	"c:\windows\system.txt"
+	//			->						"system.txt"
+	//
+	// 4.:	oFrom:	"c:\windows\system.txt\"
+	//		oTo:	"c:\windows\system.txt"
+	//			->						"..\system.txt"
+	static bool GetRelativePosition(const CString &oFrom, const CString &oTo, CString &oRelativePath);
+
+	// oAbsolute path must be finished by a back slash
+	// 1.:	oAbsolutePath:	"c:\windows\"
+	//		oRelativePath:	"..\windos"
+	//			->						"c:\windos"
+	//
+	// 2.:	oAbsolutePath:	"c:\windows\new\"
+	//		oRelativePath:	"..\windos\blah.txt"
+	//			->						"c:\windows\windos\blah.txt"
+	//
+	static bool ApplyRelativePath(const CString &oRelativePath, CString &oAbsolutePath);
+
+	// "c:\windows\blah.txt"	->	"c:\windows\"
+	// "c:\windows"				->	"c:\windows\"
+	// "c:"						->	"c:\"
+	// "c:windows"				-> error
+	// "windows"				-> error
+	// "windows\blah.txt"		-> error
+	// "c:\windows\blah.txt\"	-> "c:\windows\blah.txt\"	// in this case blah.txt should be a directory
+	// return value: success
+	// make sure you NOTE: the string MUST contain a
+	// drive specification
+	// if bAssumeDirectory==true then the following happens:
+	// "c:\windows\blah.txt"	->	"c:\windows\blah.txt\"
+	static bool MakePath(CString &oStr, bool bAssumeDirectory=false);
+
+	// extracts the file name from a path
+	// "c:\windows\blah.txt"	->	"blah.txt"
+	// "c:\windows\blah.txt\"	-> error
+	// "c:blah.txt"				->	"blah.txt"
+	// "blah.txt"				->	"blah.txt"
+	// source and target string parameter may reference the
+	// same object
+	static bool ExtractFileName(const CString &oPath, CString &oFileName);
+
+	// "c:\windows\blah.txt"	->	"c:"
+	// "\windows\blah.txt"		-> error
+	// source and target string parameter may reference the
+	// same object
+	static bool ExtractDrive(const CString &oPath, CString &oDrive);
+
+	// "blah.txt"				->	"blah", "txt"
+	// "blah"					->	"blah", ""
+	// "blah."					->	"blah", ""
+	// "somewhere\blah.txt"		->	"somewhere\blah", "txt"
+	// source and target string parameter may reference the
+	// same object; the target objects may be the same object
+	// (however behaviour is undefined in this case)
+	static bool SplitFileAndExtension(const CString &oFilePath, CString &oSimpleFileName, CString &oExtension);
+
+	// bAcceptDirectories==false
+	//	""						-> false
+	//	"*.txt"					-> true
+	//	"*.something"			-> true
+	//	"*"						-> true
+	//	"*.*"					-> true
+	//	"*.*.*"					-> true
+	//	"*..txt"				-> false
+	//	"?something.txt"		-> true
+	//	"s?omething.*"			-> true
+	//	"something.t xt"		-> false
+	//	"something.txt"			-> false	(!)
+	//	"\*.*"					-> false
+	//	"c:\temp\*.*"			-> false
+	// bAcceptDirectories==true
+	//	""						-> false
+	//	"*.txt"					-> true
+	//	"*.something"			-> true
+	//	"*"						-> true
+	//	"*.*"					-> true
+	//	"*.*.*"					-> true
+	//	"*..txt"				-> false
+	//	"?something.txt"		-> true
+	//	"s?omething.*"			-> true
+	//	"something.t xt"		-> false
+	//	"something.txt"			-> false	(!)
+	//	"\*.*"					-> true
+	//	"c:\temp\*.*"			-> true
+	static bool IsValidFileMask(const CString &oFileMask, bool bAcceptDirectories=false);
+
+private:
+	// oPath must be a directory description finished with
+	// a back slash;
+	// "c:\windows\system\"		->	"c:\windows\"
+	// "c:\"					-> error
+	static bool RemoveOneDirFromEnd(CString &oPath, CString &oRemoved);
+
+	// counts the number of back slashs in the string
+	// and thus determines the depth of the path
+	static long CountBackSlashes(const CString &oPath);
+
+	// deletes all unaccepted chars from the string
+	static void FilterString(CString &oString, const CString &oAcceptedChars);
+
+	// deletes all specified chars from the string
+	static void FilterStringInverse(CString &oString, const CString &oCharsToRemove);
+};
+
+#endif // !defined(AFX_FILEPATHCALC_H__B9F42A01_49AE_11D3_A724_50DB50C10057__INCLUDED_)
--- /dev/null
+++ b/wingui/FileSerializable.cpp
@@ -1,0 +1,40 @@
+// FileSerializable.cpp: implementation of the CFileSerializable class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "FileSerializable.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CFileSerializable::CFileSerializable()
+{
+
+}
+
+CFileSerializable::~CFileSerializable()
+{
+
+}
+
+void CFileSerializable::SerializeBool(CArchive &oArchive, bool bBool)
+{
+	int iBool=bBool ? 1 : 0;
+	oArchive << iBool;
+}
+
+void CFileSerializable::DeSerializeBool(CArchive &oArchive, bool &bBool)
+{
+	int iBool;
+	oArchive >> iBool;
+	bBool=iBool!=0;
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/FileSerializable.h
@@ -1,0 +1,30 @@
+// FileSerializable.h: interface for the CFileSerializable class.
+// Author: Torsten Landmann
+//
+// An interface for classes that can be serialized to or deserialized
+// from a file stream.
+// Also contains some utility methods for CArchive interaction.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_FILESERIALIZABLE_H__5FC5E381_1729_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_FILESERIALIZABLE_H__5FC5E381_1729_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CFileSerializable  
+{
+public:
+	CFileSerializable();
+	virtual ~CFileSerializable();
+
+	virtual bool PutToArchive(CArchive &oArchive) const=0;
+	virtual bool GetFromArchive(CArchive &oArchive)=0;
+
+	static void SerializeBool(CArchive &oArchive, bool bBool);
+	static void DeSerializeBool(CArchive &oArchive, bool &bBool);
+};
+
+#endif // !defined(AFX_FILESERIALIZABLE_H__5FC5E381_1729_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/FileSerializableJobList.cpp
@@ -1,0 +1,130 @@
+// FileSerializableJobList.cpp: implementation of the CFileSerializableJobList class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "FileSerializableJobList.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+CFileSerializableJobListElem::CFileSerializableJobListElem()
+{
+}
+
+CFileSerializableJobListElem::~CFileSerializableJobListElem()
+{
+}
+
+bool CFileSerializableJobListElem::PutToArchive(CArchive &oArchive, long lSaveParams) const
+{
+	switch (lSaveParams)
+	{
+	case 1:
+		{
+			return m_oJob.PutToArchive(oArchive);
+		}
+	default:
+		{
+			// unknown file format version
+			return false;
+		}
+	}
+}
+
+bool CFileSerializableJobListElem::GetFromArchive(CArchive &oArchive, long lLoadParams)
+{
+	switch (lLoadParams)
+	{
+	case 1:
+		{
+			return m_oJob.GetFromArchive(oArchive);
+		}
+	default:
+		{
+			// unknown file format version
+			return false;
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CFileSerializableJobList::CFileSerializableJobList()
+{
+}
+
+CFileSerializableJobList::CFileSerializableJobList(CJobList &oJobList)
+{
+	GetFromRegularJobList(oJobList);
+}
+
+CFileSerializableJobList::~CFileSerializableJobList()
+{
+
+}
+
+CFileSerializableJobList::operator CJobList()
+{
+	CJobList oRegularJobList;
+	CopyToRegularJobList(oRegularJobList);
+	return oRegularJobList;
+}
+
+long CFileSerializableJobList::AddJob(const CJob &oJob, long lDesiredIndex)
+{
+	CFileSerializableJobListElem *poNewElem=(CFileSerializableJobListElem*)Add(lDesiredIndex);
+	poNewElem->m_oJob=oJob;
+	return poNewElem->GetIndex();
+}
+
+CJob* CFileSerializableJobList::GetJob(long lIndex)
+{
+	CFileSerializableJobListElem *poElem=(CFileSerializableJobListElem*)GetElem(lIndex);
+	if (poElem==0) return 0;
+	return &poElem->m_oJob;
+}
+
+CJob* CFileSerializableJobList::GetNextJob(CBListReader &oReader, long *plIndex)
+{
+	CFileSerializableJobListElem *poElem=(CFileSerializableJobListElem*)ReadElem(oReader);
+	if (poElem==0) return 0;
+	return &poElem->m_oJob;
+}
+
+PBBaseElem CFileSerializableJobList::CreateElem()
+{
+	return new CFileSerializableJobListElem;
+}
+
+void CFileSerializableJobList::GetFromRegularJobList(CJobList &oJobList)
+{
+	DeleteAll();
+
+	CBListReader oReader(oJobList);
+	CJob *poCurJob;
+	long lCurJobIndex;
+	while ((poCurJob=oJobList.GetNextJob(oReader, &lCurJobIndex))!=0)
+	{
+		AddJob(*poCurJob, lCurJobIndex);
+	}
+}
+
+void CFileSerializableJobList::CopyToRegularJobList(CJobList &oJobList)
+{
+	oJobList.DeleteAll();
+
+	CBListReader oReader(*this);
+	CJob *poCurJob;
+	long lCurJobIndex;
+	while ((poCurJob=GetNextJob(oReader, &lCurJobIndex))!=0)
+	{
+		oJobList.AddJob(*poCurJob, lCurJobIndex);
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/FileSerializableJobList.h
@@ -1,0 +1,67 @@
+// FileSerializableJobList.h: interface for the CFileSerializableJobList class.
+// Author: Torsten Landmann
+//
+// This class was necessary to be able to reuse certain existing code for
+// loading/saving lists. It can be used as a substitute to CJobList in most
+// cases. Sometimes explicit casting may be necessary in one or the other
+// direction.
+// Instances of CFileSerializableJobList have the advantage that they are
+// serializable via CBList members such as
+// SaveToFile() or LoadFromFile().
+// Instances of CFileSerializableJobList have the disadvantage that they aren't
+// instances of TItemList<CJob> so they don't provide quite some functionality.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_FILESERIALIZABLEJOBLIST_H__5FC5E383_1729_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_FILESERIALIZABLEJOBLIST_H__5FC5E383_1729_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "listobj.h"
+
+class CFileSerializableJobListElem : public CBBaseElem
+{
+	friend class CFileSerializableJobList;
+
+protected:
+	CFileSerializableJobListElem();     // only allowed for derivations and for CBList (=friend)
+	virtual ~CFileSerializableJobListElem();
+
+	// override these members if you want to put your list
+	// to a stream or retreive it from there;
+	// do never forget to call these ones if you override them
+	virtual bool PutToArchive(CArchive &oArchive, long lSaveParams) const;
+	virtual bool GetFromArchive(CArchive &oArchive, long lLoadParams);
+private:
+	CJob m_oJob;
+};
+
+class CFileSerializableJobList : public CBList  
+{
+public:
+	CFileSerializableJobList();
+	CFileSerializableJobList(CJobList &oJobList);
+	virtual ~CFileSerializableJobList();
+
+	operator CJobList();
+
+	long AddJob(const CJob &oJob, long lDesiredIndex=-1);
+	CJob* GetJob(long lIndex);
+	CJob* GetNextJob(CBListReader &oReader, long *plIndex=0);
+
+private:
+	// -- overridden from CBList
+	// the following method must be overriden by every
+	// subclass returning an element of the type of the particular
+	// subclass of PBBaseElem
+	virtual PBBaseElem CreateElem();
+
+	void GetFromRegularJobList(CJobList &oJobList);
+	void CopyToRegularJobList(CJobList &oJobList);
+};
+
+
+#endif // !defined(AFX_FILESERIALIZABLEJOBLIST_H__5FC5E383_1729_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/FloatingPropertyDialog.cpp
@@ -1,0 +1,117 @@
+// FloatingPropertyDialog.cpp : implementation file
+// Author: Torsten Landmann
+//
+///////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "FloatingPropertyDialog.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+CFloatingPropertyDialog *CFloatingPropertyDialog::m_poFloatingPropertyDialogSingleton=0;
+
+/////////////////////////////////////////////////////////////////////////////
+// CFloatingPropertyDialog dialog
+
+
+CFloatingPropertyDialog::CFloatingPropertyDialog(CWnd* pParent /*=NULL*/):
+	m_poPropertiesDummyDialog(0)
+{
+	//{{AFX_DATA_INIT(CFloatingPropertyDialog)
+		// NOTE: the ClassWizard will add member initialization here
+	//}}AFX_DATA_INIT
+
+	Create(CFloatingPropertyDialog::IDD, pParent);
+}
+
+CFloatingPropertyDialog::~CFloatingPropertyDialog()
+{
+	if (m_poPropertiesDummyDialog!=0)
+	{
+		delete m_poPropertiesDummyDialog;
+		m_poPropertiesDummyDialog=0;
+
+		((CFaac_winguiApp*)AfxGetApp())->SetGlobalPropertiesDummyParentDialogSingleton(0);
+	}
+}
+
+void CFloatingPropertyDialog::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CFloatingPropertyDialog)
+	DDX_Control(pDX, IDC_LABELDEBUGTAG, m_ctrlLabelDebugTag);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CFloatingPropertyDialog, CDialog)
+	//{{AFX_MSG_MAP(CFloatingPropertyDialog)
+	ON_WM_SIZE()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CFloatingPropertyDialog message handlers
+
+void CFloatingPropertyDialog::CreateFloatingPropertiesDummyParentDialog()
+{
+	if (m_poFloatingPropertyDialogSingleton==0)
+	{
+		// memory leak reported here is ok (leak is created immediately before
+		// application exit)
+		m_poFloatingPropertyDialogSingleton=new CFloatingPropertyDialog;
+	}
+}
+
+void CFloatingPropertyDialog::InvalidFloatingPropertiesDialog()
+{
+	if (m_poFloatingPropertyDialogSingleton!=0)
+	{
+		delete m_poFloatingPropertyDialogSingleton;
+		m_poFloatingPropertyDialogSingleton=0;
+	}
+}
+
+void CFloatingPropertyDialog::OnSize(UINT nType, int cx, int cy) 
+{
+	CDialog::OnSize(nType, cx, cy);
+
+	m_oCurrentSize=CRect(0, 0, cx, cy);
+	ApplyNewSize(m_oCurrentSize);
+}
+
+BOOL CFloatingPropertyDialog::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	// TODO: Add extra initialization here
+	ShowWindow(SW_SHOW);
+	m_poPropertiesDummyDialog=new CPropertiesDummyParentDialog(true, this);
+	((CFaac_winguiApp*)AfxGetApp())->SetGlobalPropertiesDummyParentDialogSingleton(m_poPropertiesDummyDialog);
+	ApplyNewSize(m_oCurrentSize);
+	m_poPropertiesDummyDialog->ShowWindow(SW_SHOW);
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CFloatingPropertyDialog::ApplyNewSize(const CRect &oSize)
+{
+	if (m_poPropertiesDummyDialog!=0)
+	{
+		// dialog has been initialized
+
+		m_poPropertiesDummyDialog->MoveWindow(oSize);
+
+		CRect oLabelRect;
+		m_ctrlLabelDebugTag.GetWindowRect(&oLabelRect);
+		CRect oDebugLabelRect(oSize.BottomRight(), oLabelRect.Size());
+		oDebugLabelRect.OffsetRect(-oLabelRect.Size().cx, -oLabelRect.Size().cy);
+		m_ctrlLabelDebugTag.MoveWindow(oDebugLabelRect);
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/FloatingPropertyDialog.h
@@ -1,0 +1,76 @@
+// Author: Torsten Landmann
+//
+// This class represents the floating property dialog used
+// to configure the jobs
+//
+////////////////////////////////////////////////////////
+
+#if !defined(AFX_FLOATINGPROPERTYDIALOG_H__442115C9_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_FLOATINGPROPERTYDIALOG_H__442115C9_0FD4_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// FloatingPropertyDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CFloatingPropertyDialog dialog
+
+class CFloatingPropertyDialog : public CDialog
+{
+// Construction
+public:
+	CFloatingPropertyDialog(CWnd* pParent = NULL);   // standard constructor
+	virtual ~CFloatingPropertyDialog();
+
+// Dialog Data
+	//{{AFX_DATA(CFloatingPropertyDialog)
+	enum { IDD = IDD_FLOATINGPROPERTYDIALOG };
+	CStatic	m_ctrlLabelDebugTag;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CFloatingPropertyDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+public:
+	// this member creates a singelton dummy dialog that's embedded
+	// in any floating window; the creation of this floating window
+	// is task of this method;
+	// note that this member works somewhat asynchrounous; on creation
+	// of the CPropertiesDummyParentDialog window it calls the
+	static void CreateFloatingPropertiesDummyParentDialog();
+
+	// this member properly cleans up any floating property window, if there's
+	// any
+	static void InvalidFloatingPropertiesDialog();
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CFloatingPropertyDialog)
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	virtual BOOL OnInitDialog();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+private:
+	static CFloatingPropertyDialog *m_poFloatingPropertyDialogSingleton;
+
+	CPropertiesDummyParentDialog *m_poPropertiesDummyDialog;
+
+	CRect m_oCurrentSize;
+
+	void ApplyNewSize(const CRect &oSize);
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_FLOATINGPROPERTYDIALOG_H__442115C9_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/FolderDialog.cpp
@@ -1,0 +1,115 @@
+// FolderDialog.cpp: implementation of the CFolderDialog class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "FolderDialog.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CFolderDialog::CFolderDialog(CWnd *poParent, const CString &oDlgCaption, unsigned int iFlags):
+	m_oDlgCaption(oDlgCaption)
+{
+	m_sctBrowseParams.hwndOwner=*poParent;
+	m_sctBrowseParams.pidlRoot=NULL;		// no special root directory (this entry is NOT the directory that is shown first)
+	m_sctBrowseParams.pszDisplayName=0;
+	m_sctBrowseParams.lpszTitle=0;
+	m_sctBrowseParams.ulFlags=iFlags;
+	m_sctBrowseParams.lpfn=NULL;			// no callback
+	m_sctBrowseParams.lParam=0;
+}
+
+CFolderDialog::~CFolderDialog()
+{
+
+}
+
+int CFolderDialog::DoModal()
+{
+	m_sctBrowseParams.pszDisplayName=m_oFolderName.GetBuffer(_MAX_PATH);
+	m_sctBrowseParams.lpszTitle=m_oDlgCaption;				// better do that here
+
+	LPITEMIDLIST lpSelectedItems;
+	if ((lpSelectedItems=SHBrowseForFolder(&m_sctBrowseParams))!=NULL)
+	{
+		// OK pressed
+		m_oFolderName.ReleaseBuffer();
+		// unfortunately m_oFolderName only contains the name of the
+		// directory selected and not its complete path; thus we have
+		// some work left to do...
+
+		// complicated but more flexible version of finding out the path;
+		/*// find out the complete selected path; for this we'll need
+		// the desktop interface (SHBrowseForFolder() returns the directory
+		// position relatively to the desktop folder)
+		IShellFolder *pifcFile;
+		SHGetDesktopFolder(&pifcFile);
+
+		// now ask the desktop interface for the relative position of the
+		// folder returned
+		// -- this parameter makes this version more flexible-+
+		STRRET sctRet;			//							  |
+								//							  V
+		pifcFile->GetDisplayNameOf(lpSelectedItems, SHGDN_NORMAL, &sctRet);
+		
+		
+		// fetch the path that the user has selected
+		switch (sctRet.uType)
+		{
+		case STRRET_CSTR:
+			{
+				m_oFolderPath=sctRet.cStr;
+				break;
+			}
+		case STRRET_WSTR:
+			{
+				m_oFolderPath=sctRet.pOleStr;
+				break;
+			}
+		default:
+		case STRRET_OFFSET:
+			{
+				ASSERT(false);
+					// unkown or unhandleble return type
+				AfxMessageBox(IDS_InvalidReturnType);
+
+				break;
+			}
+		}*/
+
+		// conventional way of finding out the complete folder path
+		BOOL bSuccess=SHGetPathFromIDList(lpSelectedItems, m_oFolderPath.GetBuffer(_MAX_PATH));
+		m_oFolderPath.ReleaseBuffer();
+
+		// free buffer that was returned by SHBrowseForFolder()
+		IMalloc *pifcMalloc;
+		SHGetMalloc(&pifcMalloc);
+		pifcMalloc->Free(lpSelectedItems);
+
+		if (!bSuccess)
+		{
+			// error finding out the complete path
+			m_bError=true;
+			return IDCANCEL;
+		}
+
+		return IDOK;
+	}
+	else
+	{
+		// cancel pressed
+		m_oFolderName.ReleaseBuffer();
+
+		m_bError=false;
+		return IDCANCEL;
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/FolderDialog.h
@@ -1,0 +1,38 @@
+// FolderDialog.h: interface for the CFolderDialog class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_FOLDERDIALOG_H__57C79485_9C5F_11D3_A724_007250C10000__INCLUDED_)
+#define AFX_FOLDERDIALOG_H__57C79485_9C5F_11D3_A724_007250C10000__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CFolderDialog  
+{
+public:
+	// for a flag description see BROWSEINFO in the MSDN
+	CFolderDialog(CWnd *poParent, const CString &oDlgCaption, unsigned int iFlags=0);
+	virtual ~CFolderDialog();
+
+	// write to this member if you want to modify the parameters
+	// provided at construction before calling DoModal()
+	BROWSEINFO m_sctBrowseParams;
+
+	// read these members after DoModal() return with IDOK
+	CString m_oFolderName;
+	CString m_oFolderPath;
+
+	// read this member after DoModal() return with IDCANCEL
+	bool m_bError;
+
+	// call this member to show the dialog
+	int DoModal();
+
+private:
+	CString m_oDlgCaption;
+};
+
+#endif // !defined(AFX_FOLDERDIALOG_H__57C79485_9C5F_11D3_A724_007250C10000__INCLUDED_)
--- /dev/null
+++ b/wingui/Id3TagInfo.cpp
@@ -1,0 +1,107 @@
+// Id3TagInfo.cpp: implementation of the CId3TagInfo class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "Id3TagInfo.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CId3TagInfo::CId3TagInfo():
+	m_lTrackNo(-1),
+	m_lYear(-1)
+{
+}
+
+CId3TagInfo::CId3TagInfo(const CId3TagInfo &oSource)
+{
+	*this=oSource;
+}
+
+CId3TagInfo::~CId3TagInfo()
+{
+}
+
+
+CId3TagInfo& CId3TagInfo::operator=(const CId3TagInfo &oRight)
+{
+	m_oArtist=oRight.m_oArtist;
+	m_lTrackNo=oRight.m_lTrackNo;
+	m_oAlbum=oRight.m_oAlbum;
+	m_lYear=oRight.m_lYear;
+	m_oSongTitle=oRight.m_oSongTitle;
+	m_bCopyright=oRight.m_bCopyright;
+	m_oOriginalArtist=oRight.m_oOriginalArtist;
+	m_oComposer=oRight.m_oComposer;
+	m_oUrl=oRight.m_oUrl;
+	m_oGenre=oRight.m_oGenre;
+	m_oEncodedBy=oRight.m_oEncodedBy;
+	m_oComment=oRight.m_oComment;
+
+	return *this;
+}
+
+bool CId3TagInfo::PutToArchive(CArchive &oArchive) const
+{
+	// put a class version flag
+	int iVersion=1;
+	oArchive << iVersion;
+
+	oArchive << m_oArtist;
+	oArchive << m_lTrackNo;
+	oArchive << m_oAlbum;
+	oArchive << m_lYear;
+	oArchive << m_oSongTitle;
+	CFileSerializable::SerializeBool(oArchive, m_bCopyright);
+	oArchive << m_oOriginalArtist;
+	oArchive << m_oComposer;
+	oArchive << m_oUrl;
+	oArchive << m_oGenre;
+	oArchive << m_oEncodedBy;
+	oArchive << m_oComment;
+
+	return true;
+}
+
+bool CId3TagInfo::GetFromArchive(CArchive &oArchive)
+{
+	// fetch the class version flag
+	int iVersion;
+	oArchive >> iVersion;
+
+	switch (iVersion)
+	{
+	case 1:
+		{
+			oArchive >> m_oArtist;
+			oArchive >> m_lTrackNo;
+			oArchive >> m_oAlbum;
+			oArchive >> m_lYear;
+			oArchive >> m_oSongTitle;
+			CFileSerializable::DeSerializeBool(oArchive, m_bCopyright);
+			oArchive >> m_oOriginalArtist;
+			oArchive >> m_oComposer;
+			oArchive >> m_oUrl;
+			oArchive >> m_oGenre;
+			oArchive >> m_oEncodedBy;
+			oArchive >> m_oComment;
+
+			return true;
+		}
+	default:
+		{
+			// unknown file format version
+			return false;
+		}
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/Id3TagInfo.h
@@ -1,0 +1,85 @@
+// Id3TagInfo.h: interface for the CId3TagInfo class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ID3TAGINFO_H__DFE38E72_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_ID3TAGINFO_H__DFE38E72_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "FileSerializable.h"
+
+class CId3TagInfo : public CFileSerializable
+{
+public:
+	CId3TagInfo();
+	CId3TagInfo(const CId3TagInfo &oSource);	// copy constructor
+	virtual ~CId3TagInfo();
+
+	// getters
+	const CString& GetArtist() const				{ return m_oArtist; }
+	CString &GetArtist()							{ return m_oArtist; }
+	long GetTrackNo() const							{ return m_lTrackNo; }
+	long& GetTrackNoRef()							{ return m_lTrackNo; }
+	const CString& GetAlbum() const					{ return m_oAlbum; }
+	CString &GetAlbum()								{ return m_oAlbum; }
+	long GetYear() const							{ return m_lYear; }
+	long& GetYearRef()								{ return m_lYear; }
+	const CString &GetSongTitle() const				{ return m_oSongTitle; }
+	CString& GetSongTitle()							{ return m_oSongTitle; }
+	bool GetCopyright() const						{ return m_bCopyright; }
+	bool& GetCopyrightRef()							{ return m_bCopyright; }
+	const CString& GetOriginalArtist() const		{ return m_oOriginalArtist; }
+	CString &GetOriginalArtist()					{ return m_oOriginalArtist; }
+	const CString &GetComposer() const				{ return m_oComposer; }
+	CString& GetComposer()							{ return m_oComposer; }
+	const CString &GetUrl() const					{ return m_oUrl; }
+	CString& GetUrl()								{ return m_oUrl; }
+	const CString &GetGenre() const					{ return m_oGenre; }
+	CString& GetGenre()								{ return m_oGenre; }
+	const CString &GetEncodedBy() const				{ return m_oEncodedBy; }
+	CString& GetEncodedBy()							{ return m_oEncodedBy; }
+	const CString& GetComment() const				{ return m_oComment; }
+	CString &GetComment()							{ return m_oComment; }
+			
+	// setters
+	void SetArtist(const CString &oArtist)					{ m_oArtist=oArtist; }
+	void SetTrackNo(long lTrackNo)							{ m_lTrackNo=lTrackNo; }
+	void SetAlbum(const CString &oAlbum)					{ m_oAlbum=oAlbum; }
+	void SetYear(long lYear)								{ m_lYear=lYear; }
+	void SetSongTitle(const CString &oSongTitle)			{ m_oSongTitle=oSongTitle; }
+	void SetCopyright(bool bCopyright)						{ m_bCopyright=bCopyright; }
+	void SetOriginalArtist(const CString &oOriginalArtist)	{ m_oOriginalArtist=oOriginalArtist; }
+	void SetComposer(const CString &oComposer)				{ m_oComposer=oComposer; }
+	void SetUrl(const CString &oUrl)						{ m_oUrl=oUrl; }
+	void SetGenre(const CString &oGenre)					{ m_oGenre=oGenre; }
+	void SetEncodedBy(const CString &oEncodedBy)			{ m_oEncodedBy=oEncodedBy; }
+	void SetComment(const CString &oComment)				{ m_oComment=oComment; }
+
+	CId3TagInfo& operator=(const CId3TagInfo &oRight);
+
+	// implementations to CFileSerializable
+	virtual bool PutToArchive(CArchive &oArchive) const;
+	virtual bool GetFromArchive(CArchive &oArchive);
+													
+private:
+	CString m_oArtist;
+	long m_lTrackNo;
+	CString m_oAlbum;
+	long m_lYear;
+	CString m_oSongTitle;
+	bool m_bCopyright;
+	CString m_oOriginalArtist;
+	CString m_oComposer;
+	CString m_oUrl;
+	CString m_oGenre;
+	CString m_oEncodedBy;
+	CString m_oComment;
+	// further to come (don't forget to update our assignment operator)
+
+};
+
+#endif // !defined(AFX_ID3TAGINFO_H__DFE38E72_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/Job.cpp
@@ -1,0 +1,228 @@
+// Job.cpp: implementation of the CJob class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "Job.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CJob::CJob():
+	m_eJobType(eUndefined),
+	m_poJob(0)
+{
+}
+
+CJob::CJob(const CEncoderJob &oEncoderJob):
+	m_eJobType(eUndefined),
+	m_poJob(0)
+{
+	SetEncoderJob(oEncoderJob);
+}
+
+CJob::CJob(const CJob &oSource):
+	m_eJobType(eUndefined),
+	m_poJob(0)
+{
+	*this=oSource;
+}
+
+CJob::~CJob()
+{
+	if (m_poJob!=0)
+	{
+		delete m_poJob;
+	}
+}
+
+
+void CJob::SetEncoderJob(const CEncoderJob &oEncoderJob)
+{
+	ResetContent();
+
+	m_eJobType=eEncoderJob;
+
+	m_poJob=new CEncoderJob(oEncoderJob);
+}
+
+CJob& CJob::operator=(const CJob &oRight)
+{
+	if (this==&oRight) return *this;
+	ResetContent();
+
+	m_eJobType=oRight.m_eJobType;
+	switch (m_eJobType)
+	{
+	case eEncoderJob:
+		{
+			m_poJob=new CEncoderJob(*((CEncoderJob*)oRight.m_poJob));
+			break;
+		}
+	case eUndefined:
+		{
+			break;
+		}
+	default:
+		{
+			ASSERT(false);
+			break;
+		}
+	}
+
+	return *this;
+}
+
+CString CJob::DescribeJobTypeShort() const
+{
+	if (m_poJob!=0)
+	{
+		return m_poJob->DescribeJobTypeShort();
+	}
+
+	return "U";
+}
+
+CString CJob::DescribeJobTypeLong() const
+{
+	if (m_poJob!=0)
+	{
+		return m_poJob->DescribeJobTypeLong();
+	}
+
+	CString oUndefined;
+	oUndefined.LoadString(IDS_UndefinedShort);
+	return oUndefined;
+}
+
+CString CJob::DescribeJob() const
+{
+	if (m_poJob!=0)
+	{
+		return m_poJob->DescribeJob();
+	}
+
+	CString oInvalidJob;
+	oInvalidJob.LoadString(IDS_InvalidJob);
+	return oInvalidJob;
+}
+
+CSupportedPropertyPagesData CJob::GetSupportedPropertyPages() const
+{
+	if (m_poJob!=0)
+	{
+		return m_poJob->GetSupportedPropertyPages();
+	}
+	else
+	{
+		return CSupportedPropertyPagesData();
+	}
+}
+
+CString CJob::GetDetailedDescriptionForStatusDialog() const
+{
+	// doesn't need an implementation here
+	return "";
+}
+
+bool CJob::PutToArchive(CArchive &oArchive) const
+{
+	// put a class version flag
+	int iVersion=1;
+	oArchive << iVersion;
+
+	oArchive << m_eJobType;
+
+	bool bSerializeJob=m_poJob!=0;
+	CFileSerializable::SerializeBool(oArchive, bSerializeJob);
+	if (bSerializeJob)
+	{
+		if (!m_poJob->PutToArchive(oArchive)) return false;
+	}
+
+	return true;
+}
+
+bool CJob::GetFromArchive(CArchive &oArchive)
+{
+	// fetch the class version flag
+	int iVersion;
+	oArchive >> iVersion;
+
+	switch (iVersion)
+	{
+	case 1:
+		{
+			oArchive >> (int&)m_eJobType;
+
+			if (m_poJob!=0)
+			{
+				delete m_poJob;
+				m_poJob=0;
+			}
+			bool bDeSerializeJob;
+			CFileSerializable::DeSerializeBool(oArchive, bDeSerializeJob);
+			if (bDeSerializeJob)
+			{
+				switch (m_eJobType)
+				{
+				case eEncoderJob:
+					{
+						m_poJob=new CEncoderJob;
+						break;
+					}
+				default:
+					{
+						// unknown type of job
+						ASSERT(false);
+						return false;
+					}
+				}
+				if (!m_poJob->GetFromArchive(oArchive)) return false;
+			}
+			else
+			{
+				m_poJob=0;
+			}
+
+			return true;
+		}
+	default:
+		{
+			// unknown file format version
+			ASSERT(false);
+			return false;
+		}
+	}
+}
+
+bool CJob::ProcessJob() const
+{
+	if (m_poJob!=0)
+	{
+		return m_poJob->ProcessJob();
+	}
+	else
+	{
+		return false;
+	}
+}
+
+void CJob::ResetContent()
+{
+	if (m_poJob!=0)
+	{
+		delete m_poJob;
+	}
+
+	m_eJobType=eUndefined;
+}
--- /dev/null
+++ b/wingui/Job.h
@@ -1,0 +1,71 @@
+// Job.h: interface for the CJob class.
+// Author: Torsten Landmann
+//
+// represents a certain block of work (e.g. one encoding job or one
+// decoding job)
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_JOB_H__DFE38E6F_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_JOB_H__DFE38E6F_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "TItemList.h"
+#include "EncoderJob.h"
+#include "ConcreteJobBase.h"
+
+class CJob : public CGenericSortable, public CConcreteJobBase
+{
+public:
+	enum EJobType
+	{
+		eUndefined,
+		eEncoderJob,
+	};
+
+	CJob();
+	CJob(const CEncoderJob &oEncoderJob);
+	CJob(const CJob &oSource);		// copy constructor
+	virtual ~CJob();
+
+	// each of the following methods overwrites the settings
+	// of a previous such method call
+	void SetEncoderJob(const CEncoderJob &oEncoderJob);
+
+	EJobType GetJobType() const							{ return m_eJobType; }
+	// each of the following methods returns 0 if the content
+	// of this object doesn't match the method called
+	const CEncoderJob* GetEncoderJob() const			{ return m_eJobType==eEncoderJob ? (CEncoderJob*)m_poJob : 0; }
+	CEncoderJob* GetEncoderJob()						{ return m_eJobType==eEncoderJob ? (CEncoderJob*)m_poJob : 0; }
+
+	CJob& operator=(const CJob &oRight);
+
+
+	// implementations to CJobListCtrlDescribable
+	virtual CString DescribeJobTypeShort() const;
+	virtual CString DescribeJobTypeLong() const;
+	virtual CString DescribeJob() const;
+
+	// implementations to CAbstractJob
+	virtual CSupportedPropertyPagesData GetSupportedPropertyPages() const;
+	virtual bool ProcessJob() const;
+	virtual CString GetDetailedDescriptionForStatusDialog() const;
+
+	// implementations to CFileSerializable
+	virtual bool PutToArchive(CArchive &oArchive) const;
+	virtual bool GetFromArchive(CArchive &oArchive);
+
+private:
+	EJobType m_eJobType;
+
+	// this member contains an object of the type defined by
+	// m_eJobType
+	CConcreteJobBase *m_poJob;
+
+	void ResetContent();
+};
+
+#endif // !defined(AFX_JOB_H__DFE38E6F_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/JobList.cpp
@@ -1,0 +1,45 @@
+// JobList.cpp: implementation of the CJobList class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "JobList.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CJobList::CJobList()
+{
+
+}
+
+CJobList::~CJobList()
+{
+
+}
+
+long CJobList::AddJob(const CJob &oJob, long lDesiredIndex)
+{
+	return AddNewElem(oJob, lDesiredIndex);
+}
+
+CJob* CJobList::GetJob(long lIndex)
+{
+	CJob *poJob;
+	return GetElemContent(lIndex, poJob) ? poJob : 0;
+}
+
+CJob* CJobList::GetNextJob(CBListReader &oReader, long *plIndex)
+{
+	CJob *poJob;
+	return GetNextElemContent(oReader, poJob, plIndex) ? poJob : 0;
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/JobList.h
@@ -1,0 +1,31 @@
+// JobList.h: interface for the CJobList class.
+// Author: Torsten Landmann
+//
+// This class is used to save lists of jobs. Note the class
+// CFileSerializableJobList, which is used to save and load job
+// lists to and from files.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_JOBLIST_H__DFE38E75_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_JOBLIST_H__DFE38E75_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "TItemList.h"
+#include "Job.h"
+
+class CJobList : public TItemList<CJob>  
+{
+public:
+	CJobList();
+	virtual ~CJobList();
+
+	long AddJob(const CJob &oJob, long lDesiredIndex=-1);
+	CJob* GetJob(long lIndex);
+	CJob* GetNextJob(CBListReader &oReader, long *plIndex=0);
+};
+
+#endif // !defined(AFX_JOBLIST_H__DFE38E75_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/JobListCtrlDescribable.cpp
@@ -1,0 +1,28 @@
+// JobListCtrlDescribable.cpp: implementation of the CJobListCtrlDescribable class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "JobListCtrlDescribable.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CJobListCtrlDescribable::CJobListCtrlDescribable()
+{
+
+}
+
+CJobListCtrlDescribable::~CJobListCtrlDescribable()
+{
+
+}
--- /dev/null
+++ b/wingui/JobListCtrlDescribable.h
@@ -1,0 +1,26 @@
+// JobListCtrlDescribable.h: interface for the CJobListCtrlDescribable class.
+// Author: Torsten Landmann
+//
+// Classes should implement this interface if they want to be used as jobs
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_JOBLISTCTRLDESCRIBABLE_H__DFE38E73_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_JOBLISTCTRLDESCRIBABLE_H__DFE38E73_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CJobListCtrlDescribable
+{
+public:
+	CJobListCtrlDescribable();
+	virtual ~CJobListCtrlDescribable();
+
+	virtual CString DescribeJobTypeShort() const=0;
+	virtual CString DescribeJobTypeLong() const=0;
+	virtual CString DescribeJob() const=0;
+};
+
+#endif // !defined(AFX_JOBLISTCTRLDESCRIBABLE_H__DFE38E73_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/JobListUpdatable.cpp
@@ -1,0 +1,27 @@
+// JobListUpdatable.cpp: implementation of the CJobListUpdatable class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "JobListUpdatable.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CJobListUpdatable::CJobListUpdatable()
+{
+
+}
+
+CJobListUpdatable::~CJobListUpdatable()
+{
+
+}
--- /dev/null
+++ b/wingui/JobListUpdatable.h
@@ -1,0 +1,29 @@
+// JobListUpdatable.h: interface for the CJobListUpdatable class.
+// Author: Torsten Landmann
+//
+// just an interface for better encapsulation
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_JOBLISTUPDATABLE_H__A1444E81_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_JOBLISTUPDATABLE_H__A1444E81_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "ListCtrlStateSaver.h"
+
+class CJobListUpdatable  
+{
+public:
+	CJobListUpdatable();
+	virtual ~CJobListUpdatable();
+
+	// this method refills the job list control;
+	// if no explicit selection state is specified the current
+	// selection is preserved
+	virtual void ReFillInJobListCtrl(CListCtrlStateSaver *poSelectionStateToUse=0, bool bSimpleUpdate=true)=0;
+};
+
+#endif // !defined(AFX_JOBLISTUPDATABLE_H__A1444E81_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/JobListsToConfigureSaver.cpp
@@ -1,0 +1,67 @@
+// JobListsToConfigureSaver.cpp: implementation of the CJobListsToConfigureSaver class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "JobListsToConfigureSaver.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CJobListsToConfigureSaver::CJobListsToConfigureSaver()
+{
+
+}
+
+CJobListsToConfigureSaver::CJobListsToConfigureSaver(TItemList<CJob*> &oJobs)
+{
+	SaveJobs(oJobs);
+}
+
+CJobListsToConfigureSaver::~CJobListsToConfigureSaver()
+{
+
+}
+
+void CJobListsToConfigureSaver::SaveJobs(TItemList<CJob*> &oJobs)
+{
+	m_oSavedJobs.DeleteAll();
+	CBListReader oReader(oJobs);
+	CJob *poCurJob;
+	long lCurJobIndex;
+	while (oJobs.GetNextElemContent(oReader, poCurJob, &lCurJobIndex))
+	{
+		m_oSavedJobs.AddJob(*poCurJob, lCurJobIndex);
+	}
+}
+
+void CJobListsToConfigureSaver::RestoreJobs(TItemList<CJob*> &oJobs)
+{
+	CBListReader oReader(oJobs);
+	CJob *poCurJob;
+	long lCurJobIndex;
+	while (oJobs.GetNextElemContent(oReader, poCurJob, &lCurJobIndex))
+	{
+		// find the referring job in the list of saved jobs
+		CJob *poSavedJob=m_oSavedJobs.GetJob(lCurJobIndex);
+		if (poSavedJob==0)
+		{
+			// looks like you have modified the list structur between
+			// the load and save operation
+			ASSERT(false);
+		}
+		else
+		{
+			// copy in the saved content for the current job
+			*poCurJob=*poSavedJob;
+		}
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/JobListsToConfigureSaver.h
@@ -1,0 +1,38 @@
+// JobListsToConfigureSaver.h: interface for the CJobListsToConfigureSaver class.
+// Author: Torsten Landmann
+//
+// This class is able to save jobs that are available only as pointers
+// so that their contents can be restored later; note that it is assumed
+// that the structure of the list (number and indexes of elements) does
+// not change between the save and the restore operation
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_JOBLISTSTOCONFIGURESAVER_H__A1444E82_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_JOBLISTSTOCONFIGURESAVER_H__A1444E82_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "Job.h"
+#include "JobList.h"
+
+class CJobListsToConfigureSaver  
+{
+public:
+	CJobListsToConfigureSaver();
+	CJobListsToConfigureSaver(TItemList<CJob*> &oJobs);	// implies the save operation
+	virtual ~CJobListsToConfigureSaver();
+
+	// you can assume that both methods accept a const parameter; the
+	// only reason that it isn't really a const parameter is that
+	// we need a read session
+	void SaveJobs(TItemList<CJob*> &oJobs);
+	void RestoreJobs(TItemList<CJob*> &oJobs);
+
+private:
+	CJobList m_oSavedJobs;
+};
+
+#endif // !defined(AFX_JOBLISTSTOCONFIGURESAVER_H__A1444E82_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/ListCtrlStateSaver.cpp
@@ -1,0 +1,268 @@
+// ListCtrlStateSaver.cpp: implementation of the CListCtrlStateSaver class.
+// Copyright 1999, Torsten Landmann
+// successfully compiled and tested under MSVC 6.0
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ListCtrlStateSaver.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CListCtrlStateSaver::CListCtrlStateSaver()
+{
+
+}
+
+CListCtrlStateSaver::CListCtrlStateSaver(CListCtrl *poListCtrl)
+{
+	SaveState(poListCtrl);
+}
+
+CListCtrlStateSaver::~CListCtrlStateSaver()
+{
+
+}
+
+void CListCtrlStateSaver::SaveState(CListCtrl *poListCtrl)
+{
+	m_bIsSaving=true;
+	m_oSelectedItemLParams.DeleteAll();
+	m_oCheckedItemLParams.DeleteAll();
+	m_lFocusedItemLParam=-1;		// no selection or don't know the selection yet
+
+	if (poListCtrl!=0)
+	{
+		GoThroughEntireList(poListCtrl);
+	}
+}
+
+void CListCtrlStateSaver::RestoreState(CListCtrl *poListCtrl)
+{
+	m_bIsSaving=false;
+
+	if (poListCtrl!=0)
+	{
+		GoThroughEntireList(poListCtrl);
+	}
+}
+
+void CListCtrlStateSaver::UnselectAll()
+{
+	m_oSelectedItemLParams.DeleteAll();
+}
+
+void CListCtrlStateSaver::UncheckAll()
+{
+	m_oCheckedItemLParams.DeleteAll();
+}
+
+void CListCtrlStateSaver::SetToSelected(long lParam, bool bSelected)
+{
+	if (bSelected)
+	{
+		AddSelectedItem(lParam);
+	}
+	else
+	{
+		m_oSelectedItemLParams.DeleteAllElemsWithContent(lParam);
+	}
+}
+
+void CListCtrlStateSaver::SetToSelected(TItemList<long> oLParams, bool bSelected)
+{
+	HRead hRead=oLParams.BeginRead();
+	long lCurLParam;
+	while (oLParams.GetNextElemContent(hRead, lCurLParam))
+	{
+		SetToSelected(lCurLParam, bSelected);
+	}
+	oLParams.EndRead(hRead);
+}
+
+void CListCtrlStateSaver::SetToChecked(long lParam, bool bChecked)
+{
+	if (bChecked)
+	{
+		AddCheckedItem(lParam);
+	}
+	else
+	{
+		m_oCheckedItemLParams.DeleteAllElemsWithContent(lParam);
+	}
+}
+
+void CListCtrlStateSaver::SetToChecked(TItemList<long> oLParams, bool bSelected)
+{
+	HRead hRead=oLParams.BeginRead();
+	long lCurLParam;
+	while (oLParams.GetNextElemContent(hRead, lCurLParam))
+	{
+		SetToChecked(lCurLParam, bSelected);
+	}
+	oLParams.EndRead(hRead);
+}
+
+long CListCtrlStateSaver::GetFocusedItemLParam() const
+{
+	return m_lFocusedItemLParam;
+}
+
+bool CListCtrlStateSaver::IsSelected(long lItemLParam) const
+{
+	long lDummy;
+	return m_oSelectedItemLParams.FindContent(lItemLParam, lDummy);
+}
+
+bool CListCtrlStateSaver::IsChecked(long lItemLParam) const
+{
+	long lDummy;
+	return m_oCheckedItemLParams.FindContent(lItemLParam, lDummy);
+}
+
+long CListCtrlStateSaver::GetNumberOfSelectedItems() const
+{
+	return m_oSelectedItemLParams.GetNumber();
+}
+
+long CListCtrlStateSaver::GetNumberOfCheckedItems() const
+{
+	return m_oCheckedItemLParams.GetNumber();
+}
+
+void CListCtrlStateSaver::AddSelectedItem(long lParam)
+{
+	long lId;
+	if (!m_oSelectedItemLParams.FindContent(lParam, lId))
+	{
+		m_oSelectedItemLParams.AddNewElem(lParam);
+	}
+}
+
+void CListCtrlStateSaver::AddCheckedItem(long lParam)
+{
+	long lId;
+	if (!m_oCheckedItemLParams.FindContent(lParam, lId))
+	{
+		m_oCheckedItemLParams.AddNewElem(lParam);
+	}
+}
+
+bool CListCtrlStateSaver::IsSelected(CListCtrl *poListCtrl, int iItemId)
+{
+	UINT uiItemState=ListView_GetItemState(*poListCtrl, iItemId, LVIS_SELECTED);
+	return uiItemState!=0;
+}
+
+bool CListCtrlStateSaver::IsInSelectedItemsList(long lParam)
+{
+	long lId;
+	return m_oSelectedItemLParams.FindContent(lParam, lId);
+}
+
+bool CListCtrlStateSaver::IsChecked(CListCtrl *poListCtrl, int iItemId)
+{
+	return ListView_GetCheckState(*poListCtrl, iItemId)!=0;
+}
+
+bool CListCtrlStateSaver::IsInCheckedItemsList(long lParam)
+{
+	long lId;
+	return m_oCheckedItemLParams.FindContent(lParam, lId);
+}
+
+bool CListCtrlStateSaver::IsFocused(CListCtrl *poListCtrl, int iItemId)
+{
+	UINT uiItemState=ListView_GetItemState(*poListCtrl, iItemId, LVIS_FOCUSED);
+	return uiItemState!=0;
+}
+
+void CListCtrlStateSaver::SetSelectedState(CListCtrl *poListCtrl, int iItemId, bool bSelected)
+{
+	if (bSelected)
+	{
+		ListView_SetItemState(*poListCtrl, iItemId, LVIS_SELECTED, LVIS_SELECTED);
+	}
+	else
+	{
+		ListView_SetItemState(*poListCtrl, iItemId, 0, LVIS_SELECTED);
+	}
+}
+
+void CListCtrlStateSaver::SetCheckedState(CListCtrl *poListCtrl, int iItemId, bool bChecked)
+{
+	// macro as written at topic "Extended list view styles"
+	// in the msdn
+#ifndef ListView_SetCheckState
+   #define ListView_SetCheckState(hwndLV, i, fCheck) \
+      ListView_SetItemState(hwndLV, i, \
+      INDEXTOSTATEIMAGEMASK((fCheck)+1), LVIS_STATEIMAGEMASK)
+#endif
+
+	if (bChecked)
+	{
+		ListView_SetCheckState(*poListCtrl, iItemId, TRUE);
+	}
+	else
+	{
+		ListView_SetCheckState(*poListCtrl, iItemId, FALSE);
+	}
+}
+
+void CListCtrlStateSaver::SetToFocused(CListCtrl *poListCtrl, int iItemId)
+{
+	ListView_SetItemState(*poListCtrl, iItemId, LVIS_FOCUSED, LVIS_FOCUSED);
+}
+
+void CListCtrlStateSaver::GoThroughEntireList(CListCtrl *poListCtrl)
+{
+	long lNumberOfItems=poListCtrl->GetItemCount();
+	for (int iCurItemId=0; iCurItemId<lNumberOfItems; iCurItemId++)
+	{
+		long lCurItemLParam=poListCtrl->GetItemData(iCurItemId);
+		if (m_bIsSaving)
+		{
+			// save the item's state
+
+			if (IsSelected(poListCtrl, iCurItemId))
+			{
+				AddSelectedItem(lCurItemLParam);
+			}
+
+			if (IsChecked(poListCtrl, iCurItemId))
+			{
+				AddCheckedItem(lCurItemLParam);
+			}
+
+			if (IsFocused(poListCtrl, iCurItemId))
+			{
+				m_lFocusedItemLParam=lCurItemLParam;
+			}
+		}
+		else
+		{
+			// restore the item's state
+			SetSelectedState(poListCtrl, iCurItemId, IsInSelectedItemsList(lCurItemLParam));
+			SetCheckedState(poListCtrl, iCurItemId, IsInCheckedItemsList(lCurItemLParam));
+
+			if (m_lFocusedItemLParam==lCurItemLParam)
+			{
+				SetToFocused(poListCtrl, iCurItemId);
+			}
+		}
+	}
+
+	if (!m_bIsSaving && m_lFocusedItemLParam<0)
+	{
+		// no focused item
+		SetToFocused(poListCtrl, -1);
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/ListCtrlStateSaver.h
@@ -1,0 +1,70 @@
+// ListCtrlStateSaver.h: interface for the CListCtrlStateSaver class.
+// Copyright 1999, Torsten Landmann
+// successfully compiled and tested under MSVC 6.0
+//
+// This class is able to easily preserve the state of a list control
+// during refills of that control. It preserves information on which
+// items are selected and which items are checked. It does not preserve
+// the order.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_LISTCTRLSTATESAVER_H__CAAC66A6_72CB_11D3_A724_C0C04EC10107__INCLUDED_)
+#define AFX_LISTCTRLSTATESAVER_H__CAAC66A6_72CB_11D3_A724_C0C04EC10107__INCLUDED_
+
+#include "TItemList.h"
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CListCtrlStateSaver  
+{
+public:
+	CListCtrlStateSaver();		// when using this constructor you can configure the list control using SetToSelected() and public methods below
+	CListCtrlStateSaver(CListCtrl *poListCtrl);
+	virtual ~CListCtrlStateSaver();
+
+	void SaveState(CListCtrl *poListCtrl);
+	void RestoreState(CListCtrl *poListCtrl);		// not a const member; however you can assume it is one
+
+	// for manual list control configuration; take effect
+	// on RestoreState()
+	void UnselectAll();
+	void UncheckAll();
+	void SetToSelected(long lParam, bool bSelected=true);
+	void SetToSelected(TItemList<long> oLParams, bool bSelected=true);
+	void SetToChecked(long lParam, bool bChecked=true);
+	void SetToChecked(TItemList<long> oLParams, bool bSelected=true);
+
+	long GetFocusedItemLParam() const;		// -1 if there's no focused item
+	bool IsSelected(long lItemLParam) const;
+	bool IsChecked(long lItemLParam) const;
+
+	long GetNumberOfSelectedItems() const;
+	long GetNumberOfCheckedItems() const;
+
+private:
+	long m_lFocusedItemLParam;
+	TItemList<long> m_oSelectedItemLParams;
+	TItemList<long> m_oCheckedItemLParams;
+
+	void AddSelectedItem(long lParam);
+	void AddCheckedItem(long lParam);
+
+	static bool IsSelected(CListCtrl *poListCtrl, int iItemId);
+	bool IsInSelectedItemsList(long lParam);
+	static bool IsChecked(CListCtrl *poListCtrl, int iItemId);
+	bool IsInCheckedItemsList(long lParam);
+	static bool IsFocused(CListCtrl *poListCtrl, int iItemId);
+
+	void SetSelectedState(CListCtrl *poListCtrl, int iItemId, bool bSelected);
+	void SetCheckedState(CListCtrl *poListCtrl, int iItemId, bool bChecked);
+	void SetToFocused(CListCtrl *poListCtrl, int iItemId);
+
+	bool m_bIsSaving;
+
+	void GoThroughEntireList(CListCtrl *poListCtrl);
+};
+
+#endif // !defined(AFX_LISTCTRLSTATESAVER_H__CAAC66A6_72CB_11D3_A724_C0C04EC10107__INCLUDED_)
--- /dev/null
+++ b/wingui/Listobj.cpp
@@ -1,0 +1,730 @@
+// list class
+// Copyright 1999, Torsten Landmann
+// successfully compiled and tested under MSVC 6.0
+//
+//////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "Listobj.h"
+
+// definitions for class CBListReader
+CBListReader::CBListReader(CBList &oList)
+{
+	m_poList=&oList;
+	m_hRead=oList.BeginRead();
+
+	m_piUsageStack=new int;
+	*m_piUsageStack=1;
+}
+
+CBListReader::CBListReader(const CBListReader &oSource)
+{
+	*this=oSource;
+}
+
+CBListReader::~CBListReader()
+{
+	AbandonCurrentContent();
+}
+
+
+CBListReader& CBListReader::operator=(const CBListReader &oRight)
+{
+	if (this==&oRight) return *this;
+	AbandonCurrentContent();
+
+	m_poList=oRight.m_poList;
+	m_hRead=oRight.m_hRead;
+	m_piUsageStack=oRight.m_piUsageStack;
+	if (m_piUsageStack!=0) *m_piUsageStack++;
+
+	return *this;
+}
+
+CBListReader::CBListReader(CBList *poList, HRead hRead):
+	 m_poList(poList), m_hRead(hRead)
+{
+	m_piUsageStack=new int;
+	*m_piUsageStack=1;
+}
+
+void CBListReader::AbandonCurrentContent()
+{
+	if (m_piUsageStack!=0)
+	{
+		(*m_piUsageStack)--;
+		if (*m_piUsageStack==0)
+		{
+			// last copy of this reader destroyed
+			m_poList->EndRead(m_hRead);
+			delete m_piUsageStack;
+			m_piUsageStack=0;
+		}
+	}
+}
+
+
+
+// ----------- definitions for CBBaseElem ---------
+
+CBBaseElem::CBBaseElem()
+{
+	lIndex=0;
+	pNext=0;
+	pPrevious=0;
+}
+
+CBBaseElem::~CBBaseElem()
+{
+}
+
+signed long CBBaseElem::IsHigher(class CBBaseElem *pElem)
+{
+	if (lIndex>pElem->GetIndex())
+	{
+		return(1);
+	}
+	else
+	{
+		if (lIndex<pElem->GetIndex())
+		{
+			return(-1);
+		}
+		else
+		{
+			return(0);
+		}
+	}
+}
+
+bool CBBaseElem::PutToArchive(CArchive &oArchive, long lSaveParams) const
+{
+	oArchive << lIndex;
+
+	return true;
+}
+
+bool CBBaseElem::GetFromArchive(CArchive &oArchive, long lLoadParams)
+{
+	oArchive >> lIndex;
+
+	return true;
+}
+
+
+// ------ definitions for CBList ---------
+
+
+CBList::CBList()
+{
+	pFirst=0; pLast=0;
+	lCurrentIndex=1;
+	SortBeforeReading=false;
+	long lCount;
+	for (lCount=lMaxNumRS-1; lCount>=0; lCount--)
+	{
+		bReadEntryUsed[lCount]=false;
+	}
+	lNumOfOpenReadingSessions=0;
+}
+
+CBList::~CBList()
+{
+	if (pFirst!=0)
+	{
+		DeleteAll();
+	}
+}
+
+TBListErr CBList::DeleteAll()
+{
+	if (lNumOfOpenReadingSessions>0)
+	{
+#ifdef _DEBUG
+		// release an error even in encapsulated code
+		// (OCX controls and so on)
+		char *pTest=0;
+		char szTest=*pTest;
+#endif
+		return siListErr;
+	}
+
+	PBBaseElem pCurrent=pFirst, pDummy;
+	while (pCurrent!=0)
+	{
+		pDummy=pCurrent->pNext;
+
+		OnPreDeleteItem(pCurrent);	// inform sub classes of deletion
+		pCurrent->pNext=0;
+		delete pCurrent;
+
+		pCurrent=pDummy;
+	}
+	pFirst=0; pLast=0;
+	return siListNoErr;
+}
+
+signed long CBList::GetSmallestIndex()
+   // determines the lowest available Index
+{
+	long lPos=lCurrentIndex+1;  // begin search at next element
+	if (lPos>iMaxNumberOfCBListItems)
+	{
+		lPos=1;
+	}
+	while (Exists(lPos))
+	{
+		if (lPos==lCurrentIndex)  // one turn with nothing found?
+		{
+			return(siListErr);  // return error
+		}
+		if (lPos>iMaxNumberOfCBListItems)
+		{
+			lPos=1;
+		}
+		lPos++;
+	}
+	lCurrentIndex=lPos;
+	return(lPos);
+}
+
+
+
+PBBaseElem CBList::Add()
+{
+	if (lNumOfOpenReadingSessions>0)
+	{
+#ifdef _DEBUG
+		// release an error even in encapsulated code
+		// (OCX controls and so on)
+		char *pTest=0;
+		char szTest=*pTest;
+#endif
+		return 0;
+	}
+
+	long lIndex=GetSmallestIndex();
+	PBBaseElem pElem;
+	if (lIndex==siListErr)
+	{
+		return 0;
+	}
+
+	pElem=CreateElem();
+
+
+	if (pLast==0) pLast=pElem;
+	pElem->pNext=pFirst;
+	if (pFirst!=0) pElem->pNext->pPrevious=pElem;
+	pElem->pPrevious=0;
+	pFirst=pElem;
+	pElem->lIndex=lIndex;
+	pElem->pParentList=this;
+
+	return pElem;
+}
+
+PBBaseElem CBList::Add(long lDesiredIndex)
+{
+	if (lNumOfOpenReadingSessions>0)
+	{
+#ifdef _DEBUG
+		// release an error even in encapsulated code
+		// (OCX controls and so on)
+		char *pTest=0;
+		char szTest=*pTest;
+#endif
+		return 0;
+	}
+
+	long lIndex=lDesiredIndex;
+
+	if (lIndex<1 || lIndex>iMaxNumberOfCBListItems ||
+		Exists(lIndex))
+	{
+		// the desired index can't be used
+		return Add();
+	}
+
+	PBBaseElem pElem;
+
+	pElem=CreateElem();
+
+
+	if (pLast==0) pLast=pElem;
+	pElem->pNext=pFirst;
+	if (pFirst!=0) pElem->pNext->pPrevious=pElem;
+	pElem->pPrevious=0;
+	pFirst=pElem;
+	pElem->lIndex=lIndex;
+	pElem->pParentList=this;
+
+	return pElem;
+}
+
+bool CBList::OnMapHandle(CBBaseElem *poElem, long lTask, long lHint)
+{
+	// do nothing; return false to avoid a waste of time
+	return false;
+}
+
+
+// set to true virtual
+/*PBBaseElem CBList::CreateElem()
+{
+	PBBaseElem pNewElem=new TBBaseElem;
+	return pNewElem;
+}*/
+
+void CBList::OnPreDeleteItem(PBBaseElem poElem)
+{
+	// do nothing here
+}
+
+TBListErr CBList::DeleteElem(long lIndex)
+{
+	if (lNumOfOpenReadingSessions>0)
+	{
+#ifdef _DEBUG
+		// release an error even in encapsulated code
+		// (OCX controls and so on)
+		char *pTest=0;
+		char szTest=*pTest;
+#endif
+		return siListErr;
+	}
+
+	PBBaseElem pCurrent=pFirst;
+	while (pCurrent!=0)
+	{
+		if (pCurrent->lIndex==lIndex)  // current corresponds to searched?
+		{
+			OnPreDeleteItem(pCurrent);	// inform sub class of deletion
+
+			bool bDeleted=false;
+			if (pCurrent==pFirst)   // first Element to be deleted?
+			{
+				pFirst=pFirst->pNext;
+				if (pFirst!=0)
+				{
+					pFirst->pPrevious=0;
+				}
+				bDeleted=true;
+			}
+			if (pCurrent==pLast)  // last Element to be deleted?
+			{
+				pLast=pLast->pPrevious;
+				if (pLast!=0)
+				{
+					pLast->pNext=0;
+				}
+				bDeleted=true;
+			}
+			if (!bDeleted)
+				// neither first nor last element
+			{
+				pCurrent->pNext->pPrevious=pCurrent->pPrevious;
+				pCurrent->pPrevious->pNext=pCurrent->pNext;
+			}
+			delete pCurrent;
+			return siListNoErr;
+		}
+		pCurrent=pCurrent->pNext;
+	}
+	// if the programm reaches this point the desired element could
+	// not be found
+	return siListErr;
+}
+
+
+bool CBList::Exists(long lIndex) const
+{
+	PBBaseElem pCurrent=pFirst;
+	while (pCurrent!=0)
+	{
+		if (pCurrent->lIndex==lIndex)  // desired element found?
+		{
+			return true;
+		}
+		pCurrent=pCurrent->pNext;
+	}
+	// if the program reaches this point the desired element could
+	// not be found
+	return false;
+}
+
+signed long CBList::GetNumber() const
+{
+	PBBaseElem pCurrent=pFirst;
+	long lNumber=0;
+	while (pCurrent!=0)
+	{
+		lNumber++;
+		pCurrent=pCurrent->pNext;
+	}
+	return lNumber;
+}
+
+
+PBBaseElem CBList::GetElem(long lIndex) const
+{
+	PBBaseElem pCurrent=pFirst;
+	while (pCurrent!=0)
+	{
+		if (pCurrent->lIndex==lIndex)
+		{
+			return pCurrent;
+		}
+		pCurrent=pCurrent->pNext;
+	}
+
+	// element was not found
+	return 0;
+}
+
+PBBaseElem CBList::GetPos(long lPos) const
+{
+	PBBaseElem pCurrent=pFirst;
+	while (pCurrent!=0)
+	{
+		if (lPos==0)
+		{
+			return pCurrent;
+		}
+		pCurrent=pCurrent->pNext;
+		lPos--;
+	}
+	return 0;
+}
+
+long CBList::GetIndexPos(long lIndex) const
+{
+	long lCurPos=0;
+	PBBaseElem pCurrent=pFirst;
+	while (pCurrent!=0)
+	{
+		if (pCurrent->GetIndex()==lIndex)
+		{
+			return lCurPos;
+		}
+
+		pCurrent=pCurrent->pNext;
+		lCurPos++;
+	}
+
+	// index was not found
+	return siListErr;
+}
+
+
+TBListErr CBList::Sort(ESortMode eSortMode)
+	// sort using methods "IsHigher()" and "Exchange()"
+	// error: siListErr
+{
+	if (lNumOfOpenReadingSessions>0)
+	{
+#ifdef _DEBUG
+		// release an error even in encapsulated code
+		// (OCX controls and so on)
+		char *pTest=0;
+		char szTest=*pTest;
+#endif
+		return siListErr;
+	}
+
+	return DoBubbleSort(pFirst, pLast, eSortMode);
+}
+
+bool CBList::SetSortBeforeReading(bool bNewValue)
+	// returns old state
+{
+	if (lNumOfOpenReadingSessions>0)
+	{
+#ifdef _DEBUG
+		// release an error even in encapsulated code
+		// (OCX controls and so on)
+		char *pTest=0;
+		char szTest=*pTest;
+#endif
+		return siListErr;
+	}
+
+	bool old=SortBeforeReading;
+	SortBeforeReading=bNewValue;
+	return old;
+}
+
+signed long CBList::FindOpenReadPos() const
+{
+	long lPos=0;
+	while (bReadEntryUsed[lPos])
+	{
+		if (lPos>=lMaxNumRS)
+		{
+			return siListErr;
+		}
+		lPos++;
+	}
+	return lPos;
+}
+
+HRead CBList::BeginRead()
+{
+	HRead hNewReadingSession=FindOpenReadPos();
+	if (hNewReadingSession==siListErr) return siListErr;
+
+	if (SortBeforeReading) Sort();
+
+	pReadPos[hNewReadingSession]=pFirst;
+	bReadEntryUsed[hNewReadingSession]=true;
+	lNumOfOpenReadingSessions++;
+	return hNewReadingSession;
+}
+
+CBListReader CBList::BeginReadEx()
+{
+	return CBListReader(this, BeginRead());
+}
+
+PBBaseElem CBList::ReadElem(HRead hRead)
+{
+	PBBaseElem pCurrent=pReadPos[hRead];
+	if (pReadPos[hRead]!=0)
+		pReadPos[hRead]=pReadPos[hRead]->pNext;
+	return pCurrent;
+}
+
+TBListErr CBList::EndRead(HRead hRead)
+{
+	bReadEntryUsed[hRead]=false;
+	lNumOfOpenReadingSessions--;
+	return siListNoErr;
+}
+
+TBListErr CBList::EndRead(CBListReader &oReader)
+{
+	oReader.EndReaderSession();
+	return siListNoErr;
+}
+
+bool CBList::Map(long lTask, long lHint)
+{
+	HRead hRead=BeginRead();
+	CBBaseElem *poCurElem;
+	while ((poCurElem=ReadElem(hRead))!=0)
+	{
+		if (!OnMapHandle(poCurElem, lTask, lHint))
+		{
+			// action was aborted
+			EndRead(hRead);
+			return false;
+		}
+	}
+	EndRead(hRead);
+
+	// action was not aborted
+	return true;
+}
+
+
+TBListErr CBList::PutToArchive(CArchive &oArchive, long lSaveParams) const
+{
+	// save the number of elements
+	long lNumberOfElements=GetNumber();
+	oArchive << lNumberOfElements;
+
+	// go through all elements and save them
+	PBBaseElem pCurrent=pFirst;
+	while (pCurrent!=0)
+	{
+		if (!pCurrent->PutToArchive(oArchive, lSaveParams))
+		{
+			return siListErr;
+		}
+
+		pCurrent=pCurrent->pNext;
+	}
+
+	return siListNoErr;
+}
+
+TBListErr CBList::GetFromArchive(CArchive &oArchive, long lLoadParams)
+{
+	// remove old content
+	DeleteAll();
+
+	// get the number of elements
+	long lNumberOfElements;
+	oArchive >> lNumberOfElements;
+
+	// go through all elements and load them
+	while (lNumberOfElements>0)
+	{
+		// create a new element and fill it with data from the stream;
+		// we give a desired index to avoid wasting time searching
+		// for an available id
+		PBBaseElem poCurElem;
+		if (!(poCurElem=Add(23456))->GetFromArchive(oArchive, lLoadParams))
+		{
+			// return siListErr;	// I found this was too strict
+
+			// delete the element that we've just created
+			DeleteElem(poCurElem->GetIndex());
+		}
+
+		lNumberOfElements--;
+	}
+
+	return siListNoErr;
+}
+
+TBListErr CBList::SaveToFile(const char *lpszFileName, long lSaveParams)
+{
+	try
+	{
+		// open the file
+		CFile oFile(lpszFileName, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite);
+		CArchive oArchive(&oFile, CArchive::store);
+
+		// put data to it
+		return PutToArchive(oArchive, lSaveParams)==siListNoErr;
+	}
+	catch (...)
+	{
+		// error opening the file for exclusive writing
+		return siListSavErr;
+	}
+
+}
+
+TBListErr CBList::LoadFromFile(const char *lpszFileName, long lLoadParams)
+{
+	try
+	{
+		// open the file
+		CFile oFile(lpszFileName, CFile::modeRead | CFile::shareDenyNone);
+		CArchive oArchive(&oFile, CArchive::load);
+
+		// get data from it
+		return GetFromArchive(oArchive, lLoadParams)==siListNoErr;
+	}
+	catch (...)
+	{
+		// error opening the file for exclusive writing
+		return siListErr;
+	}
+}
+
+// ---- private definitions ----
+
+TBListErr CBList::Exchange(PBBaseElem pOne, PBBaseElem pTwo)
+{
+	if (pOne==0 || pTwo==0) return siListErr;
+	if (pOne==pTwo) return siListNoErr;
+
+	PBBaseElem pBeforeOne=pOne->GetPrevious();
+	PBBaseElem pBeforeTwo=pTwo->GetPrevious();
+	PBBaseElem pAfterOne=pOne->GetNext();
+	PBBaseElem pAfterTwo=pTwo->GetNext();
+
+	// set new pFirst and pLast states, if necessary
+	if (pOne==pFirst) pFirst=pTwo; else
+		if (pTwo==pFirst) pFirst=pOne;
+	if (pOne==pLast) pLast=pTwo; else
+		if (pTwo==pLast) pLast=pOne;
+
+	if (pBeforeTwo==pOne)
+	{	// Elements follow on each other
+		if (pOne->pPrevious!=0)	pOne->pPrevious->pNext=pTwo;
+		if (pTwo->pNext!=0)		pTwo->pNext->pPrevious=pOne;
+
+		pTwo->pPrevious=pOne->pPrevious;
+		pOne->pPrevious=pTwo;
+
+		pOne->pNext=pTwo->pNext;
+		pTwo->pNext=pOne;
+		return siListNoErr;
+	}
+	if (pBeforeOne==pTwo)
+	{	// Elements follow on each other
+		if (pTwo->pPrevious!=0)	pTwo->pPrevious->pNext=pOne;
+		if (pOne->pNext!=0)		pOne->pNext->pPrevious=pTwo;
+
+		pOne->pPrevious=pTwo->pPrevious;
+		pTwo->pPrevious=pOne;
+
+		pTwo->pNext=pOne->pNext;
+		pOne->pNext=pTwo;
+		return siListNoErr;
+	}
+
+	// if the execution comes to here both pOne and pTwo do not
+	// follow each other
+
+	if (pTwo->pNext!=0)		pTwo->pNext->pPrevious=pOne;
+	if (pTwo->pPrevious!=0)	pTwo->pPrevious->pNext=pOne;
+	if (pOne->pNext!=0)		pOne->pNext->pPrevious=pTwo;
+	if (pOne->pPrevious!=0)	pOne->pPrevious->pNext=pTwo;
+	
+	PBBaseElem pDummy;
+
+	pDummy=pOne->pNext;
+	pOne->pNext=pTwo->pNext;
+	pTwo->pNext=pDummy;
+
+	pDummy=pOne->pPrevious;
+	pOne->pPrevious=pTwo->pPrevious;
+	pTwo->pPrevious=pDummy;
+
+	return siListNoErr;
+}
+
+PBBaseElem CBList::FindLowest(PBBaseElem pBeginFrom, PBBaseElem pGoTo, ESortMode eSortMode)
+{   // finds the element with the lowest key in a given interval
+	if (pBeginFrom==pGoTo) return pBeginFrom;
+
+	PBBaseElem pCurLowest=pBeginFrom;
+	while (pBeginFrom!=pGoTo->GetNext())
+	{
+		if (eSortMode==eAscending)
+		{
+			if (pBeginFrom->IsHigher(pCurLowest)==-1)
+				pCurLowest=pBeginFrom;
+		}
+		else
+		{
+			if (pBeginFrom->IsHigher(pCurLowest)==1)
+				pCurLowest=pBeginFrom;
+		}
+
+		pBeginFrom=pBeginFrom->pNext;
+	}
+	return pCurLowest;
+}
+
+
+TBListErr CBList::DoBubbleSort(PBBaseElem pLeft, PBBaseElem pRight, ESortMode eSortMode)
+{
+	if (pLeft==0 || pRight==0) return siListNoErr;	// sucessfully finished
+	if (pLeft==pRight) return siListNoErr;  // sucessfully finished
+
+	
+
+	PBBaseElem pLeftSortBorder=pLeft;
+	PBBaseElem pLowestElem;
+	while (pLeftSortBorder!=pRight)
+	{
+		pLowestElem=FindLowest(pLeftSortBorder, pRight, eSortMode);
+
+		// exchanging the elements may have lead to a change of pRight
+		if (pRight==pLowestElem) pRight=pLeftSortBorder;
+		else if (pRight==pLeftSortBorder) pRight=pLowestElem;
+
+		Exchange(pLowestElem, pLeftSortBorder);
+
+		// pLowestElem's successor is now the new left sort border
+		pLeftSortBorder=pLowestElem->pNext;
+	}
+	return siListNoErr;
+}
+
--- /dev/null
+++ b/wingui/PageCheckboxCtrlContent.cpp
@@ -1,0 +1,56 @@
+// PageCheckboxCtrlContent.cpp: implementation of the CPageCheckboxCtrlContent class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "PageCheckboxCtrlContent.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPageCheckboxCtrlContent::CPageCheckboxCtrlContent(bool bCheckMark):
+	m_bCheckMark(bCheckMark)
+{
+
+}
+
+CPageCheckboxCtrlContent::~CPageCheckboxCtrlContent()
+{
+
+}
+
+
+CString CPageCheckboxCtrlContent::GetHashString() const
+{
+	return "CPageCheckboxCtrlContent-"+CString(m_bCheckMark ? "T" : "F");
+}
+
+void CPageCheckboxCtrlContent::ApplyCheckCodeToButton(CButton *poButton) const
+{
+	if (Is3rdState())
+	{
+		poButton->SetButtonStyle(BS_AUTO3STATE);
+		poButton->SetCheck(2);
+	}
+	else
+	{
+		poButton->SetCheck(m_bCheckMark ? 1 : 0);
+	}
+}
+
+void CPageCheckboxCtrlContent::ApplyToJob(bool &bBool) const
+{
+	if (!Is3rdState())
+	{
+		bBool=GetCheckMark();
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/PageCheckboxCtrlContent.h
@@ -1,0 +1,43 @@
+// PageCheckboxCtrlContent.h: interface for the CPageCheckboxCtrlContent class.
+// Author: Torsten Landmann
+//
+// is able to save the content of a checkbox including the 3rd state
+// and perform merge operations so that data for several jobs can be
+// merged
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PAGECHECKBOXCTRLCONTENT_H__7B47B269_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PAGECHECKBOXCTRLCONTENT_H__7B47B269_0FF8_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "AbstractPageCtrlContent.h"
+
+class CPageCheckboxCtrlContent : public CAbstractPageCtrlContent  
+{
+public:
+	CPageCheckboxCtrlContent(bool bCheckMark=false);
+	virtual ~CPageCheckboxCtrlContent();
+
+	// setting content automatically disables the 3rd state
+	void SetCheckMark(bool bCheckMark)		{ SetIs3rdState(false); m_bCheckMark=bCheckMark; }
+	bool GetCheckMark() const				{ return m_bCheckMark; }
+
+	// accepts values returned by CButton::GetCheck()
+	void SetCheckCode(int iCheckCode)		{ SetIs3rdState(iCheckCode==2); m_bCheckMark=iCheckCode==1; }
+	int GetCheckCode() const				{ if (Is3rdState()) return 2; else return m_bCheckMark ? 1 : 0; }
+	void ApplyCheckCodeToButton(CButton *poButton) const;		// this member should prefered over GetCheckCode() because it also enables the 3rd state, if necessary
+
+	void ApplyToJob(bool &bBool) const;
+
+	// implementation of CAbstractPageCtrlContent method
+	virtual CString GetHashString() const;
+
+private:
+	bool m_bCheckMark;
+};
+
+#endif // !defined(AFX_PAGECHECKBOXCTRLCONTENT_H__7B47B269_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/PageComboBoxCtrlContent.cpp
@@ -1,0 +1,138 @@
+// PageComboBoxCtrlContent.cpp: implementation of the CPageComboBoxCtrlContent class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "PageComboBoxCtrlContent.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPageComboBoxCtrlContent::CPageComboBoxCtrlContent()
+{
+
+}
+
+CPageComboBoxCtrlContent::~CPageComboBoxCtrlContent()
+{
+
+}
+
+void CPageComboBoxCtrlContent::SetContentSelection(int iSelectionId)
+{
+	CString oSelection;
+	oSelection.Format("%d", iSelectionId);
+	SetContentText(oSelection);
+}
+
+int CPageComboBoxCtrlContent::GetContentSelection() const
+{
+	CString oSelectionString(GetContentText());
+	if (oSelectionString.IsEmpty()) return -1;		// 3rd state
+	int iSelectionId;
+	if (sscanf(oSelectionString, "%d", &iSelectionId)!=1)
+	{
+		// error while parsing
+		return -1;
+	}
+
+	return iSelectionId;
+}
+
+void CPageComboBoxCtrlContent::SetContentText(const CString &oText)
+{
+	SetContent(oText);
+}
+
+const CString& CPageComboBoxCtrlContent::GetContentText() const
+{
+	return GetContent();
+}
+
+CString& CPageComboBoxCtrlContent::GetContentText()
+{
+	return GetContent();
+}
+
+void CPageComboBoxCtrlContent::SetCurComboBoxSelectionText(CComboBox *poComboBox)
+{
+	int iCurSelection=poComboBox->GetCurSel();
+	if (iCurSelection<0)
+	{
+		SetIs3rdState(true);
+		return;
+	}
+
+	CString oText;
+	poComboBox->GetLBText(iCurSelection, oText);
+	SetContent(oText);
+}
+
+void CPageComboBoxCtrlContent::ApplyToJob(CString &oNativeJobPropertyTextString) const
+{
+	if (!Is3rdState())
+	{
+		oNativeJobPropertyTextString=GetContentText();
+	}
+}
+
+void CPageComboBoxCtrlContent::ApplyToJob(long &lNativeJobPropertySelectionLong) const
+{
+	int iId=GetContentSelection();
+	if (iId>=0)
+	{
+		lNativeJobPropertySelectionLong=GetContentSelection();
+	}
+}
+
+void CPageComboBoxCtrlContent::ApplyToComboBoxVariable(int &iSelectionVariable) const
+{
+	int iId=GetContentSelection();
+	if (iId>=0)
+	{
+		iSelectionVariable=GetContentSelection();
+	}
+}
+
+void CPageComboBoxCtrlContent::ApplyToComboBoxVariable(CString &oSelectionVariable) const
+{
+	if (!Is3rdState())
+	{
+		oSelectionVariable=GetContentText();
+	}
+}
+
+void CPageComboBoxCtrlContent::ApplyToComboBoxPointer(CComboBox *poComboBox) const
+{
+	// important: this method is only for drop down combo boxes
+	// that have been used with the text feature
+	CString oStringToSelect;
+	if (Is3rdState())
+	{
+		oStringToSelect.Empty();
+	}
+	else
+	{
+		oStringToSelect=GetContent();
+	}
+
+	int iSelection=poComboBox->FindStringExact(0, oStringToSelect);
+	if (iSelection>=0)
+	{
+		poComboBox->SetCurSel(iSelection);
+	}
+}
+
+CString CPageComboBoxCtrlContent::GetHashString() const
+{
+	return CString("CPageComboBoxCtrlContent:")+CPageEditCtrlContent::GetHashString();
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/PageComboBoxCtrlContent.h
@@ -1,0 +1,69 @@
+// PageComboBoxCtrlContent.h: interface for the CPageComboBoxCtrlContent class.
+// Author: Torsten Landmann
+//
+// is able to save the content of a combo box control including the 3rd state
+// and perform merge operations so that data for several jobs can be
+// merged
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PAGECOMBOBOXCTRLCONTENT_H__C245DF24_11A6_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PAGECOMBOBOXCTRLCONTENT_H__C245DF24_11A6_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "PageEditCtrlContent.h"
+
+class CPageComboBoxCtrlContent : public CPageEditCtrlContent
+	// I'd rather inherit from CPageEditCtrlContent as private but
+	// that'd be too complicated since CAbstractPageCtrlContent implements
+	// essential behaviour that must still be accessible from outside
+{
+public:
+	CPageComboBoxCtrlContent();
+	virtual ~CPageComboBoxCtrlContent();
+
+	// note: you must not mix selection and text content
+	// based management for one combo control to manage
+	// at a time
+
+	// data for combo controls that you wish to manage
+	// based on their selection ids
+	void SetContentSelection(int iSelectionId);
+	int GetContentSelection() const;		// returns a negative value if in 3rd state or in case of errors
+
+	// data for combo controls that you wish to manage
+	// based on their currently selected/entered texts
+	void SetContentText(const CString &oText);
+	const CString& GetContentText() const;
+	CString& GetContentText();
+	// this method is only for drop down combo boxes; it fetches
+	// the text of the current selection and applies it via
+	// SetCurrentText(const CString&)
+	void SetCurComboBoxSelectionText(CComboBox *poComboBox);
+
+	void ApplyToJob(CString &oNativeJobPropertyTextString) const;
+	void ApplyToJob(long &lNativeJobPropertySelectionLong) const;
+
+	// apply to variables that are defined in the class wizard
+	void ApplyToComboBoxVariable(int &iSelectionVariable) const;
+	void ApplyToComboBoxVariable(CString &oSelectionVariable) const;
+
+	// important: this method is only for drop down combo boxes
+	// that have been used with the text feature; note
+	// that the behaviour is undefined if the string that must
+	// be set doesn't exist in the combo box; this includes
+	// the empty string that is attempted to be set when
+	// the 3rd state is detected
+	void ApplyToComboBoxPointer(CComboBox *poComboBox) const;
+
+	// implementation of CAbstractPageCtrlContent method
+	virtual CString GetHashString() const;
+
+private:
+	// this class does not need own data
+};
+
+#endif // !defined(AFX_PAGECOMBOBOXCTRLCONTENT_H__C245DF24_11A6_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/PageEditCtrlContent.cpp
@@ -1,0 +1,111 @@
+// PageEditCtrlContent.cpp: implementation of the CPageEditCtrlContent class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "PageEditCtrlContent.h"
+#include "WindowUtil.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+CString CPageEditCtrlContent::s_oEmptyString="";
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPageEditCtrlContent::CPageEditCtrlContent()
+{
+}
+
+CPageEditCtrlContent::CPageEditCtrlContent(const CString &oEditCtrlContent):
+	m_oEditCtrlContent(oEditCtrlContent)
+{
+}
+
+CPageEditCtrlContent::~CPageEditCtrlContent()
+{
+
+}
+
+void CPageEditCtrlContent::SetContent(const CString &oEditCtrlContent)
+{
+	if (oEditCtrlContent.IsEmpty())
+	{
+		SetIs3rdState(true);
+	}
+	else
+	{
+		SetIs3rdState(false);
+		m_oEditCtrlContent=oEditCtrlContent;
+	}
+}
+
+void CPageEditCtrlContent::SetContent(long lEditCtrlContent, bool bNegativeIs3rdState)
+{
+	if (bNegativeIs3rdState && lEditCtrlContent<0)
+	{
+		SetIs3rdState(true);
+		return;
+	}
+
+	m_oEditCtrlContent.Format("%d", lEditCtrlContent);
+	SetIs3rdState(false);
+}
+
+const CString& CPageEditCtrlContent::GetContent() const
+{
+	if (Is3rdState())
+	{
+		return s_oEmptyString;
+	}
+	else
+	{
+		return m_oEditCtrlContent;
+	}
+}
+
+CString& CPageEditCtrlContent::GetContent()
+{
+	if (Is3rdState())
+	{
+		return s_oEmptyString;
+	}
+	else
+	{
+		return m_oEditCtrlContent;
+	}
+}
+
+void CPageEditCtrlContent::ApplyToJob(CString &oNativeJobPropertyString) const
+{
+	if (!Is3rdState())
+	{
+		oNativeJobPropertyString=GetContent();
+	}
+}
+
+void CPageEditCtrlContent::ApplyToJob(long &lNativeJobPropertyLong) const
+{
+	if (!Is3rdState())
+	{
+		CString oContent(GetContent());
+		CWindowUtil::FilterString(oContent, "0123456789");
+		long lNumber;
+		if (sscanf(oContent, "%d", &lNumber)==1)
+		{
+			lNativeJobPropertyLong=lNumber;
+		}
+	}
+}
+
+CString CPageEditCtrlContent::GetHashString() const
+{
+	return "CPageEditCtrlContent-"+m_oEditCtrlContent;
+}
--- /dev/null
+++ b/wingui/PageEditCtrlContent.h
@@ -1,0 +1,43 @@
+// PageEditCtrlContent.h: interface for the CPageEditCtrlContent class.
+// Author: Torsten Landmann
+//
+// is able to save the content of an edit control including the 3rd state
+// and perform merge operations so that data for several jobs can be
+// merged
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PAGEEDITCTRLCONTENT_H__7B47B267_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PAGEEDITCTRLCONTENT_H__7B47B267_0FF8_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "AbstractPageCtrlContent.h"
+
+class CPageEditCtrlContent : public CAbstractPageCtrlContent
+{
+public:
+	CPageEditCtrlContent();
+	CPageEditCtrlContent(const CString &oEditCtrlContent);
+	virtual ~CPageEditCtrlContent();
+
+	// setting content automatically disables the 3rd state
+	void SetContent(const CString &oEditCtrlContent);
+	void SetContent(long lEditCtrlContent, bool bNegativeIs3rdState=false);
+	const CString& GetContent() const;
+	CString& GetContent();
+
+	void ApplyToJob(CString &oNativeJobPropertyString) const;
+	void ApplyToJob(long &lNativeJobPropertyLong) const;
+
+	// implementation of CAbstractPageCtrlContent method
+	virtual CString GetHashString() const;
+
+private:
+	CString m_oEditCtrlContent;
+	static CString s_oEmptyString;
+};
+
+#endif // !defined(AFX_PAGEEDITCTRLCONTENT_H__7B47B267_0FF8_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/PageRadioGroupCtrlContent.cpp
@@ -1,0 +1,33 @@
+// PageRadioGroupCtrlContent.cpp: implementation of the CPageRadioGroupCtrlContent class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "PageRadioGroupCtrlContent.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPageRadioGroupCtrlContent::CPageRadioGroupCtrlContent()
+{
+
+}
+
+CPageRadioGroupCtrlContent::~CPageRadioGroupCtrlContent()
+{
+
+}
+
+CString CPageRadioGroupCtrlContent::GetHashString() const
+{
+	return CString("CPageRadioGroupCtrlContent:")+CPageEditCtrlContent::GetHashString();
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/PageRadioGroupCtrlContent.h
@@ -1,0 +1,38 @@
+// PageRadioGroupCtrlContent.h: interface for the CPageRadioGroupCtrlContent class.
+// Author: Torsten Landmann
+//
+// is able to save the content of a radio button group including the 3rd state
+// and perform merge operations so that data for several jobs can be
+// merged
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PAGERADIOGROUPCTRLCONTENT_H__9818D045_158E_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PAGERADIOGROUPCTRLCONTENT_H__9818D045_158E_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "PageEditCtrlContent.h"
+
+class CPageRadioGroupCtrlContent : public CPageEditCtrlContent
+{
+public:
+	CPageRadioGroupCtrlContent();
+	virtual ~CPageRadioGroupCtrlContent();
+
+	// callers should only call the SetContent(long) and ApplyToJob(long) methods
+	// what are inherited from CPageEditCtrlContent
+
+	void GetFromRadioGroupVariable(int iVariable, long lNumberOfRadiosInGroup)			{ SetContent(iVariable, true); if (iVariable>=lNumberOfRadiosInGroup) SetIs3rdState(true); }
+	void ApplyToRadioGroupVariable(int &iVariable) const								{ long lContent=-1; ApplyToJob(lContent); iVariable=lContent; }
+
+	// implementation of CAbstractPageCtrlContent method
+	virtual CString GetHashString() const;
+
+private:
+	// have no own data members
+};
+
+#endif // !defined(AFX_PAGERADIOGROUPCTRLCONTENT_H__9818D045_158E_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/ProcessJobStatusDialog.cpp
@@ -1,0 +1,156 @@
+// ProcessJobStatusDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "ProcessJobStatusDialog.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#ifndef SW_VIS_CODE
+#define SW_VIS_CODE(bVisible)		((bVisible) ? SW_SHOW : SW_HIDE)
+#endif
+
+CProcessJobStatusDialog *CProcessJobStatusDialog::m_poDialog=0;
+
+/////////////////////////////////////////////////////////////////////////////
+// CProcessJobStatusDialog dialog
+
+
+CProcessJobStatusDialog::CProcessJobStatusDialog(CProcessingStartStopPauseInteractable *poClient, CWnd* pParent /*=NULL*/)
+	: CDialog(CProcessJobStatusDialog::IDD, pParent),
+	m_poClient(poClient)
+{
+	//{{AFX_DATA_INIT(CProcessJobStatusDialog)
+	m_oLabelBottomStatusText = _T("");
+	m_oLabelTopStatusText = _T("");
+	//}}AFX_DATA_INIT
+}
+
+CProcessJobStatusDialog::~CProcessJobStatusDialog()
+{
+}
+
+void CProcessJobStatusDialog::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CProcessJobStatusDialog)
+	DDX_Control(pDX, IDC_BUTTONPAUSE, m_ctrlButtonPause);
+	DDX_Control(pDX, IDC_BUTTONCONTINUE, m_ctrlButtonContinue);
+	DDX_Control(pDX, IDC_BUTTONABORT, m_ctrlButtonAbort);
+	DDX_Control(pDX, IDC_PROGRESS1, m_ctrlProgressBar);
+	DDX_Text(pDX, IDC_LABELBOTTOMSTATUSTEXT, m_oLabelBottomStatusText);
+	DDX_Text(pDX, IDC_LABELTOPSTATUSTEXT, m_oLabelTopStatusText);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CProcessJobStatusDialog, CDialog)
+	//{{AFX_MSG_MAP(CProcessJobStatusDialog)
+	ON_BN_CLICKED(IDC_BUTTONABORT, OnButtonAbort)
+	ON_BN_CLICKED(IDC_BUTTONPAUSE, OnButtonPause)
+	ON_BN_CLICKED(IDC_BUTTONCONTINUE, OnButtonContinue)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CProcessJobStatusDialog message handlers
+
+BOOL CProcessJobStatusDialog::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	// TODO: Add extra initialization here
+	m_ctrlProgressBar.SetRange32(0, 10000);
+
+	// install a timer to initiiate the processing
+	ASSERT(m_poDialog==0);
+	m_poDialog=this;
+	::SetTimer(*this, 100, 200, TimerProc);
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CProcessJobStatusDialog::SetStatus(double dProgress, const CString &oTopStatusText, const CString &oBottomStatusText)
+{
+	m_ctrlProgressBar.SetPos((int)dProgress*100);
+	m_oLabelTopStatusText=oTopStatusText;
+	m_oLabelBottomStatusText=oBottomStatusText;
+	UpdateData(FALSE);
+}
+
+void CProcessJobStatusDialog::SetAvailableActions(bool bStop, bool bPause)
+{
+	m_ctrlButtonAbort.ShowWindow(SW_VIS_CODE(bStop));
+	m_ctrlButtonPause.ShowWindow(SW_VIS_CODE(bPause));
+	m_ctrlButtonContinue.ShowWindow(SW_VIS_CODE(bPause));
+}
+
+void CProcessJobStatusDialog::ProcessUserMessages()
+{
+	MSG msg;
+	while (::PeekMessage(&msg, /**this*/0, 0, 0, PM_REMOVE)) 
+	{ 
+		::TranslateMessage(&msg);
+		::DispatchMessage(&msg); 
+	}
+}
+
+void CProcessJobStatusDialog::ReturnToCaller(bool bSuccess)
+{
+	if (bSuccess)
+	{
+		CDialog::OnOK();
+	}
+	else
+	{
+		CDialog::OnCancel();
+	}
+}
+
+void CALLBACK EXPORT CProcessJobStatusDialog::TimerProc(
+	   HWND hWnd,      // handle of CWnd that called SetTimer
+	   UINT nMsg,      // WM_TIMER
+	   UINT nIDEvent,  // timer identification
+	   DWORD dwTime    // system time
+	)
+{
+	// kill the timer
+	::KillTimer(hWnd, nIDEvent);
+
+	if (m_poDialog==0)
+	{
+		// ignore timer
+		return;
+	}
+
+	ASSERT(m_poDialog!=0);
+
+	// initiate the processing
+	CProcessJobStatusDialog *poDialog=m_poDialog;
+	m_poDialog=0;
+	poDialog->m_poClient->Start(poDialog);
+}
+
+void CProcessJobStatusDialog::OnButtonAbort() 
+{
+	// TODO: Add your control notification handler code here
+	m_poClient->Stop();
+}
+
+void CProcessJobStatusDialog::OnButtonPause() 
+{
+	// TODO: Add your control notification handler code here
+	m_poClient->Pause();
+}
+
+void CProcessJobStatusDialog::OnButtonContinue() 
+{
+	// TODO: Add your control notification handler code here
+	m_poClient->Start(0);
+}
--- /dev/null
+++ b/wingui/ProcessJobStatusDialog.h
@@ -1,0 +1,76 @@
+#if !defined(AFX_PROCESSJOBSTATUSDIALOG_H__A1444E8F_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PROCESSJOBSTATUSDIALOG_H__A1444E8F_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// ProcessJobStatusDialog.h : header file
+//
+
+#include "ProcessingStatusDialogInfoFeedbackCallbackInterface.h"
+#include "ProcessingStartStopPauseInteractable.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CProcessJobStatusDialog dialog
+
+class CProcessJobStatusDialog : public CDialog, public CProcessingStatusDialogInfoFeedbackCallbackInterface
+{
+// Construction
+public:
+	CProcessJobStatusDialog(CProcessingStartStopPauseInteractable *poClient, CWnd* pParent = NULL);   // standard constructor
+	virtual ~CProcessJobStatusDialog();
+
+// Dialog Data
+	//{{AFX_DATA(CProcessJobStatusDialog)
+	enum { IDD = IDD_PROCESSJOBSTATUSDIALOG };
+	CButton	m_ctrlButtonPause;
+	CButton	m_ctrlButtonContinue;
+	CButton	m_ctrlButtonAbort;
+	CProgressCtrl	m_ctrlProgressBar;
+	CString	m_oLabelBottomStatusText;
+	CString	m_oLabelTopStatusText;
+	//}}AFX_DATA
+
+	// implementation to interface CProcessingStatusDialogInfoFeedbackCallbackInterface
+	virtual void SetStatus(double dProgress, const CString &oTopStatusText, const CString &oBottomStatusText);
+	virtual void SetAvailableActions(bool bStop, bool bPause);
+	virtual void ProcessUserMessages();
+	virtual void ReturnToCaller(bool bSuccess);
+
+	static CProcessJobStatusDialog *m_poDialog;
+	static void CALLBACK EXPORT TimerProc(
+	   HWND hWnd,      // handle of CWnd that called SetTimer
+	   UINT nMsg,      // WM_TIMER
+	   UINT nIDEvent,  // timer identification
+	   DWORD dwTime    // system time
+	);
+
+
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CProcessJobStatusDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CProcessJobStatusDialog)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnButtonAbort();
+	afx_msg void OnButtonPause();
+	afx_msg void OnButtonContinue();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+	CProcessingStartStopPauseInteractable *m_poClient;
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PROCESSJOBSTATUSDIALOG_H__A1444E8F_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/ProcessJobStatusDialog2.cpp
@@ -1,0 +1,135 @@
+// ProcessJobStatusDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "ProcessJobStatusDialog.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#ifndef SW_VIS_CODE
+#define SW_VIS_CODE(bVisible)		((bVisible) ? SW_SHOW : SW_HIDE)
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CProcessJobStatusDialog dialog
+
+
+CProcessJobStatusDialog::CProcessJobStatusDialog(CProcessingStartStopPauseInteractable *poClient, CWnd* pParent /*=NULL*/)
+	: CDialog(CProcessJobStatusDialog::IDD, pParent),
+	m_poClient(poClient)
+{
+	//{{AFX_DATA_INIT(CProcessJobStatusDialog)
+	m_oLabelBottomStatusText = _T("");
+	m_oLabelTopStatusText = _T("");
+	//}}AFX_DATA_INIT
+}
+
+CProcessJobStatusDialog::~CProcessJobStatusDialog()
+{
+}
+
+void CProcessJobStatusDialog::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CProcessJobStatusDialog)
+	DDX_Control(pDX, IDC_BUTTONPAUSE, m_ctrlButtonPause);
+	DDX_Control(pDX, IDC_BUTTONCONTINUE, m_ctrlButtonContinue);
+	DDX_Control(pDX, IDC_BUTTONABORT, m_ctrlButtonAbort);
+	DDX_Control(pDX, IDC_PROGRESS1, m_ctrlProgressBar);
+	DDX_Text(pDX, IDC_LABELBOTTOMSTATUSTEXT, m_oLabelBottomStatusText);
+	DDX_Text(pDX, IDC_LABELTOPSTATUSTEXT, m_oLabelTopStatusText);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CProcessJobStatusDialog, CDialog)
+	//{{AFX_MSG_MAP(CProcessJobStatusDialog)
+	ON_BN_CLICKED(IDC_BUTTONABORT, OnButtonAbort)
+	ON_BN_CLICKED(IDC_BUTTONPAUSE, OnButtonPause)
+	ON_BN_CLICKED(IDC_BUTTONCONTINUE, OnButtonContinue)
+	ON_MESSAGE(4000, OnStartProcessing)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CProcessJobStatusDialog message handlers
+
+BOOL CProcessJobStatusDialog::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	// TODO: Add extra initialization here
+	m_ctrlProgressBar.SetRange32(0, 10000);
+
+	// install a timer to initiiate the processing
+	PostMessage(4000, 0, 0);
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CProcessJobStatusDialog::SetStatus(double dProgress, const CString &oTopStatusText, const CString &oBottomStatusText)
+{
+	m_ctrlProgressBar.SetPos((int)dProgress*100);
+	m_oLabelTopStatusText=oTopStatusText;
+	m_oLabelBottomStatusText=oBottomStatusText;
+	UpdateData(FALSE);
+}
+
+void CProcessJobStatusDialog::SetAvailableActions(bool bStop, bool bPause)
+{
+	m_ctrlButtonAbort.ShowWindow(SW_VIS_CODE(bStop));
+	m_ctrlButtonPause.ShowWindow(SW_VIS_CODE(bPause));
+	m_ctrlButtonContinue.ShowWindow(SW_VIS_CODE(bPause));
+}
+
+void CProcessJobStatusDialog::ProcessUserMessages()
+{
+	MSG msg;
+	while (::PeekMessage(&msg, /**this*/0, 0, 0, PM_REMOVE)) 
+	{ 
+		::TranslateMessage(&msg);
+		::DispatchMessage(&msg); 
+	}
+}
+
+void CProcessJobStatusDialog::ReturnToCaller(bool bSuccess)
+{
+	if (bSuccess)
+	{
+		CDialog::OnOK();
+	}
+	else
+	{
+		CDialog::OnCancel();
+	}
+}
+
+LRESULT CProcessJobStatusDialog::OnStartProcessing(WPARAM wParam, LPARAM lParam)
+{
+	m_poClient->Start(this);
+	return 0;
+}
+
+void CProcessJobStatusDialog::OnButtonAbort() 
+{
+	// TODO: Add your control notification handler code here
+	m_poClient->Stop();
+}
+
+void CProcessJobStatusDialog::OnButtonPause() 
+{
+	// TODO: Add your control notification handler code here
+	m_poClient->Pause();
+}
+
+void CProcessJobStatusDialog::OnButtonContinue() 
+{
+	// TODO: Add your control notification handler code here
+	m_poClient->Start(0);
+}
--- /dev/null
+++ b/wingui/ProcessJobStatusDialog2.h
@@ -1,0 +1,68 @@
+#if !defined(AFX_PROCESSJOBSTATUSDIALOG_H__A1444E8F_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PROCESSJOBSTATUSDIALOG_H__A1444E8F_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// ProcessJobStatusDialog.h : header file
+//
+
+#include "ProcessingStatusDialogInfoFeedbackCallbackInterface.h"
+#include "ProcessingStartStopPauseInteractable.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CProcessJobStatusDialog dialog
+
+class CProcessJobStatusDialog : public CDialog, public CProcessingStatusDialogInfoFeedbackCallbackInterface
+{
+// Construction
+public:
+	CProcessJobStatusDialog(CProcessingStartStopPauseInteractable *poClient, CWnd* pParent = NULL);   // standard constructor
+	virtual ~CProcessJobStatusDialog();
+
+// Dialog Data
+	//{{AFX_DATA(CProcessJobStatusDialog)
+	enum { IDD = IDD_PROCESSJOBSTATUSDIALOG };
+	CButton	m_ctrlButtonPause;
+	CButton	m_ctrlButtonContinue;
+	CButton	m_ctrlButtonAbort;
+	CProgressCtrl	m_ctrlProgressBar;
+	CString	m_oLabelBottomStatusText;
+	CString	m_oLabelTopStatusText;
+	//}}AFX_DATA
+
+	// implementation to interface CProcessingStatusDialogInfoFeedbackCallbackInterface
+	virtual void SetStatus(double dProgress, const CString &oTopStatusText, const CString &oBottomStatusText);
+	virtual void SetAvailableActions(bool bStop, bool bPause);
+	virtual void ProcessUserMessages();
+	virtual void ReturnToCaller(bool bSuccess);
+
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CProcessJobStatusDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CProcessJobStatusDialog)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnButtonAbort();
+	afx_msg void OnButtonPause();
+	afx_msg void OnButtonContinue();
+	afx_msg LRESULT OnStartProcessing(WPARAM wParam, LPARAM lParam);
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+	CProcessingStartStopPauseInteractable *m_poClient;
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PROCESSJOBSTATUSDIALOG_H__A1444E8F_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/ProcessingStartStopPauseInteractable.cpp
@@ -1,0 +1,28 @@
+// ProcessingStartStopPauseInteractable.cpp: implementation of the CProcessingStartStopPauseInteractable class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "ProcessingStartStopPauseInteractable.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CProcessingStartStopPauseInteractable::CProcessingStartStopPauseInteractable()
+{
+
+}
+
+CProcessingStartStopPauseInteractable::~CProcessingStartStopPauseInteractable()
+{
+
+}
--- /dev/null
+++ b/wingui/ProcessingStartStopPauseInteractable.h
@@ -1,0 +1,37 @@
+// ProcessingStartStopPauseInteractable.h: interface for the CProcessingStartStopPauseInteractable class.
+// Author: Torsten Landmann
+//
+// this class is an interface to start, stop or pause processes (i.e. job processing)
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PROCESSINGSTARTSTOPPAUSEINTERACTABLE_H__A1444E90_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PROCESSINGSTARTSTOPPAUSEINTERACTABLE_H__A1444E90_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "ProcessingStatusDialogInfoFeedbackCallbackInterface.h"
+
+class CProcessingStartStopPauseInteractable  
+{
+public:
+	CProcessingStartStopPauseInteractable();
+	virtual ~CProcessingStartStopPauseInteractable();
+
+	// the flow of the following three methods is as follows:
+	// at the beginning there is a call to Start() WITH valid parameter
+	// Stop() and Pause() can only occur after Start() has been called at least once;
+	// When Stop() has been sent the called object should cleanup;
+	// when Pause() has been sent the called object should be idle() until
+	// a new call to Start() has taken place; the second call may contain
+	// a 0 parameter, so the previous value is to be used
+
+	virtual void Start(CProcessingStatusDialogInfoFeedbackCallbackInterface *poInfoTarget)=0;
+
+	virtual void Stop()=0;
+	virtual void Pause()=0;
+};
+
+#endif // !defined(AFX_PROCESSINGSTARTSTOPPAUSEINTERACTABLE_H__A1444E90_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/ProcessingStatusDialogInfoFeedbackCallbackInterface.cpp
@@ -1,0 +1,28 @@
+// ProcessingStatusDialogInfoFeedbackCallbackInterface.cpp: implementation of the CProcessingStatusDialogInfoFeedbackCallbackInterface class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "ProcessingStatusDialogInfoFeedbackCallbackInterface.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CProcessingStatusDialogInfoFeedbackCallbackInterface::CProcessingStatusDialogInfoFeedbackCallbackInterface()
+{
+
+}
+
+CProcessingStatusDialogInfoFeedbackCallbackInterface::~CProcessingStatusDialogInfoFeedbackCallbackInterface()
+{
+
+}
--- /dev/null
+++ b/wingui/ProcessingStatusDialogInfoFeedbackCallbackInterface.h
@@ -1,0 +1,32 @@
+// ProcessingStatusDialogInfoFeedbackCallbackInterface.h: interface for the CProcessingStatusDialogInfoFeedbackCallbackInterface class.
+// Author: Torsten Landmann
+//
+// This class is an interface to enable a process to update the status
+// dialog that displays the progress and further information
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PROCESSINGSTATUSDIALOGINFOFEEDBACKCALLBACKINTERFACE_H__A1444E91_1546_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PROCESSINGSTATUSDIALOGINFOFEEDBACKCALLBACKINTERFACE_H__A1444E91_1546_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CProcessingStatusDialogInfoFeedbackCallbackInterface  
+{
+public:
+	CProcessingStatusDialogInfoFeedbackCallbackInterface();
+	virtual ~CProcessingStatusDialogInfoFeedbackCallbackInterface();
+
+	// progress must be given in percent
+	virtual void SetStatus(double dProgress, const CString &oTopStatusText, const CString &oBottomStatusText)=0;
+	virtual void SetAvailableActions(bool bStop, bool bPause)=0;
+	virtual void ProcessUserMessages()=0;
+
+	// the return value is the status code to return to the caller;
+	// if bSuccess then IDOK is returned, IDCANCEL otherwise
+	virtual void ReturnToCaller(bool bSuccess)=0;
+};
+
+#endif // !defined(AFX_PROCESSINGSTATUSDIALOGINFOFEEDBACKCALLBACKINTERFACE_H__A1444E91_1546_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/PropertiesDummyParentDialog.cpp
@@ -1,0 +1,146 @@
+// PropertiesDummyParentDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "PropertiesDummyParentDialog.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CPropertiesDummyParentDialog dialog
+
+
+CPropertiesDummyParentDialog::CPropertiesDummyParentDialog(
+	bool bDestroyParentWindowOnDestruction, CWnd* pParent /*=NULL*/):
+	m_bDestroyParentWindowOnDestruction(bDestroyParentWindowOnDestruction),
+	m_poCurrentPropertiesDialog(0),
+	m_bInitialized(false),
+	m_bSetContentHasBeenCalled(false)
+{
+	//{{AFX_DATA_INIT(CPropertiesDummyParentDialog)
+		// NOTE: the ClassWizard will add member initialization here
+	//}}AFX_DATA_INIT
+
+	Create(CPropertiesDummyParentDialog::IDD, pParent);
+}
+
+CPropertiesDummyParentDialog::~CPropertiesDummyParentDialog()
+{
+	DestroyCurrentPropertiesPage();
+
+	/*if (m_bDestroyParentWindowOnDestruction)
+	{
+		if (GetParent()!=0)
+		{
+			GetParent()->DestroyWindow();
+		}
+	}*/
+}
+
+void CPropertiesDummyParentDialog::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CPropertiesDummyParentDialog)
+	DDX_Control(pDX, IDC_LABELDEBUGTAG, m_ctrlLabelDebugTag);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CPropertiesDummyParentDialog, CDialog)
+	//{{AFX_MSG_MAP(CPropertiesDummyParentDialog)
+	ON_WM_SIZE()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPropertiesDummyParentDialog message handlers
+
+void CPropertiesDummyParentDialog::SetContent(
+	const CSupportedPropertyPagesData &oPagesToShow,
+	const TItemList<CJob*> &oJobsToConfigure,
+	CJobListUpdatable *poListContainer)
+{
+	if (m_bInitialized)
+	{
+		m_bSetContentHasBeenCalled=false;
+
+		DestroyCurrentPropertiesPage();
+
+		m_poCurrentPropertiesDialog=new CPropertiesTabParentDialog(oPagesToShow, oJobsToConfigure, poListContainer, this);
+		ApplyNewSize(m_oCurrentSize);
+		m_poCurrentPropertiesDialog->ShowWindow(SW_SHOW);
+	}
+	else
+	{
+		m_bSetContentHasBeenCalled=true;
+
+		m_oPagesToShowBuffer=oPagesToShow;
+		m_oJobsToConfigureBuffer=oJobsToConfigure;
+		m_poListContainer=poListContainer;
+	}
+}
+
+void CPropertiesDummyParentDialog::DefineDestroyParentWindowOnDestrution(bool bDestroyParentWindowOnDestruction)
+{
+	m_bDestroyParentWindowOnDestruction=bDestroyParentWindowOnDestruction;
+}
+
+void CPropertiesDummyParentDialog::OnSize(UINT nType, int cx, int cy) 
+{
+	CDialog::OnSize(nType, cx, cy);
+
+	m_oCurrentSize=CRect(0, 0, cx, cy);
+	
+	// TODO: Add your message handler code here
+	ApplyNewSize(m_oCurrentSize);
+}
+
+BOOL CPropertiesDummyParentDialog::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	// TODO: Add extra initialization here
+	m_bInitialized=true;
+
+	if (m_bSetContentHasBeenCalled)
+	{
+		SetContent(m_oPagesToShowBuffer, m_oJobsToConfigureBuffer, m_poListContainer);
+	}
+	ApplyNewSize(m_oCurrentSize);
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CPropertiesDummyParentDialog::ApplyNewSize(const CRect &oSize)
+{
+	if (m_bInitialized)
+	{
+		// dialog has been initialized
+
+		if (m_poCurrentPropertiesDialog!=0)
+		{
+			m_poCurrentPropertiesDialog->MoveWindow(oSize);
+		}
+
+		CRect oLabelRect;
+		m_ctrlLabelDebugTag.GetWindowRect(&oLabelRect);
+		CRect oDebugLabelRect(oSize.BottomRight(), oLabelRect.Size());
+		oDebugLabelRect.OffsetRect(-oLabelRect.Size().cx, -oLabelRect.Size().cy);
+		m_ctrlLabelDebugTag.MoveWindow(oDebugLabelRect);
+	}
+}
+
+void CPropertiesDummyParentDialog::DestroyCurrentPropertiesPage()
+{
+	if (m_poCurrentPropertiesDialog!=0)
+	{
+		delete m_poCurrentPropertiesDialog;
+		m_poCurrentPropertiesDialog=0;
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/PropertiesDummyParentDialog.h
@@ -1,0 +1,76 @@
+#if !defined(AFX_PROPERTIESDUMMYPARENTDIALOG_H__442115CA_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PROPERTIESDUMMYPARENTDIALOG_H__442115CA_0FD4_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// PropertiesDummyParentDialog.h : header file
+//
+
+#include "SupportedPropertyPagesData.h"
+#include "PropertiesTabParentDialog.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CPropertiesDummyParentDialog dialog
+
+class CPropertiesDummyParentDialog : public CDialog
+{
+// Construction
+public:
+	CPropertiesDummyParentDialog(bool bDestroyParentWindowOnDestruction, CWnd* pParent = NULL);   // standard constructor
+	virtual ~CPropertiesDummyParentDialog();
+
+// Dialog Data
+	//{{AFX_DATA(CPropertiesDummyParentDialog)
+	enum { IDD = IDD_PROPERTIESDUMMYPARENTDIALOG };
+	CStatic	m_ctrlLabelDebugTag;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CPropertiesDummyParentDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+public:
+
+	void SetContent(const CSupportedPropertyPagesData &oPagesToShow, const TItemList<CJob*> &oJobsToConfigure, CJobListUpdatable *poListContainer);
+
+	void DefineDestroyParentWindowOnDestrution(bool bDestroyParentWindowOnDestruction);
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CPropertiesDummyParentDialog)
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	virtual BOOL OnInitDialog();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+	bool m_bInitialized;
+
+	CPropertiesTabParentDialog *m_poCurrentPropertiesDialog;
+
+	// these two members are used if SetContent is called before this
+	// dialog has been initialized
+	bool m_bSetContentHasBeenCalled;
+	CSupportedPropertyPagesData m_oPagesToShowBuffer;
+	TItemList<CJob*> m_oJobsToConfigureBuffer;
+	CJobListUpdatable *m_poListContainer;
+
+	bool m_bDestroyParentWindowOnDestruction;
+
+	CRect m_oCurrentSize;
+
+	void ApplyNewSize(const CRect &oSize);
+
+	void DestroyCurrentPropertiesPage();
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PROPERTIESDUMMYPARENTDIALOG_H__442115CA_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/PropertiesTabParentDialog.cpp
@@ -1,0 +1,238 @@
+// PropertiesTabParentDialog.cpp : implementation file
+// Author: Torsten Landmann
+//
+///////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "PropertiesTabParentDialog.h"
+#include "EncoderGeneralPageDialog.h"
+#include "EncoderQualityPageDialog.h"
+#include "EncoderId3PageDialog.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+int CPropertiesTabParentDialog::s_iLastTabPage=0;
+
+/////////////////////////////////////////////////////////////////////////////
+// CPropertiesTabParentDialog dialog
+
+
+CPropertiesTabParentDialog::CPropertiesTabParentDialog(
+	const CSupportedPropertyPagesData &oPagesToShow,
+	const TItemList<CJob*> &oJobsToConfigure,
+	CJobListUpdatable *poListContainer,
+	CWnd* pParent /*=NULL*/):
+	m_oPagesToShow(oPagesToShow),
+	m_oJobsToConfigure(oJobsToConfigure),
+	m_bTabsAdded(false),
+	m_bInitialized(false),
+	m_poCurrentPage(0),
+	m_poListContainer(poListContainer)
+{
+	//{{AFX_DATA_INIT(CPropertiesTabParentDialog)
+		// NOTE: the ClassWizard will add member initialization here
+	//}}AFX_DATA_INIT
+
+	Create(CPropertiesTabParentDialog::IDD, pParent);
+}
+
+CPropertiesTabParentDialog::~CPropertiesTabParentDialog()
+{
+	if (m_poCurrentPage!=0)
+	{
+		delete m_poCurrentPage;
+		m_poCurrentPage=0;
+	}
+}
+
+void CPropertiesTabParentDialog::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CPropertiesTabParentDialog)
+	DDX_Control(pDX, IDC_LABELDEBUGTAG, m_ctrlLabelDebugTag);
+	DDX_Control(pDX, IDC_LABELNOSELECTION, m_ctrlLabelNoSelection);
+	DDX_Control(pDX, IDC_TAB1, m_ctrlTab);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CPropertiesTabParentDialog, CDialog)
+	//{{AFX_MSG_MAP(CPropertiesTabParentDialog)
+	ON_WM_SIZE()
+	ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnSelchangeTab1)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPropertiesTabParentDialog message handlers
+
+
+BOOL CPropertiesTabParentDialog::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	// TODO: Add extra initialization here
+	m_bInitialized=true;
+
+	ApplyNewSize(m_oCurrentSize, m_oCurrentPageSize);
+
+	if (m_oPagesToShow.GetNumberOfPages()>0)
+	{
+		m_ctrlTab.ShowWindow(SW_SHOW);
+		m_ctrlLabelNoSelection.ShowWindow(SW_HIDE);
+
+		AddTabs();
+
+		// restore last selected tab page
+		if (s_iLastTabPage>=m_oPagesToShow.GetNumberOfPages())
+		{
+			s_iLastTabPage=0;
+		}
+		m_ctrlTab.SetCurSel(s_iLastTabPage);
+		ShowPage(s_iLastTabPage);
+	}
+	else
+	{
+		m_ctrlTab.ShowWindow(SW_HIDE);
+		m_ctrlLabelNoSelection.ShowWindow(SW_SHOW);
+	}
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CPropertiesTabParentDialog::OnSize(UINT nType, int cx, int cy) 
+{
+	CDialog::OnSize(nType, cx, cy);
+
+	m_oCurrentSize=CRect(0, 0, cx, cy);
+	m_oCurrentPageSize=m_oCurrentSize;
+	m_oCurrentPageSize.left+=6;
+	m_oCurrentPageSize.top+=25;
+	m_oCurrentPageSize.right-=6;
+	m_oCurrentPageSize.bottom-=6;
+	
+	ApplyNewSize(m_oCurrentSize, m_oCurrentPageSize);
+}
+
+void CPropertiesTabParentDialog::AddTabs()
+{
+	if (m_bTabsAdded) return;
+
+	// first insert the tabs
+
+	int iCurTabPage=0;
+	m_oPagesToShow.Sort();
+	CBListReader oReader(m_oPagesToShow);
+	EPropertyPageType eCurrentPageType;
+	while (m_oPagesToShow.GetNextElemContent(oReader, eCurrentPageType))
+	{
+		if (AddTab(eCurrentPageType, iCurTabPage))
+		{
+			iCurTabPage++;
+		}
+	}
+	m_bTabsAdded=true;
+}
+
+bool CPropertiesTabParentDialog::AddTab(EPropertyPageType ePageType, int iTabId)
+{
+	// create the tab page
+	m_ctrlTab.InsertItem(iTabId, CSupportedPropertyPagesData::GetPageDescriptionShort(ePageType));
+
+	return true;
+}
+
+
+bool CPropertiesTabParentDialog::ShowPage(int iId)
+{
+	if (m_poCurrentPage!=0)
+	{
+		delete m_poCurrentPage;
+		m_poCurrentPage=0;
+	}
+
+	EPropertyPageType ePageType;
+	if (!m_oPagesToShow.GetPosContent(iId, ePageType))
+	{
+		// to many tabs
+		ASSERT(false);
+		return false;
+	}
+
+	switch (ePageType)
+	{
+	case ePageTypeEncoderGeneral:
+		{
+			m_poCurrentPage=new CEncoderGeneralPageDialog(m_oJobsToConfigure, m_poListContainer, this);
+			break;
+		}
+	case ePageTypeEncoderQuality:
+		{
+			m_poCurrentPage=new CEncoderQualityPageDialog(m_oJobsToConfigure, m_poListContainer, this);
+			break;
+		}
+	case ePageTypeEncoderID3:
+		{
+			m_poCurrentPage=new CEncoderId3PageDialog(m_oJobsToConfigure, m_poListContainer, this);
+			break;
+		}
+	default:
+		{
+			// unknown type of property page
+			ASSERT(false);
+			return false;
+		}
+	}
+	m_poCurrentPage->MoveWindow(m_oCurrentPageSize);
+	m_poCurrentPage->ShowWindow(SW_SHOW);
+
+	s_iLastTabPage=iId;
+
+	return true;
+}
+
+void CPropertiesTabParentDialog::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	// TODO: Add your control notification handler code here
+
+	ShowPage(m_ctrlTab.GetCurSel());
+	
+	*pResult = 0;
+}
+
+void CPropertiesTabParentDialog::ApplyNewSize(const CRect &oSize, const CRect &oPageSize)
+{
+	// TODO: Add your message handler code here
+	if (m_bInitialized)
+	{
+		// resize the tab control
+		m_ctrlTab.MoveWindow(oSize);
+
+		// resize the page
+		if (m_poCurrentPage!=0)
+		{
+			m_poCurrentPage->MoveWindow(oPageSize);
+		}
+
+		// move debug tag label
+		CRect oLabelRect;
+		m_ctrlLabelDebugTag.GetWindowRect(&oLabelRect);
+		CRect oDebugLabelRect(oSize.BottomRight(), oLabelRect.Size());
+		oDebugLabelRect.OffsetRect(-oLabelRect.Size().cx, -oLabelRect.Size().cy);
+		m_ctrlLabelDebugTag.MoveWindow(oDebugLabelRect);
+
+		// move no selection label
+		m_ctrlLabelNoSelection.GetWindowRect(oLabelRect);
+		CPoint oCurLabelCenter(oLabelRect.CenterPoint());
+		CPoint oDesiredLabelCenter(oSize.CenterPoint());
+		CPoint oOffset(oDesiredLabelCenter-oCurLabelCenter);
+		oLabelRect.OffsetRect(oOffset);
+		m_ctrlLabelNoSelection.MoveWindow(oLabelRect);
+	}
+}
--- /dev/null
+++ b/wingui/PropertiesTabParentDialog.h
@@ -1,0 +1,79 @@
+#if !defined(AFX_PROPERTIESTABPARENTDIALOG_H__442115C1_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_PROPERTIESTABPARENTDIALOG_H__442115C1_0FD4_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// PropertiesTabParentDialog.h : header file
+//
+
+#include "SupportedPropertyPagesData.h"
+#include "TItemList.h"
+#include "Job.h"
+#include "JobListUpdatable.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CPropertiesTabParentDialog dialog
+
+class CPropertiesTabParentDialog : public CDialog
+{
+// Construction
+public:
+	CPropertiesTabParentDialog(const CSupportedPropertyPagesData &oPagesToShow, const TItemList<CJob*> &oJobsToConfigure, CJobListUpdatable *poListContainer, CWnd* pParent = NULL);   // standard constructor
+	virtual ~CPropertiesTabParentDialog();
+
+// Dialog Data
+	//{{AFX_DATA(CPropertiesTabParentDialog)
+	enum { IDD = IDD_PROPERTIESTABPARENTDIALOG };
+	CStatic	m_ctrlLabelDebugTag;
+	CStatic	m_ctrlLabelNoSelection;
+	CTabCtrl	m_ctrlTab;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CPropertiesTabParentDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CPropertiesTabParentDialog)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult);
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+private:
+	CSupportedPropertyPagesData m_oPagesToShow;
+	TItemList<CJob*> m_oJobsToConfigure;
+	CJobListUpdatable *m_poListContainer;
+
+	// if this dialog has already been initialized
+	bool m_bInitialized;
+
+	bool m_bTabsAdded;
+	void AddTabs();
+	bool AddTab(EPropertyPageType ePageType, int iTabId);	// also creates the tab page; returns false in case of errors
+	bool ShowPage(int iId);
+
+	CDialog *m_poCurrentPage;
+
+	CRect m_oCurrentSize;
+	CRect m_oCurrentPageSize;
+
+	// this is just saved for the user's convenience
+	static int s_iLastTabPage;
+
+	void ApplyNewSize(const CRect &oSize, const CRect &oPageSize);
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PROPERTIESTABPARENTDIALOG_H__442115C1_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/ReadMe.txt
@@ -1,0 +1,88 @@
+========================================================================
+       MICROSOFT FOUNDATION CLASS LIBRARY : faac_wingui
+========================================================================
+
+
+AppWizard has created this faac_wingui application for you.  This application
+not only demonstrates the basics of using the Microsoft Foundation classes
+but is also a starting point for writing your application.
+
+This file contains a summary of what you will find in each of the files that
+make up your faac_wingui application.
+
+faac_wingui.dsp
+    This file (the project file) contains information at the project level and
+    is used to build a single project or subproject. Other users can share the
+    project (.dsp) file, but they should export the makefiles locally.
+
+faac_wingui.h
+    This is the main header file for the application.  It includes other
+    project specific headers (including Resource.h) and declares the
+    CFaac_winguiApp application class.
+
+faac_wingui.cpp
+    This is the main application source file that contains the application
+    class CFaac_winguiApp.
+
+faac_wingui.rc
+    This is a listing of all of the Microsoft Windows resources that the
+    program uses.  It includes the icons, bitmaps, and cursors that are stored
+    in the RES subdirectory.  This file can be directly edited in Microsoft
+	Visual C++.
+
+faac_wingui.clw
+    This file contains information used by ClassWizard to edit existing
+    classes or add new classes.  ClassWizard also uses this file to store
+    information needed to create and edit message maps and dialog data
+    maps and to create prototype member functions.
+
+res\faac_wingui.ico
+    This is an icon file, which is used as the application's icon.  This
+    icon is included by the main resource file faac_wingui.rc.
+
+res\faac_wingui.rc2
+    This file contains resources that are not edited by Microsoft 
+	Visual C++.  You should place all resources not editable by
+	the resource editor in this file.
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+AppWizard creates one dialog class:
+
+faac_winguiDlg.h, faac_winguiDlg.cpp - the dialog
+    These files contain your CFaac_winguiDlg class.  This class defines
+    the behavior of your application's main dialog.  The dialog's
+    template is in faac_wingui.rc, which can be edited in Microsoft
+	Visual C++.
+
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named faac_wingui.pch and a precompiled types file named StdAfx.obj.
+
+Resource.h
+    This is the standard header file, which defines new resource IDs.
+    Microsoft Visual C++ reads and updates this file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" to indicate parts of the source code you
+should add to or customize.
+
+If your application uses MFC in a shared DLL, and your application is 
+in a language other than the operating system's current language, you
+will need to copy the corresponding localized resources MFC42XXX.DLL
+from the Microsoft Visual C++ CD-ROM onto the system or system32 directory,
+and rename it to be MFCLOC.DLL.  ("XXX" stands for the language abbreviation.
+For example, MFC42DEU.DLL contains resources translated to German.)  If you
+don't do this, some of the UI elements of your application will remain in the
+language of the operating system.
+
+/////////////////////////////////////////////////////////////////////////////
--- /dev/null
+++ b/wingui/RecursiveDirectoryTraverser.cpp
@@ -1,0 +1,186 @@
+// RecursiveDirectoryTraverser.cpp: implementation of the CRecursiveDirectoryTraverser class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "RecursiveDirectoryTraverser.h"
+#include "FilePathCalc.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CRecursiveDirectoryTraverser::CRecursiveDirectoryTraverser()
+{
+
+}
+
+CRecursiveDirectoryTraverser::~CRecursiveDirectoryTraverser()
+{
+
+}
+
+TItemList<CString> CRecursiveDirectoryTraverser::FindFiles(const CString &oRootDirectory, const CString &oFileNameFilter, bool bRecursive)
+{
+	TItemList<CString> oToReturn;
+	CString oRootDir(oRootDirectory);
+	if (!CFilePathCalc::MakePath(oRootDir) || !CFilePathCalc::IsValidFileMask(oFileNameFilter))
+	{
+		CString oError;
+		oError.Format(IDS_SearchParametersInvalid, oRootDir, oFileNameFilter);
+		AfxMessageBox(oError, MB_OK | MB_ICONSTOP);
+		return oToReturn;
+	}
+
+	CFileFind oFileFind;
+	CString oSearchMask=
+		// "c:\\eigene dateien\\standard.apf";
+		oRootDir+oFileNameFilter;
+
+	
+	if (oFileFind.FindFile(oSearchMask))
+	{	
+		CString oFileName;
+		while (oFileFind.FindNextFile())
+		{
+			oFileName=oFileFind.GetFilePath();
+			oToReturn.AddNewElem(oFileName);
+		}
+	}
+
+	oFileFind.Close();
+
+	// if requested traverse child directories
+	if (bRecursive)
+	{
+		oSearchMask=oRootDir+"*";
+		if (oFileFind.FindFile(oSearchMask))
+		{
+		
+			CString oFileName;
+			while (oFileFind.FindNextFile())
+			{
+				if (oFileFind.IsDirectory())
+				{
+					if (oFileFind.GetFileName()!="." &&
+						oFileFind.GetFileName()!="..")
+					{
+						oToReturn+=FindFiles(oFileFind.GetFilePath(), oFileNameFilter, bRecursive);
+					}
+				}
+			}
+		}
+	}
+
+	return oToReturn;
+}
+
+bool CRecursiveDirectoryTraverser::MakeSureDirectoryExists(const CString &oDirectoryPath)
+{
+	CString oLocalPath(oDirectoryPath);
+	CFilePathCalc::MakePath(oLocalPath);
+	
+	// first split the desired path in existing and "creatable" path
+	CString oExistingPath;
+	CString oCreatablePath;
+	{
+		oLocalPath.Delete(oLocalPath.GetLength()-1);
+		while (CountMatchingFiles(oLocalPath)<1)
+		{
+			int iLastBackslashPos=oLocalPath.ReverseFind('\\');
+			if (iLastBackslashPos>=0)
+			{
+				int iLength=oLocalPath.GetLength();
+				oLocalPath.Delete(iLastBackslashPos, iLength-iLastBackslashPos);
+			}
+			else
+			{
+				// no more backslashes
+				oCreatablePath=oDirectoryPath;
+				break;
+			}
+		}
+		if (oCreatablePath.IsEmpty())
+		{
+			// must determine the path to create
+			oExistingPath=oLocalPath;
+			CFilePathCalc::MakePath(oExistingPath, true);
+			oCreatablePath=oDirectoryPath;
+			CFilePathCalc::MakePath(oCreatablePath, true);
+
+			// now we must remove directories from oCreatablePath as long
+			// the string matches with oExistingPath
+			long lExistingPos=0;
+			while (!oCreatablePath.IsEmpty() &&
+				!(lExistingPos==oExistingPath.GetLength()) &&
+				oExistingPath.GetAt(lExistingPos)==oCreatablePath[0])
+			{
+				lExistingPos++;
+				oCreatablePath.Delete(0);
+			}
+
+			// now the two paths are complete and we can begin creating the
+			// directories
+			while (!oCreatablePath.IsEmpty())
+			{
+				if (!CreateOneDirectory(oExistingPath, oCreatablePath))
+				{
+					// XXX might be useful to clean up already created directories
+					// here
+					return false;
+				}
+			}
+		}
+	}
+	return true;
+}
+
+int CRecursiveDirectoryTraverser::CountMatchingFiles(const CString &oFilterString)
+{
+	int iToReturn=0;
+
+	CFileFind oFileFind;
+	CString oSearchMask=oFilterString;
+	
+	if (oFileFind.FindFile(oSearchMask))
+	{		
+		iToReturn++;
+		while (oFileFind.FindNextFile())
+		{
+			iToReturn++;
+		}
+	}
+
+	oFileFind.Close();
+
+	return iToReturn;
+}
+
+bool CRecursiveDirectoryTraverser::CreateOneDirectory(CString &oExistingPath, CString &oCreatablePath)
+{
+	// extract the first substring from the creatable path
+	int iBackslashpos=oCreatablePath.Find('\\');
+	if (iBackslashpos<=0) return false;
+
+	CString oNextDirectoryToCreate(oCreatablePath.Left(iBackslashpos));
+
+	// first try to create the directory
+	if (!::CreateDirectory(
+		oExistingPath+oNextDirectoryToCreate, 0))
+	{
+		return false;
+	}
+
+	// directory was successfully created
+	oCreatablePath.Delete(0, iBackslashpos+1);
+	oExistingPath+=oNextDirectoryToCreate+"\\";
+
+	return true;
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/RecursiveDirectoryTraverser.h
@@ -1,0 +1,54 @@
+// RecursiveDirectoryTraverser.h: interface for the CRecursiveDirectoryTraverser class.
+// Author: Torsten Landmann
+//
+// This class is made for finding files within a directory tree.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_RECURSIVEDIRECTORYTRAVERSER_H__99D7AE61_17EB_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_RECURSIVEDIRECTORYTRAVERSER_H__99D7AE61_17EB_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "TItemList.h"
+
+class CRecursiveDirectoryTraverser  
+{
+public:
+	CRecursiveDirectoryTraverser();
+	virtual ~CRecursiveDirectoryTraverser();
+
+	// this method finds all files that are in the specified directory
+	// and match the filter; it can walk recursively through the entire
+	// subtree returning all files in the subtree that match the filter;
+	// in this case directory names are NOT matched against the filter;
+	// return value: a list of complete paths of the files found;
+	// this method displays error messages and returns an empty list in case
+	// of errors
+	static TItemList<CString> FindFiles(const CString &oRootDirectory, const CString &oFileNameFilter, bool bRecursive);
+
+	// returns if the directory was found or could be created. if false is
+	// returned this mostly means that there is a concurring file to 
+	// the first directory that needs to be created
+	static bool MakeSureDirectoryExists(const CString &oDirectoryPath);
+
+private:
+	// returns -1 in case of errors
+	static int CountMatchingFiles(const CString &oFilterString);
+
+	// example:
+	//	before:
+	//		oExistingPath=="c:\somewhere\hello\"
+	//		oCreatablePath="somewhereelse\super\"
+	//	after:
+	//		oExistingPath=="c:\somewhere\hello\somewhereelse"
+	//		oCreatablePath="super\"
+	//////
+	// the method physically creates the directory on the disk;
+	// returns false in case of errors
+	static bool CreateOneDirectory(CString &oExistingPath, CString &oCreatablePath);
+};
+
+#endif // !defined(AFX_RECURSIVEDIRECTORYTRAVERSER_H__99D7AE61_17EB_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/SourceTargetFilePair.cpp
@@ -1,0 +1,141 @@
+// SourceTargetFilePair.cpp: implementation of the CSourceTargetFilePair class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "SourceTargetFilePair.h"
+#include "FilePathCalc.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CSourceTargetFilePair::CSourceTargetFilePair()
+{
+
+}
+
+CSourceTargetFilePair::CSourceTargetFilePair(const CString &oSourceFileDirectory, const CString &oSourceFileName, const CString &oTargetFileDirectory, const CString &oTargetFileName):
+	m_oSourceFileDirectory(oSourceFileName),
+	m_oSourceFileName(oSourceFileName),
+	m_oTargetFileDirectory(oTargetFileDirectory),
+	m_oTargetFileName(oTargetFileName)
+{
+}
+
+CSourceTargetFilePair::CSourceTargetFilePair(const CString &oSourceFilePath, const CString &oTargetFilePath)
+{
+	bool bSuccess=true;
+
+	m_oSourceFileDirectory=oSourceFilePath;
+	bSuccess&=SetCompleteSourceFilePath(oSourceFilePath);
+	bSuccess&=SetCompleteTargetFilePath(oTargetFilePath);
+
+	ASSERT(bSuccess);
+}
+
+CSourceTargetFilePair::CSourceTargetFilePair(const CSourceTargetFilePair &oSource)
+{
+	*this=oSource;
+}
+
+CSourceTargetFilePair::~CSourceTargetFilePair()
+{
+
+}
+
+CString CSourceTargetFilePair::GetCompleteSourceFilePath() const
+{
+	CString oPath(GetSourceFileDirectory());
+	CFilePathCalc::MakePath(oPath);
+	return oPath+GetSourceFileName();
+}
+
+CString CSourceTargetFilePair::GetCompleteTargetFilePath() const
+{
+	CString oPath(GetTargetFileDirectory());
+	CFilePathCalc::MakePath(oPath);
+	return oPath+GetTargetFileName();
+}
+
+bool CSourceTargetFilePair::SetCompleteSourceFilePath(const CString &oPath)
+{
+	bool bSuccess=true;
+
+	m_oSourceFileDirectory=oPath;
+	bSuccess&=CFilePathCalc::MakePath(m_oSourceFileDirectory);
+	bSuccess&=CFilePathCalc::ExtractFileName(oPath, m_oSourceFileName);
+
+	return bSuccess;
+}
+
+bool CSourceTargetFilePair::SetCompleteTargetFilePath(const CString &oPath)
+{
+	bool bSuccess=true;
+
+	m_oTargetFileDirectory=oPath;
+	bSuccess&=CFilePathCalc::MakePath(m_oTargetFileDirectory);
+	bSuccess&=CFilePathCalc::ExtractFileName(oPath, m_oTargetFileName);
+
+	return bSuccess;
+}
+
+CSourceTargetFilePair& CSourceTargetFilePair::operator=(const CSourceTargetFilePair &oRight)
+{
+	m_oSourceFileDirectory=oRight.m_oSourceFileDirectory;
+	m_oSourceFileName=oRight.m_oSourceFileName;
+
+	m_oTargetFileDirectory=oRight.m_oTargetFileDirectory;
+	m_oTargetFileName=oRight.m_oTargetFileName;
+
+	return *this;
+}
+
+bool CSourceTargetFilePair::PutToArchive(CArchive &oArchive) const
+{
+	// put a class version flag
+	int iVersion=1;
+	oArchive << iVersion;
+
+	oArchive << m_oSourceFileDirectory;
+	oArchive << m_oSourceFileName;
+
+	oArchive << m_oTargetFileDirectory;
+	oArchive << m_oTargetFileName;
+
+	return true;
+}
+
+bool CSourceTargetFilePair::GetFromArchive(CArchive &oArchive)
+{
+	// fetch the class version flag
+	int iVersion;
+	oArchive >> iVersion;
+
+	switch (iVersion)
+	{
+	case 1:
+		{
+			oArchive >> m_oSourceFileDirectory;
+			oArchive >> m_oSourceFileName;
+
+			oArchive >> m_oTargetFileDirectory;
+			oArchive >> m_oTargetFileName;
+
+			return true;
+		}
+	default:
+		{
+			// unknown file format version
+			return false;
+		}
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/SourceTargetFilePair.h
@@ -1,0 +1,64 @@
+// SourceTargetFilePair.h: interface for the CSourceTargetFilePair class.
+// Author: Torsten Landmann
+//
+// encapsulates the source and target information of an encoding or
+// decoding job
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_SOURCETARGETFILEPAIR_H__DFE38E71_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_SOURCETARGETFILEPAIR_H__DFE38E71_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "FilePathCalc.h"
+#include "FileSerializable.h"
+
+class CSourceTargetFilePair : public CFileSerializable
+{
+public:
+	CSourceTargetFilePair();
+	CSourceTargetFilePair(const CString &oSourceFileDirectory, const CString &oSourceFileName, const CString &oTargetFileDirectory, const CString &oTargetFileName);
+	CSourceTargetFilePair(const CString &oSourceFilePath, const CString &oTargetFilePath);
+	CSourceTargetFilePair(const CSourceTargetFilePair &oSource);		// copy constructor
+	virtual ~CSourceTargetFilePair();
+
+	// property getters
+	const CString& GetSourceFileDirectory() const						{ return m_oSourceFileDirectory; }
+	CString& GetSourceFileDirectory()									{ return m_oSourceFileDirectory; }
+	const CString& GetSourceFileName() const							{ return m_oSourceFileName; }
+	CString& GetSourceFileName()										{ return m_oSourceFileName; }
+	const CString& GetTargetFileDirectory() const						{ return m_oTargetFileDirectory; }
+	CString& GetTargetFileDirectory()									{ return m_oTargetFileDirectory; }
+	const CString& GetTargetFileName() const							{ return m_oTargetFileName; }
+	CString& GetTargetFileName()										{ return m_oTargetFileName; }
+
+	// property setters
+	void SetSourceFileDirectory(const CString& oSourceFileDirectory)	{ m_oSourceFileDirectory=oSourceFileDirectory; CFilePathCalc::MakePath(m_oSourceFileDirectory); }
+	void SetSourceFileName(const CString& oSourceFileName)				{ m_oSourceFileName=oSourceFileName; }
+	void SetTargetFileDirectory(const CString& oTargetFileDirectory)	{ m_oTargetFileDirectory=oTargetFileDirectory; CFilePathCalc::MakePath(m_oTargetFileDirectory); }
+	void SetTargetFileName(const CString& oTargetFileName)				{ m_oTargetFileName=oTargetFileName; }
+
+	// functionality
+	CString GetCompleteSourceFilePath() const;
+	CString GetCompleteTargetFilePath() const;
+	bool SetCompleteSourceFilePath(const CString &oPath);		// returns false if the argument could not be evaluated properly
+	bool SetCompleteTargetFilePath(const CString &oPath);		// returns false if the argument could not be evaluated properly
+
+	CSourceTargetFilePair& operator=(const CSourceTargetFilePair &oRight);
+
+	// implementations to CFileSerializable
+	virtual bool PutToArchive(CArchive &oArchive) const;
+	virtual bool GetFromArchive(CArchive &oArchive);
+
+private:
+	CString m_oSourceFileDirectory;
+	CString m_oSourceFileName;
+
+	CString m_oTargetFileDirectory;
+	CString m_oTargetFileName;
+};
+
+#endif // !defined(AFX_SOURCETARGETFILEPAIR_H__DFE38E71_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/StdAfx.cpp
@@ -1,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+//	faac_wingui.pch will be the pre-compiled header
+//	stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
+
--- /dev/null
+++ b/wingui/StdAfx.h
@@ -1,0 +1,27 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__DFE38E69_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_STDAFX_H__DFE38E69_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h>         // MFC core and standard components
+#include <afxext.h>         // MFC extensions
+#include <afxdisp.h>        // MFC Automation classes
+#include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>			// MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__DFE38E69_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/SupportedPropertyPagesData.cpp
@@ -1,0 +1,121 @@
+// SupportedPropertyPagesData.cpp: implementation of the CSupportedPropertyPagesData class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "SupportedPropertyPagesData.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CSupportedPropertyPagesData::CSupportedPropertyPagesData()
+{
+
+}
+
+CSupportedPropertyPagesData::CSupportedPropertyPagesData(
+	const CSupportedPropertyPagesData &oSource)
+{
+	*this=oSource;
+}
+
+CSupportedPropertyPagesData::~CSupportedPropertyPagesData()
+{
+
+}
+
+void CSupportedPropertyPagesData::ShowPage(EPropertyPageType ePageType)
+{
+	if (!IsPageVisible(ePageType))
+	{
+		AddNewElem(ePageType);
+	}
+}
+
+void CSupportedPropertyPagesData::HidePage(EPropertyPageType ePageType)
+{
+	DeleteAllElemsWithContent(ePageType);
+}
+
+bool CSupportedPropertyPagesData::IsPageVisible(EPropertyPageType ePageType) const
+{
+	return FindContent(ePageType);
+}
+
+CSupportedPropertyPagesData& CSupportedPropertyPagesData::operator=(const CSupportedPropertyPagesData &oRight)
+{
+	// call inherited version
+	TItemList<EPropertyPageType>::operator=(oRight);
+
+	// have no own members to copy
+	return *this;
+}
+
+CSupportedPropertyPagesData CSupportedPropertyPagesData::operator*(
+	const CSupportedPropertyPagesData &oRight)
+{
+	CSupportedPropertyPagesData oToReturn(*this);
+	oToReturn*=oRight;
+	return oToReturn;
+}
+
+CSupportedPropertyPagesData& CSupportedPropertyPagesData::operator*=(
+	const CSupportedPropertyPagesData &oRight)
+{
+	if (this!=&oRight)
+	{
+		// call inherited version
+		TItemList<EPropertyPageType>::operator*=(oRight);
+
+		// have no own members to intersect
+	}
+	return *this;
+}
+
+long CSupportedPropertyPagesData::GetNumberOfPages() const
+{
+	TItemList<EPropertyPageType> oTempList(*this);
+	oTempList.RemoveDoubleElements();
+
+	return oTempList.GetNumber();
+}
+
+CString CSupportedPropertyPagesData::GetPageDescriptionShort(EPropertyPageType ePageType)
+{
+	int iStringId=0;
+	switch (ePageType)
+	{
+	case ePageTypeEncoderGeneral:
+		{
+			iStringId=IDS_EncoderGeneralShort;
+			break;
+		}
+	case ePageTypeEncoderQuality:
+		{
+			iStringId=IDS_EncoderQualityShort;
+			break;
+		}
+	case ePageTypeEncoderID3:
+		{
+			iStringId=IDS_EncoderId3Short;
+			break;
+		}
+	default:
+		{
+			iStringId=IDS_TabUndefined;
+			break;
+		}
+	}
+
+	CString oToReturn;
+	oToReturn.LoadString(iStringId);
+	return oToReturn;
+}
--- /dev/null
+++ b/wingui/SupportedPropertyPagesData.h
@@ -1,0 +1,48 @@
+// SupportedPropertyPagesData.h: interface for the CSupportedPropertyPagesData class.
+// Author: Torsten Landmann
+//
+// This class is a wrapper around a simple TItemList<long>. It provides some
+// basic functionality to save which pages of a set of property pages shall
+// be visible.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_SUPPORTEDPROPERTYPAGESDATA_H__442115C2_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_SUPPORTEDPROPERTYPAGESDATA_H__442115C2_0FD4_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "TItemList.h"
+
+enum EPropertyPageType
+{
+	ePageTypeEncoderGeneral,
+	ePageTypeEncoderQuality,
+	ePageTypeEncoderID3,
+};
+
+class CSupportedPropertyPagesData : public TItemList<EPropertyPageType>
+{
+public:
+	CSupportedPropertyPagesData();
+	CSupportedPropertyPagesData(const CSupportedPropertyPagesData &oSource);
+	virtual ~CSupportedPropertyPagesData();
+
+	void ShowPage(EPropertyPageType ePageType);
+	void HidePage(EPropertyPageType ePageType);
+	bool IsPageVisible(EPropertyPageType ePageType) const;
+	long GetNumberOfPages() const;
+
+	// multiplication intersects two data objects;
+	// this is useful to determine the pages that are supported by
+	// a certain selection of different jobs
+	CSupportedPropertyPagesData& operator=(const CSupportedPropertyPagesData &oRight);
+	CSupportedPropertyPagesData operator*(const CSupportedPropertyPagesData &oRight);
+	CSupportedPropertyPagesData& operator*=(const CSupportedPropertyPagesData &oRight);
+
+	static CString GetPageDescriptionShort(EPropertyPageType ePageType);
+};
+
+#endif // !defined(AFX_SUPPORTEDPROPERTYPAGESDATA_H__442115C2_0FD4_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/TItemList.cpp
@@ -1,0 +1,11 @@
+// TItemList.cpp: Definition file for class template
+// TItemList; with this template you can create
+// lists that is able to hold elements of the
+// specified type; each element gets a unique
+// handle in the list that is returned on creation
+// 
+/////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "TItemList.h"
+
--- /dev/null
+++ b/wingui/TItemList.h
@@ -1,0 +1,850 @@
+// TItemList.h: Header file for class template
+// TItemList;
+// Copyright 2000 by Torsten Landmann
+//
+// with this template you can create
+// lists that are able to hold elements of the
+// specified type; each element gets a unique
+// handle in the list that is returned on creation
+// you can choose whatever type you want as content under
+// one condition: the operators ==, =, < and > must be defined;
+// however < and > do only need to return senseful results
+// if you wish to use the sorting feature of TItemList<..>-Lists;
+// == must always be reflexive and must never return
+// true if the two elements aren't really the same C++-object or value;
+// if all this comparison operator stuff is too complicated for
+// you and you think you don't really need to pay attention to
+// it for a specific class just derive this class from
+// CGenericSortable; note however that even then the = operator
+// still needs to be implemented by you!
+//
+// revised 2001 by Torsten Landmann
+// successfully compiled and tested under MSVC 6.0
+// 
+/////////////////////////////////////////////////////////
+
+#ifndef __TItemList_h__
+#define __TItemList_h__
+
+
+#include "ListObj.h"
+
+template <class ItemType> class TItemList;
+
+template <class ItemType> class TItemListElem:public CBBaseElem
+{
+	friend class TItemList<ItemType>;
+
+protected:
+	TItemListElem();
+	virtual ~TItemListElem();
+
+	void SetContent(const ItemType &etContent);
+	bool GetContent(ItemType &etContent) const;
+	bool GetContent(ItemType* &etContent);
+	ItemType* GetContent();
+	const ItemType* GetContent() const;
+
+	virtual signed long IsHigher(class CBBaseElem *pElem);	// overridden; used for sorting the list
+
+private:
+	bool m_bContentDefined;
+	ItemType m_etContent;
+};
+
+
+template <class LItemType> class TItemList:public CBList
+{
+public:
+	TItemList();
+	TItemList(const TItemList<LItemType> &oSource);
+	virtual ~TItemList();
+
+	// return value: unique handle of the new item; siListErr in
+	//				case of errors
+	// note: if lDesiredIndex is supplied and the index is
+	//	1.: >0 and
+	//	2.: not yet used as index
+	// then you can be sure that it is used for the new element
+	long AddNewElem(const LItemType &etContent, long lDesiredIndex=-1);
+
+	bool DeleteElemByContent(const LItemType &etContent);	// deletes maximally one element
+	void DeleteAllElemsWithContent(const LItemType &etContent);
+
+	void DeleteElems(TItemList<long> &oIndices);
+
+	bool GetElemContent(long lIndex, LItemType &etContent) const;
+	bool GetElemContent(long lIndex, LItemType* &etContent) const;
+	bool SetElemContent(long lIndex, const LItemType &etContent) const;
+	bool GetPosContent(long lPos, LItemType &etContent, long *lIndex=0) const;	// lIndex may be used to get the index of the element
+	bool GetPosContent(long lPos, LItemType* &etContent, long *lIndex=0) const;	// lIndex may be used to get the index of the element
+	bool SetPosContent(long lPos, const LItemType &etContent) const;
+	bool GetNextElemContent(HRead hRead, LItemType &etContent, long *lIndex=0);	// lIndex may be used to get the index of the element
+	bool GetNextElemContent(HRead hRead, LItemType* &etContent, long *lIndex=0);	// lIndex may be used to get the index of the element
+
+	bool FindContent(const LItemType &etContent) const;
+	bool FindContent(const LItemType &etContent, long &lId) const;
+	bool FindContent(const LItemType &etContent, long lStartSearchAfterId, long &lId) const;
+	long GetContentCount(const LItemType &etContent) const;
+	TItemList<long> GetContentIds(const LItemType &etContent) const;
+
+	bool GetFirstElemContent(LItemType &etContent, long &lId) const;
+	bool GetFirstElemContent(LItemType* &etContent, long &lId) const;
+
+	bool GetGreatestContent(LItemType &etContent, long *plId=0) const;
+	bool GetGreatestContent(LItemType* &etContent, long *plId=0) const;
+	bool GetSmallestContent(LItemType &etContent, long *plId=0) const;
+	bool GetSmallestContent(LItemType* &etContent, long *plId=0) const;
+
+	// you may also use operator= for this
+	bool CopyFrom(const TItemList<LItemType> &oSource);
+
+	// standard operators;
+	// subtraction preserves the indices of elements while
+	// addition does not necessarily!
+	// however if you are sure that no index would be in the list for several
+	// times after adding the other list also addition preserves the indices;
+	// subtraction is not number sensitive, so one element may
+	// remove several others from the target list;
+	TItemList<LItemType>& operator=(const TItemList<LItemType> &oRight);
+	TItemList<LItemType> operator+(const TItemList<LItemType> &oRight);
+	TItemList<LItemType> operator-(const TItemList<LItemType> &oRight);
+	TItemList<LItemType>& operator+=(const TItemList<LItemType> &oRight);
+	TItemList<LItemType>& operator-=(const TItemList<LItemType> &oRight);
+
+	// multiplication intersects the two lists
+	TItemList<LItemType> operator*(const TItemList<LItemType> &oRight);
+	TItemList<LItemType>& operator*=(const TItemList<LItemType> &oRight);
+	
+	
+
+	// removes all elements that are twice or more often in the list;
+	// relatively slow, use sparingly (time complexity O(n*n));
+	// you may provide a faster implementation if needed using
+	// an efficient sorting algorithm
+	void RemoveDoubleElements();
+
+protected:
+	// the following method must be overriden by every
+	// subclass returning an element of the type of the particular
+	// subclass of PBBaseElem
+	virtual PBBaseElem CreateElem();
+
+	// this method may be overriden by any sub class to perform
+	// certain operations on a content before it is removed
+	// from the list (and maybe also the last possibility to
+	// access the content)
+	// for instance, if Content is a pointer, you might want
+	// to call "delete Content;" before the pointer itself is
+	// removed from the list;
+	// !!! EXTREMELY IMPORTANT: !!!
+	// if you override this method you MUST call
+	// DeleteAll() in the destructor of your class
+	virtual void OnPreDeleteContent(LItemType Content);
+
+private:
+	// this method is inherited and called each time 
+	// an element is to be deleted;
+	// it extracts its content and passes it on to a call
+	// of OnPreDeleteContent()
+	virtual void OnPreDeleteItem(PBBaseElem poElem);
+};
+
+
+
+// ---------------- template definitions -------------------------
+
+template <class ItemType> TItemListElem<ItemType>::TItemListElem():
+	CBBaseElem()
+{
+	m_bContentDefined=false;
+}
+
+template <class ItemType> TItemListElem<ItemType>::~TItemListElem()
+{
+}
+
+template <class ItemType> void TItemListElem<ItemType>::SetContent(const ItemType &etContent)
+{
+	m_bContentDefined=true;
+	m_etContent=etContent;
+}
+
+template <class ItemType> bool TItemListElem<ItemType>::GetContent(ItemType &etContent) const
+{
+	if (!m_bContentDefined) return false;
+	etContent=m_etContent;
+	return true;
+}
+
+template <class ItemType> bool TItemListElem<ItemType>::GetContent(ItemType* &etContent)
+{
+	if (!m_bContentDefined) return false;
+	etContent=&m_etContent;
+	return true;
+}
+
+template <class ItemType> ItemType* TItemListElem<ItemType>::GetContent()
+{
+	return &m_etContent;
+}
+
+template <class ItemType> const ItemType* TItemListElem<ItemType>::GetContent() const
+{
+	return &m_etContent;
+}
+
+template <class ItemType> signed long TItemListElem<ItemType>::IsHigher(class CBBaseElem *pElem)
+{
+	ItemType ParamContent;
+
+	((TItemListElem<ItemType>*)pElem)->GetContent(ParamContent);
+	
+	if (ParamContent<m_etContent) return 1;
+	if (ParamContent>m_etContent) return -1;
+	return 0;
+}
+
+
+
+template <class LItemType> TItemList<LItemType>::TItemList():
+	CBList()
+{
+}
+
+template <class LItemType> TItemList<LItemType>::TItemList(const TItemList<LItemType> &oSource)
+{
+	CopyFrom(oSource);
+}
+
+template <class LItemType> TItemList<LItemType>::~TItemList()
+{
+}
+
+template <class LItemType> long TItemList<LItemType>::AddNewElem(
+	const LItemType &etContent, long lDesiredIndex)
+{
+	TItemListElem<LItemType>* poNewElem=
+		(TItemListElem<LItemType>*)Add(lDesiredIndex);
+
+	if (poNewElem==0)
+	{
+		return siListErr;
+	}
+
+	poNewElem->SetContent(etContent);
+	return poNewElem->GetIndex();
+}
+
+template <class LItemType> bool TItemList<LItemType>::DeleteElemByContent(const LItemType &etContent)
+{
+	long lItemId;
+	if (!FindContent(etContent, lItemId))
+	{
+		return false;
+	}
+	return DeleteElem(lItemId)!=siListErr;
+}
+
+template <class LItemType> void TItemList<LItemType>::DeleteAllElemsWithContent(const LItemType &etContent)
+{
+	while (DeleteElemByContent(etContent))
+	{
+		// nothing further
+	}
+}
+
+template <class LItemType> void TItemList<LItemType>::DeleteElems(TItemList<long> &oIndices)
+{
+	HRead hRead=oIndices.BeginRead();
+	long lCurIndex;
+	while (oIndices.GetNextElemContent(hRead, lCurIndex))
+	{
+		DeleteElem(lCurIndex);
+	}
+	oIndices.EndRead(hRead);
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetElemContent(
+	long lIndex,
+	LItemType &etContent) const
+{
+	TItemListElem<LItemType>* poElem=
+		(TItemListElem<LItemType>*)GetElem(lIndex);
+
+	if (poElem==0) return false;
+
+	return poElem->GetContent(etContent);
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetElemContent(
+	long lIndex,
+	LItemType* &etContent) const
+{
+	TItemListElem<LItemType>* poElem=
+		(TItemListElem<LItemType>*)GetElem(lIndex);
+
+	if (poElem==0) return false;
+
+	return poElem->GetContent(etContent);
+}
+
+template <class LItemType> bool TItemList<LItemType>::SetElemContent(long lIndex, const LItemType &etContent) const
+{
+	TItemListElem<LItemType>* poElem=
+		(TItemListElem<LItemType>*)GetElem(lIndex);
+
+	if (poElem==0) return false;
+
+	poElem->SetContent(etContent);
+
+	return true;
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetPosContent(long lPos, LItemType &etContent, long *lIndex) const
+{
+	TItemListElem<LItemType>* poElem=
+		(TItemListElem<LItemType>*)GetPos(lPos);
+
+	if (poElem==0) return false;
+
+	if (lIndex!=0) *lIndex=poElem->GetIndex();
+
+	return poElem->GetContent(etContent);
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetPosContent(long lPos, LItemType* &etContent, long *lIndex) const
+{
+	TItemListElem<LItemType>* poElem=
+		(TItemListElem<LItemType>*)GetPos(lPos);
+
+	if (poElem==0) return false;
+
+	if (lIndex!=0) *lIndex=poElem->GetIndex();
+
+	return poElem->GetContent(etContent);
+}
+
+template <class LItemType> bool TItemList<LItemType>::SetPosContent(long lPos, const LItemType &etContent) const
+{
+	TItemListElem<LItemType>* poElem=
+		(TItemListElem<LItemType>*)GetPos(lPos);
+
+	if (poElem==0) return false;
+
+	poElem->SetContent(etContent);
+
+	return true;
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetNextElemContent(HRead hRead, LItemType &etContent, long *lIndex)
+{
+	TItemListElem<LItemType>* poElem=
+		(TItemListElem<LItemType>*)ReadElem(hRead);
+
+	if (poElem==0) return false;
+
+	if (lIndex!=0)
+	{
+		*lIndex=poElem->GetIndex();
+	}
+
+	return poElem->GetContent(etContent);
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetNextElemContent(
+	HRead hRead, LItemType* &etContent, long *lIndex)
+{
+	TItemListElem<LItemType>* poElem=
+		(TItemListElem<LItemType>*)ReadElem(hRead);
+
+	if (poElem==0) return false;
+
+	if (lIndex!=0)
+	{
+		*lIndex=poElem->GetIndex();
+	}
+
+	return poElem->GetContent(etContent);
+}
+
+template <class LItemType> bool TItemList<LItemType>::FindContent(const LItemType &etContent) const
+{
+	long lDummy;
+	return FindContent(etContent, lDummy);
+}
+
+template <class LItemType> bool TItemList<LItemType>::FindContent(const LItemType &etContent, long &lId) const
+{
+	// we're using non-const members though we're going
+	// to reverse all changes; therefore let's disable
+	// the const checking
+	TItemList<LItemType> *poThis=(TItemList<LItemType>*)this;
+
+	// loop through all elements and compare them with the
+	// given one
+	LItemType etReadContent;
+	HRead hRead=poThis->BeginRead();
+	while (poThis->GetNextElemContent(hRead, etReadContent, &lId))
+	{
+		if (etReadContent==etContent)
+		{
+			poThis->EndRead(hRead);
+			return true;
+		}
+	}
+
+	poThis->EndRead(hRead);
+	return false;
+}
+
+template <class LItemType> bool TItemList<LItemType>::FindContent(const LItemType &etContent, long lStartSearchAfterId, long &lId) const
+{
+	// we're using non-const members though we're going
+	// to reverse all changes; therefore let's disable
+	// the const checking
+	TItemList<LItemType> *poThis=(TItemList<LItemType>*)this;
+
+	// loop through all elements and compare them with the
+	// given one; however wait until we've passed the item
+	// with id lStartSearchAfterId
+	LItemType etReadContent;
+	HRead hRead=poThis->BeginRead();
+	bool bSearchBegun=false;
+	while (poThis->GetNextElemContent(hRead, etReadContent, &lId))
+	{
+		if (etReadContent==etContent && bSearchBegun)
+		{
+			poThis->EndRead(hRead);
+			return true;
+		}
+
+		if (lId==lStartSearchAfterId)
+		{
+			bSearchBegun=true;
+		}
+	}
+
+	poThis->EndRead(hRead);
+	return false;
+}
+
+template <class LItemType> long TItemList<LItemType>::GetContentCount(const LItemType &etContent) const
+{
+	long lCount=0;
+
+	// we're using non-const members though we're going
+	// to reverse all changes; therefore let's disable
+	// the const checking
+	TItemList<LItemType> *poThis=(TItemList<LItemType>*)this;
+
+	// loop through all elements and compare them with the
+	// given one
+	LItemType etReadContent;
+	HRead hRead=poThis->BeginRead();
+	while (poThis->GetNextElemContent(hRead, etReadContent))
+	{
+		if (etReadContent==etContent)
+		{
+			lCount++;
+		}
+	}
+
+	poThis->EndRead(hRead);
+	return lCount;
+}
+
+template <class LItemType> TItemList<long> TItemList<LItemType>::GetContentIds(const LItemType &etContent) const
+{
+	TItemList<long> oReturn;
+
+	// we're using non-const members though we're going
+	// to reverse all changes; therefore let's disable
+	// the const checking
+	TItemList<LItemType> *poThis=(TItemList<LItemType>*)this;
+
+	// loop through all elements and compare them with the
+	// given one
+	LItemType etReadContent;
+	HRead hRead=poThis->BeginRead();
+	long lCurId;
+	while (poThis->GetNextElemContent(hRead, etReadContent, &lCurId))
+	{
+		if (etReadContent==etContent)
+		{
+			oReturn.AddNewElem(lCurId);
+		}
+	}
+
+	poThis->EndRead(hRead);
+	return oReturn;
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetFirstElemContent(
+	LItemType &etContent, long &lId) const
+{
+	// use another overloaded version
+	LItemType *petContent;
+	if (!GetFirstElemContent(petContent, lId))
+	{
+		return false;
+	}
+
+	etContent=*petContent;
+
+	// return success
+	return true;
+}
+
+
+template <class LItemType> bool TItemList<LItemType>::GetFirstElemContent(
+	LItemType* &etContent, long &lId) const
+{
+	// we're using non-const members though we're going
+	// to reverse all changes; therefore let's disable
+	// the const checking
+	TItemList<LItemType> *poThis=(TItemList<LItemType>*)this;
+
+	// try to fetch the first element
+	HRead hRead=poThis->BeginRead();
+	if (poThis->GetNextElemContent(hRead, etContent, &lId))
+	{
+		// we could read an element
+		poThis->EndRead(hRead);
+		return true;
+	}
+	else
+	{
+		// we could read no element
+		poThis->EndRead(hRead);
+		return false;
+	}
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetGreatestContent(
+	LItemType &etContent, long *plId) const
+{
+	// use another overloaded version
+	LItemType *poContent;
+	if (!GetGreatestContent(poContent, plId))
+	{
+		return false;
+	}
+
+	etContent=*poContent;
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetGreatestContent(
+	LItemType* &etContent, long *plId) const
+{
+	if (GetNumber()==0) return false;		// no element there
+
+	// we're using non-const members though we're going
+	// to reverse all changes; therefore let's disable
+	// the const checking
+	TItemList<LItemType> *poThis=(TItemList<LItemType>*)this;
+
+	// loop through all elements and always save the greatest
+	LItemType *petCurGreatestContent;
+	long lCurGreatestIndex;
+	if (!GetFirstElemContent(petCurGreatestContent, lCurGreatestIndex)) return false;
+
+	HRead hRead=poThis->BeginRead();
+	LItemType *petReadContent;
+	long lCurIndex;
+	while (poThis->GetNextElemContent(hRead, petReadContent, &lCurIndex))
+	{
+		if (*petReadContent>*petCurGreatestContent)
+		{
+			petCurGreatestContent=petReadContent;
+			lCurGreatestIndex=lCurIndex;
+		}
+	}
+	poThis->EndRead(hRead);
+
+	// set return results
+	etContent=petCurGreatestContent;
+	if (plId!=0) *plId=lCurGreatestIndex;
+
+
+	// return success
+	return true;
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetSmallestContent(
+	LItemType &etContent, long *plId) const
+{
+	// use another overloaded version
+	LItemType *poContent;
+	if (!GetSmallestContent(poContent, plId))
+	{
+		return false;
+	}
+
+	etContent=*poContent;
+
+	// return success
+	return true;
+}
+
+template <class LItemType> bool TItemList<LItemType>::GetSmallestContent(
+	LItemType* &etContent, long *plId) const
+{
+	if (GetNumber()==0) return false;		// no element there
+
+	// we're using non-const members though we're going
+	// to reverse all changes; therefore let's disable
+	// the const checking
+	TItemList<LItemType> *poThis=(TItemList<LItemType>*)this;
+
+	// loop through all elements and always save a pointer to the smallest
+	LItemType *petCurSmallestContent;
+	long lCurSmallestIndex;
+	if (!GetFirstElemContent(petCurSmallestContent, lCurSmallestIndex)) return false;
+
+	HRead hRead=poThis->BeginRead();
+	LItemType *petReadContent;
+	long lCurIndex;
+	while (poThis->GetNextElemContent(hRead, petReadContent, &lCurIndex))
+	{
+		if (*petReadContent<*petCurSmallestContent)
+		{
+			petCurSmallestContent=petReadContent;
+			lCurSmallestIndex=lCurIndex;
+		}
+	}
+	poThis->EndRead(hRead);
+
+	// set return results
+	etContent=petCurSmallestContent;
+	if (plId!=0) *plId=lCurSmallestIndex;
+
+
+	// return success
+	return true;
+}
+
+template <class LItemType> bool TItemList<LItemType>::CopyFrom(
+	const TItemList<LItemType> &oSource)
+{
+	ASSERT(&oSource!=this);
+
+	// we will not have changed the state of oSource on return;
+	// however we'll need non-const operations, so
+	// allow ourselves to use non-const operations
+	TItemList<LItemType> *poSource=(TItemList<LItemType>*)&oSource;
+
+	// now begin the actual copying
+	DeleteAll();
+
+	HRead hRead=poSource->BeginRead();
+
+	LItemType CurItem;
+	long lCurItemIndex;
+	while (poSource->GetNextElemContent(hRead, CurItem, &lCurItemIndex))
+	{
+		long lNewIndex=AddNewElem(CurItem, lCurItemIndex);
+		ASSERT(lNewIndex==lCurItemIndex);	// assert that the copy got the same index as the source
+	}
+
+	poSource->EndRead(hRead);
+
+	// return success
+	return true;
+}
+
+template <class LItemType> TItemList<LItemType>& TItemList<LItemType>::operator=(const TItemList<LItemType> &oRight)
+{
+	CopyFrom(oRight);
+	return *this;
+}
+
+template <class LItemType> TItemList<LItemType> TItemList<LItemType>::operator+(const TItemList<LItemType> &oRight)
+{
+	TItemList<LItemType> oReturn;
+
+	// put our elements to return
+	oReturn=*this;
+
+	// put the rvalue's elements to return
+	oReturn+=oRight;
+
+	return oReturn;
+}
+
+template <class LItemType> TItemList<LItemType> TItemList<LItemType>::operator-(const TItemList<LItemType> &oRight)
+{
+	TItemList<LItemType> oReturn;
+
+	// put our elements to return
+	oReturn=*this;
+
+	// remove the rvalue's elements from return
+	oReturn-=oRight;
+
+	return oReturn;
+}
+
+template <class LItemType> TItemList<LItemType>& TItemList<LItemType>::operator+=(const TItemList<LItemType> &oRight)
+{
+	// we will not have changed the state of oRight on return;
+	// however we'll need non-const operations, so
+	// allow ourselves to use non-const operations
+	TItemList<LItemType> *poRight=(TItemList<LItemType>*)&oRight;
+
+	// now begin the actual adding
+	HRead hRead=poRight->BeginRead();
+
+	LItemType CurItem;
+	long lCurItemIndex;
+	while (poRight->GetNextElemContent(hRead, CurItem, &lCurItemIndex))
+	{
+		AddNewElem(CurItem, lCurItemIndex);
+	}
+
+	poRight->EndRead(hRead);
+
+	return *this;
+}
+
+template <class LItemType> TItemList<LItemType>& TItemList<LItemType>::operator-=(const TItemList<LItemType> &oRight)
+{
+	// go through all elements in the right list and delete them
+	// from this one
+
+	// we will not have changed the state of oRight on return;
+	// however we'll need non-const operations, so
+	// allow ourselves to use non-const operations
+	TItemList<LItemType> *poRight=(TItemList<LItemType>*)&oRight;;
+
+	HRead hRead=poRight->BeginRead();
+	LItemType CurItem;
+	while (poRight->GetNextElemContent(hRead, CurItem))
+	{
+		// delete the content from this list
+		DeleteAllElemsWithContent(CurItem);
+	}
+	poRight->EndRead(hRead);
+
+	return *this;
+}
+
+template <class LItemType> TItemList<LItemType>& TItemList<LItemType>::operator*=(const TItemList<LItemType> &oRight)
+{
+	// we save the ids of all items that are to be removed in this list;
+	// this is necessary because the list is locked when read sessions are open
+	TItemList<long> oIndicesToDelete;
+
+	// remove all elements that are not in the oRight list
+	HRead hRead=BeginRead();
+	LItemType CurItem;
+	long lCurItemIndex;
+	while (GetNextElemContent(hRead, CurItem, &lCurItemIndex))
+	{
+		long lDummy;
+		if (!oRight.FindContent(CurItem, lDummy))
+		{
+			// the item is not in the oRight list, so save
+			// it for deletion
+			oIndicesToDelete.AddNewElem(lCurItemIndex);
+		}
+	}
+	EndRead(hRead);
+
+	// now delete all items that we saved for deletion
+	hRead=oIndicesToDelete.BeginRead();
+	while (oIndicesToDelete.GetNextElemContent(hRead, lCurItemIndex))
+	{
+		DeleteElem(lCurItemIndex);
+	}
+	oIndicesToDelete.EndRead(hRead);
+
+	return *this;
+}
+
+template <class LItemType> TItemList<LItemType> TItemList<LItemType>::operator*(const TItemList<LItemType> &oRight)
+{
+	TItemList<LItemType> oReturn;
+
+	// put our elements to return
+	oReturn=*this;
+
+	// intersect the rvalue's elements with return's
+	oReturn*=oRight;
+
+	return oReturn;
+}
+
+template <class LItemType> void TItemList<LItemType>::RemoveDoubleElements()
+{
+	// we'll copy a copy of all distinct elements in this list
+	TItemList<LItemType> oResultList;
+
+	// go through all elements in this list and copy them
+	// to the result list if appropriate
+	HRead hRead=BeginRead();
+	LItemType CurItem;
+	while (GetNextElemContent(hRead, CurItem))
+	{
+		long lDummy;
+		if (!oResultList.FindContent(CurItem, lDummy))
+		{
+			// the content is not yet in the list, so copy
+			// it
+			oResultList.AddNewElem(CurItem);
+		}
+	}
+	EndRead(hRead);
+
+	// now ResultList contains only distinct elements, so
+	// copy it to ourselves
+	*this=oResultList;
+}
+
+
+
+template <class LItemType> PBBaseElem TItemList<LItemType>::CreateElem()
+{
+	return new TItemListElem<LItemType>;
+}
+
+template <class LItemType> void TItemList<LItemType>::OnPreDeleteContent(LItemType Content)
+{
+	// do nothing here
+}
+
+template <class LItemType> void TItemList<LItemType>::OnPreDeleteItem(PBBaseElem poElem)
+{
+	// find out the content of the item
+	LItemType Content;
+	((TItemListElem<LItemType>*)poElem)->GetContent(Content);
+
+	// inform sub classes of deletion of content
+	OnPreDeleteContent(Content);
+}
+
+// see comment at the top of this file for a description
+class CGenericSortable
+{
+public:
+	CGenericSortable() {}
+	virtual ~CGenericSortable() {}
+
+	bool operator==(const CGenericSortable &oRight)
+	{
+		return this==&oRight;
+	}
+
+	bool operator<(const CGenericSortable &oRight)
+	{
+		return this<&oRight;
+	}
+
+	bool operator>(const CGenericSortable &oRight)
+	{
+		return &oRight<this;
+	}
+};
+
+
+#endif // #ifndef __TItemList_h__
\ No newline at end of file
--- /dev/null
+++ b/wingui/WindowUtil.cpp
@@ -1,0 +1,219 @@
+// WindowUtil.cpp: implementation of the CWindowUtil class.
+// Author: Torsten Landmann
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "WindowUtil.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CWindowUtil::CWindowUtil()
+{
+
+}
+
+CWindowUtil::~CWindowUtil()
+{
+
+}
+
+void CWindowUtil::DeleteAllListCtrlItems(CListCtrl *poListCtrl)
+{
+	poListCtrl->DeleteAllItems();
+}
+
+long CWindowUtil::AddListCtrlItem(CListCtrl *poListCtrl, const char *lpszText, long lParam)
+{
+	if (poListCtrl==0) return -1;
+
+	LV_ITEM sctItem;
+	sctItem.mask=LVIF_TEXT | LVIF_PARAM;
+	sctItem.iItem=0;
+	sctItem.lParam=lParam;
+	sctItem.iSubItem=0;
+	sctItem.pszText=(char*)lpszText;		// hope we can trust the caller
+	return poListCtrl->InsertItem(&sctItem);
+}
+
+void CWindowUtil::SetListCtrlItem(CListCtrl *poListCtrl, long lItemId, int iSubItemId, const char *lpszText)
+{
+	if (poListCtrl==0) return;
+
+	LV_ITEM sctItem;
+	sctItem.mask=LVIF_TEXT;
+	sctItem.iItem=lItemId;
+	sctItem.iSubItem=iSubItemId;
+	sctItem.pszText=(char*)lpszText;		// hope we can trust the caller
+	poListCtrl->SetItem(&sctItem);
+}
+
+void CWindowUtil::AddListCtrlColumn(
+	CListCtrl *poListCtrl,
+	int iColumnCount, 
+	const char *lpszText, 
+	double dWidth)
+{
+	ASSERT(poListCtrl!=0);		// valid parameter?
+	if (poListCtrl==0) return;
+
+	CRect cRect;
+	int iWidthBuf;
+
+	// determine dimensions of report list
+	poListCtrl->GetWindowRect(cRect);
+
+	// calculate width of new column
+	iWidthBuf=dWidth>1 ?
+		((int) (dWidth)) :
+		((int) (dWidth*cRect.Width()));
+
+	// create new column
+	poListCtrl->InsertColumn(iColumnCount,
+				lpszText,
+				LVCFMT_LEFT, iWidthBuf, iColumnCount);
+}
+
+
+TItemList<long> CWindowUtil::GetAllSelectedListCtrlItemLParams(CListCtrl *poListCtrl, bool bDisableNoSelectionErrorMsg)
+{
+	// buffer a pointer to the list control object
+	CListCtrl* pListCtrl=poListCtrl;
+	ASSERT(pListCtrl!=0);		// valid list parameter?
+	if (pListCtrl==0) return TItemList<long>();
+
+	// create the return item
+	TItemList<long> oSelectedLParams;
+
+	// get a list control read pointer
+	POSITION hPos=pListCtrl->GetFirstSelectedItemPosition();
+	if (hPos==0)
+	{
+		// user did not select an item
+		if (!bDisableNoSelectionErrorMsg)
+		{
+			AfxMessageBox(IDS_NoListItemSelected);
+		}
+	}
+	else
+	{   
+		// loop through all selected items and get their
+		// referring lParams
+		int nCurItem;
+		long lCurItemData;
+		while (hPos!=0)   
+		{
+			// fetch the next element
+			nCurItem=pListCtrl->GetNextSelectedItem(hPos);
+
+			// find out the item data of the current element;
+			lCurItemData=pListCtrl->GetItemData(nCurItem);
+
+			// give our element to the list
+			oSelectedLParams.AddNewElem(lCurItemData);
+		}
+	}
+
+	return oSelectedLParams;
+}
+
+int CWindowUtil::GetListCtrlItemIdByLParam(CListCtrl *poListCtrl, long lParam, int iStartAt)
+{
+	// find out the list control item that corresponds with the
+	// given lParam
+	LVFINDINFOA sctFindInfo;
+	sctFindInfo.flags=LVFI_PARAM;
+	sctFindInfo.lParam=lParam;
+	return poListCtrl->FindItem(&sctFindInfo, iStartAt);
+}
+
+
+void CWindowUtil::ForceNumericContent(CEdit *poEdit, bool bAllowNegative)
+{
+	ASSERT(poEdit!=0);
+	if (poEdit==0) return;
+
+
+	CString oOldString;
+	poEdit->GetWindowText(oOldString);
+	CString oNewString(oOldString);
+	oNewString.TrimLeft();
+	bool bIsNegative=false;
+	if (bAllowNegative)
+	{
+		if (oNewString.GetAt(0)=='-')
+		{
+			bIsNegative=true;
+			oNewString.Delete(0);
+		}
+	}
+	FilterString(oNewString, "0123456789");
+	if (bIsNegative)
+	{
+		oNewString=CString("-")+oNewString;
+	}
+	if (oNewString.GetLength()<oOldString.GetLength())
+	{
+		DWORD dwCurSel=poEdit->GetSel();
+		// have altered the text
+		poEdit->SetWindowText(oNewString);
+		poEdit->SetSel(dwCurSel);
+	}
+}
+
+void CWindowUtil::FilterString(CString &oString, const CString &oAcceptedChars)
+{
+	long lCurPos=0;
+	while (lCurPos<oString.GetLength())
+	{
+		if (oAcceptedChars.Find(oString.GetAt(lCurPos))!=-1)
+		{
+			// character is ok
+			lCurPos++;
+		}
+		else
+		{
+			// character is not ok
+			oString.Delete(lCurPos);
+		}
+	}
+}
+
+CString CWindowUtil::GetTimeDescription(long lMilliseconds, bool bIncludeMillis)
+{
+	long lSeconds=lMilliseconds/1000;
+	lMilliseconds=lMilliseconds%1000;
+	long lMinutes=lSeconds/60;
+	lSeconds=lSeconds%60;
+	long lHours=lMinutes/60;
+	lMinutes=lMinutes%60;
+	long lDays=lHours/24;
+	lHours=lHours%24;
+
+	CString oToReturn;
+	if (lDays>0)
+	{
+		oToReturn.Format("%dd:%02d:%02d:%02d", lDays, lHours, lMinutes, lSeconds);
+	}
+	else
+	{
+		oToReturn.Format("%02d:%02d:%02d", lHours, lMinutes, lSeconds);
+	}
+
+	if (bIncludeMillis)
+	{
+		CString oMillis;
+		oMillis.Format(":%03d", lMilliseconds);
+		oToReturn+=oMillis;
+	}
+	return oToReturn;
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/WindowUtil.h
@@ -1,0 +1,37 @@
+// WindowUtil.h: interface for the CWindowUtil class.
+// Author: Torsten Landmann
+//
+// some functionality to assist in work especially with windows controls
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_WINDOWUTIL_H__3B6C58DA_0CE8_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_WINDOWUTIL_H__3B6C58DA_0CE8_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "TItemList.h"
+
+class CWindowUtil  
+{
+public:
+	CWindowUtil();
+	virtual ~CWindowUtil();
+
+	static void DeleteAllListCtrlItems(CListCtrl *poListCtrl);
+	static long AddListCtrlItem(CListCtrl *poListCtrl, const char *lpszText, long lParam);
+	static void SetListCtrlItem(CListCtrl *poListCtrl, long lItemId, int iSubItemId, const char *lpszText);
+	static void AddListCtrlColumn(CListCtrl *poListCtrl, int iColumnCount, const char *lpszText, double dWidth);	// for dWidth: <1: percent of the width of the list control; >1 width in pixels
+	static TItemList<long> GetAllSelectedListCtrlItemLParams(CListCtrl *poListCtrl, bool bDisableNoSelectionErrorMsg);
+	static int GetListCtrlItemIdByLParam(CListCtrl *poListCtrl, long lParam, int iStartAt=-1);		// returns a negative value if none is found
+
+	static void ForceNumericContent(CEdit *poEdit, bool bAllowNegative);
+
+	static void FilterString(CString &oString, const CString &oAcceptedChars);
+
+	static CString GetTimeDescription(long lMilliseconds, bool bIncludeMillis=false);
+};
+
+#endif // !defined(AFX_WINDOWUTIL_H__3B6C58DA_0CE8_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/faac_wingui.clw
@@ -1,0 +1,299 @@
+; CLW file contains information for the MFC ClassWizard
+
+[General Info]
+Version=1
+LastClass=CEncoderGeneralPageDialog
+LastTemplate=CDialog
+NewFileInclude1=#include "stdafx.h"
+NewFileInclude2=#include "faac_wingui.h"
+
+ClassCount=10
+Class1=CFaac_winguiApp
+Class2=CFaac_winguiDlg
+Class3=CAboutDlg
+
+ResourceCount=15
+Resource1=IDD_ABOUTBOX
+Resource2=IDR_MAINFRAME
+Resource3=IDD_FAAC_WINGUI_DIALOG
+Resource4=IDD_PROPERTIESDUMMYPARENTDIALOG
+Resource5=IDD_PROPERTIESTABPARENTDIALOG (English (U.S.))
+Class4=CPropertiesTabParentDialog
+Resource6=IDD_PROCESSJOBSTATUSDIALOG (English (U.S.))
+Class5=CEncoderGeneralPageDialog
+Resource7=IDD_FLOATINGPROPERTYDIALOG (English (U.S.))
+Class6=CFloatingPropertyDialog
+Resource8=IDD_ENCODERGENERALPAGEDIALOG (English (U.S.))
+Class7=CPropertiesDummyParentDialog
+Resource9=IDD_FAAC_WINGUI_DIALOG (English (U.S.))
+Class8=CEncoderId3PageDialog
+Resource10=IDD_ENCODERQUALITYPAGEDIALOG
+Class9=CEncoderQualityPageDialog
+Resource11=IDD_ENCODERID3PAGEDIALOG (English (U.S.))
+Class10=CProcessJobStatusDialog
+Resource12=IDD_ABOUTBOX (English (U.S.))
+Resource13=IDR_TOOLBARMAIN (English (U.S.))
+Resource14=IDD_PROPERTIESDUMMYPARENTDIALOG (German (Germany))
+Resource15=IDD_ENCODERQUALITYPAGEDIALOG (German (Germany))
+
+[CLS:CFaac_winguiApp]
+Type=0
+HeaderFile=faac_wingui.h
+ImplementationFile=faac_wingui.cpp
+Filter=N
+
+[CLS:CFaac_winguiDlg]
+Type=0
+HeaderFile=faac_winguiDlg.h
+ImplementationFile=faac_winguiDlg.cpp
+Filter=D
+BaseClass=CDialog
+VirtualFilter=dWC
+LastObject=IDC_BUTTONDUPLICATESELECTED
+
+[CLS:CAboutDlg]
+Type=0
+HeaderFile=faac_winguiDlg.h
+ImplementationFile=faac_winguiDlg.cpp
+Filter=D
+
+[DLG:IDD_ABOUTBOX]
+Type=1
+ControlCount=4
+Control1=IDC_STATIC,static,1342177283
+Control2=IDC_STATIC,static,1342308352
+Control3=IDC_STATIC,static,1342308352
+Control4=IDOK,button,1342373889
+Class=CAboutDlg
+
+
+[DLG:IDD_FAAC_WINGUI_DIALOG]
+Type=1
+ControlCount=3
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_STATIC,static,1342308352
+Class=CFaac_winguiDlg
+
+[DLG:IDD_FAAC_WINGUI_DIALOG (English (U.S.))]
+Type=1
+Class=CFaac_winguiDlg
+ControlCount=9
+Control1=IDOK,button,1342242817
+Control2=IDC_LISTJOBS,SysListView32,1350664201
+Control3=IDC_BUTTONADDENCODERJOB,button,1342242816
+Control4=IDC_BUTTONDELETEJOBS,button,1342242816
+Control5=IDC_BUTTONPROCESSSELECTED,button,1342242816
+Control6=IDC_CHECKREMOVEPROCESSEDJOBS,button,1342242819
+Control7=IDC_BUTTONSAVEJOBLIST,button,1342242816
+Control8=IDC_BUTTONLOADJOBLIST,button,1342242816
+Control9=IDC_BUTTONDUPLICATESELECTED,button,1342242816
+
+[DLG:IDD_ABOUTBOX (English (U.S.))]
+Type=1
+Class=CAboutDlg
+ControlCount=5
+Control1=IDC_STATIC,static,1342177283
+Control2=IDC_STATIC,static,1342308480
+Control3=IDC_STATIC,static,1342308352
+Control4=IDOK,button,1342373889
+Control5=IDC_STATIC,static,1342308352
+
+[CLS:CPropertiesTabParentDialog]
+Type=0
+HeaderFile=PropertiesTabParentDialog.h
+ImplementationFile=PropertiesTabParentDialog.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CPropertiesTabParentDialog
+
+[DLG:IDD_PROPERTIESTABPARENTDIALOG (English (U.S.))]
+Type=1
+Class=CPropertiesTabParentDialog
+ControlCount=3
+Control1=IDC_TAB1,SysTabControl32,1342177280
+Control2=IDC_LABELNOSELECTION,static,1342308352
+Control3=IDC_LABELDEBUGTAG,static,1073872896
+
+[DLG:IDD_ENCODERGENERALPAGEDIALOG (English (U.S.))]
+Type=1
+Class=CEncoderGeneralPageDialog
+ControlCount=14
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_EDITSOURCEDIR,edit,1350631552
+Control3=IDC_BUTTONBROWSESOURCEDIR,button,1342242816
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_EDITSOURCEFILE,edit,1350631552
+Control6=IDC_BUTTONBROWSESOURCEFILE,button,1342242816
+Control7=IDC_CHECKRECURSIVE,button,1342242819
+Control8=IDC_STATIC,static,1342308352
+Control9=IDC_EDITTARGETDIR,edit,1350631552
+Control10=IDC_BUTTONBROWSETARGETDIR,button,1342242816
+Control11=IDC_STATIC,static,1342308352
+Control12=IDC_EDITTARGETFILE,edit,1350631552
+Control13=IDC_BUTTONBROWSETARGETFILE,button,1342242816
+Control14=IDC_BUTTON1,button,1073807361
+
+[CLS:CEncoderGeneralPageDialog]
+Type=0
+HeaderFile=EncoderGeneralPageDialog.h
+ImplementationFile=EncoderGeneralPageDialog.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=IDC_CHECKRECURSIVE
+
+[DLG:IDD_FLOATINGPROPERTYDIALOG (English (U.S.))]
+Type=1
+Class=CFloatingPropertyDialog
+ControlCount=1
+Control1=IDC_LABELDEBUGTAG,static,1073872896
+
+[CLS:CFloatingPropertyDialog]
+Type=0
+HeaderFile=FloatingPropertyDialog.h
+ImplementationFile=FloatingPropertyDialog.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=CFloatingPropertyDialog
+VirtualFilter=dWC
+
+[DLG:IDD_PROPERTIESDUMMYPARENTDIALOG]
+Type=1
+Class=CPropertiesDummyParentDialog
+ControlCount=3
+Control1=IDC_STATIC,static,1073872896
+Control2=IDC_STATIC,static,1073872896
+Control3=IDC_LABELDEBUGTAG,static,1073872896
+
+[CLS:CPropertiesDummyParentDialog]
+Type=0
+HeaderFile=PropertiesDummyParentDialog.h
+ImplementationFile=PropertiesDummyParentDialog.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+
+[DLG:IDD_ENCODERID3PAGEDIALOG (English (U.S.))]
+Type=1
+Class=CEncoderId3PageDialog
+ControlCount=24
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_STATIC,static,1342308352
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_EDITARTIST,edit,1350631552
+Control7=IDC_EDITTRACK,edit,1350631552
+Control8=IDC_EDITTITLE,edit,1350631552
+Control9=IDC_EDITURL,edit,1350631552
+Control10=IDC_STATIC,static,1342308352
+Control11=IDC_EDITALBUM,edit,1350631552
+Control12=IDC_STATIC,static,1342308352
+Control13=IDC_EDITYEAR,edit,1350631552
+Control14=IDC_STATIC,static,1342308352
+Control15=IDC_EDITCOMPOSER,edit,1350631552
+Control16=IDC_STATIC,static,1342308352
+Control17=IDC_EDITORIGINALARTIST,edit,1350631552
+Control18=IDC_CHECKCOPYRIGHT,button,1342242819
+Control19=IDC_STATIC,static,1342308352
+Control20=IDC_EDITCOMMENT,edit,1352728580
+Control21=IDC_STATIC,static,1342308352
+Control22=IDC_EDITENCODEDBY,edit,1350631552
+Control23=IDC_COMBOGENRE,combobox,1344340227
+Control24=IDC_BUTTON1,button,1073807361
+
+[CLS:CEncoderId3PageDialog]
+Type=0
+HeaderFile=EncoderId3PageDialog.h
+ImplementationFile=EncoderId3PageDialog.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=CEncoderId3PageDialog
+VirtualFilter=dWC
+
+[DLG:IDD_ENCODERQUALITYPAGEDIALOG]
+Type=1
+Class=CEncoderQualityPageDialog
+ControlCount=15
+Control1=IDC_STATIC,static,1342373888
+Control2=IDC_EDITBITRATE,edit,1350631552
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_EDITBANDWIDTH,edit,1350631552
+Control6=IDC_STATIC,static,1342308352
+Control7=IDC_CHECKMIDSIDE,button,1342242819
+Control8=IDC_CHECKUSETNS,button,1342242819
+Control9=IDC_CHECKUSELTP,button,1342242819
+Control10=IDC_CHECKUSELFE,button,1342242819
+Control11=IDC_STATIC,button,1342177287
+Control12=IDC_RADIOAACPROFILELC,button,1342373897
+Control13=IDC_RADIOAACPROFILEMAIN,button,1342177289
+Control14=IDC_RADIOAACPROFILESSR,button,1342177289
+Control15=IDC_BUTTON1,button,1073807361
+
+[CLS:CEncoderQualityPageDialog]
+Type=0
+HeaderFile=EncoderQualityPageDialog.h
+ImplementationFile=EncoderQualityPageDialog.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=CEncoderQualityPageDialog
+VirtualFilter=dWC
+
+[DLG:IDD_PROCESSJOBSTATUSDIALOG (English (U.S.))]
+Type=1
+Class=CProcessJobStatusDialog
+ControlCount=6
+Control1=IDC_LABELTOPSTATUSTEXT,static,1342308353
+Control2=IDC_LABELBOTTOMSTATUSTEXT,static,1342308353
+Control3=IDC_PROGRESS1,msctls_progress32,1350565888
+Control4=IDC_BUTTONABORT,button,1073807360
+Control5=IDC_BUTTONPAUSE,button,1073807360
+Control6=IDC_BUTTONCONTINUE,button,1208025088
+
+[CLS:CProcessJobStatusDialog]
+Type=0
+HeaderFile=ProcessJobStatusDialog.h
+ImplementationFile=ProcessJobStatusDialog.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CProcessJobStatusDialog
+
+[TB:IDR_TOOLBARMAIN (English (U.S.))]
+Type=1
+Class=?
+Command1=ID_BUTTON32771
+Command2=ID_BUTTON32772
+Command3=ID_BUTTON32773
+Command4=ID_BUTTON32774
+CommandCount=4
+
+[DLG:IDD_PROPERTIESDUMMYPARENTDIALOG (German (Germany))]
+Type=1
+ControlCount=3
+Control1=IDC_STATIC,static,1073872896
+Control2=IDC_STATIC,static,1073872896
+Control3=IDC_LABELDEBUGTAG,static,1073872896
+
+[DLG:IDD_ENCODERQUALITYPAGEDIALOG (German (Germany))]
+Type=1
+ControlCount=15
+Control1=IDC_STATIC,static,1342373888
+Control2=IDC_EDITBITRATE,edit,1350631552
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_EDITBANDWIDTH,edit,1350631552
+Control6=IDC_STATIC,static,1342308352
+Control7=IDC_CHECKMIDSIDE,button,1342242819
+Control8=IDC_CHECKUSETNS,button,1342242819
+Control9=IDC_CHECKUSELTP,button,1342242819
+Control10=IDC_CHECKUSELFE,button,1342242819
+Control11=IDC_STATIC,button,1342177287
+Control12=IDC_RADIOAACPROFILELC,button,1342373897
+Control13=IDC_RADIOAACPROFILEMAIN,button,1342177289
+Control14=IDC_RADIOAACPROFILESSR,button,1342177289
+Control15=IDC_BUTTON1,button,1073807361
+
--- /dev/null
+++ b/wingui/faac_wingui.cpp
@@ -1,0 +1,106 @@
+// faac_wingui.cpp : Defines the class behaviors for the application.
+// Author: MSVC6.0 Wizard and Torsten Landmann :)
+//
+///////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "faac_winguiDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CFaac_winguiApp
+
+BEGIN_MESSAGE_MAP(CFaac_winguiApp, CWinApp)
+	//{{AFX_MSG_MAP(CFaac_winguiApp)
+		// NOTE - the ClassWizard will add and remove mapping macros here.
+		//    DO NOT EDIT what you see in these blocks of generated code!
+	//}}AFX_MSG
+	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CFaac_winguiApp construction
+
+CFaac_winguiApp::CFaac_winguiApp():
+	m_poCurPropertiesDummyParentDialogSingletonContainer(0)
+{
+	// TODO: add construction code here,
+	// Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CFaac_winguiApp object
+
+CFaac_winguiApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CFaac_winguiApp initialization
+
+BOOL CFaac_winguiApp::InitInstance()
+{
+	AfxEnableControlContainer();
+
+	// Standard initialization
+	// If you are not using these features and wish to reduce the size
+	//  of your final executable, you should remove from the following
+	//  the specific initialization routines you do not need.
+
+#ifdef _AFXDLL
+	Enable3dControls();			// Call this when using MFC in a shared DLL
+#else
+	Enable3dControlsStatic();	// Call this when linking to MFC statically
+#endif
+
+	CFaac_winguiDlg dlg;
+	m_pMainWnd = &dlg;
+	int nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: Place code here to handle when the dialog is
+		//  dismissed with OK
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: Place code here to handle when the dialog is
+		//  dismissed with Cancel
+	}
+
+	PerformAppCleanup();
+
+	// Since the dialog has been closed, return FALSE so that we exit the
+	//  application, rather than start the application's message pump.
+	return FALSE;
+}
+
+void CFaac_winguiApp::SetGlobalPropertiesDummyParentDialogSingleton(
+	CPropertiesDummyParentDialog *poPropertyContainer)
+{
+	if (m_poCurPropertiesDummyParentDialogSingletonContainer!=0)
+	{
+		//m_poCurPropertiesDummyParentDialogSingletonContainer->DestroyWindow();
+		delete m_poCurPropertiesDummyParentDialogSingletonContainer;
+		m_poCurPropertiesDummyParentDialogSingletonContainer=0;
+	}
+
+	m_poCurPropertiesDummyParentDialogSingletonContainer=poPropertyContainer;
+}
+
+CPropertiesDummyParentDialog* CFaac_winguiApp::GetGlobalPropertiesDummyParentDialogSingleton()
+{
+	return m_poCurPropertiesDummyParentDialogSingletonContainer;
+}
+
+void CFaac_winguiApp::PerformAppCleanup()
+{
+	if (m_poCurPropertiesDummyParentDialogSingletonContainer!=0)
+	{
+		delete m_poCurPropertiesDummyParentDialogSingletonContainer;
+		m_poCurPropertiesDummyParentDialogSingletonContainer=0;
+	}
+}
\ No newline at end of file
--- /dev/null
+++ b/wingui/faac_wingui.dsp
@@ -1,0 +1,496 @@
+# Microsoft Developer Studio Project File - Name="faac_wingui" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=faac_wingui - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "faac_wingui.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "faac_wingui.mak" CFG="faac_wingui - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "faac_wingui - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "faac_wingui - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=xicl6.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "faac_wingui - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../include" /I "C:\Eigene Dateien\Programmierung\C_Projekte\Downloaded_GNU\libsndfile\libsndfile-0.0.22\src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=xilink6.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 libsndfile.lib /nologo /subsystem:windows /machine:I386
+
+!ELSEIF  "$(CFG)" == "faac_wingui - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../include" /I "C:\Eigene Dateien\Programmierung\C_Projekte\Downloaded_GNU\libsndfile\libsndfile-0.0.22\src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=xilink6.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libsndfile.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "faac_wingui - Win32 Release"
+# Name "faac_wingui - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\AbstractJob.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\AbstractPageCtrlContent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\AbstractPropertyPageContents.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ConcreteJobBase.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderGeneralPageDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderGeneralPropertyPageContents.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderId3PageDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderId3PropertyPageContents.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderJob.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderJobProcessingManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderQualityPageDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderQualityPropertyPageContents.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\faac_wingui.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\faac_wingui.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\faac_winguiDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FaacWinguiProgramSettings.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FileListQueryManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FileMaskAssembler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FilePathCalc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FileSerializable.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FileSerializableJobList.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FloatingPropertyDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FolderDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Id3TagInfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Job.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\JobList.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\JobListCtrlDescribable.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\JobListsToConfigureSaver.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\JobListUpdatable.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ListCtrlStateSaver.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Listobj.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PageCheckboxCtrlContent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PageComboBoxCtrlContent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PageEditCtrlContent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PageRadioGroupCtrlContent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessingStartStopPauseInteractable.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessingStatusDialogInfoFeedbackCallbackInterface.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessJobStatusDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PropertiesDummyParentDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PropertiesTabParentDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RecursiveDirectoryTraverser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SourceTargetFilePair.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\SupportedPropertyPagesData.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TItemList.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\WindowUtil.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\AbstractJob.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\AbstractPageCtrlContent.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\AbstractPropertyPageContents.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ConcreteJobBase.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderGeneralPageDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderGeneralPropertyPageContents.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderId3PageDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderId3PropertyPageContents.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderJob.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderJobProcessingManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderQualityPageDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EncoderQualityPropertyPageContents.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\faac.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\faac_wingui.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\faac_winguiDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FaacWinguiProgramSettings.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FileListQueryManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FileMaskAssembler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FilePathCalc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FileSerializable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FileSerializableJobList.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FloatingPropertyDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FolderDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Id3TagInfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Job.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\JobList.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\JobListCtrlDescribable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\JobListsToConfigureSaver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\JobListUpdatable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ListCtrlStateSaver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\listobj.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PageCheckboxCtrlContent.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PageComboBoxCtrlContent.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PageEditCtrlContent.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PageRadioGroupCtrlContent.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessingStartStopPauseInteractable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessingStatusDialogInfoFeedbackCallbackInterface.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessJobStatusDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PropertiesDummyParentDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PropertiesTabParentDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RecursiveDirectoryTraverser.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE="E:\Program Files\Microsoft Visual Studio\VC98\Include\sndfile.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\SourceTargetFilePair.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SupportedPropertyPagesData.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TItemList.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\WindowUtil.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\faac_wingui.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\faac_wingui.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\toolbarm.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
--- /dev/null
+++ b/wingui/faac_wingui.dsw
@@ -1,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "faac_wingui"=.\faac_wingui.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name libfaac
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libfaac"=..\libfaac\libfaac.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+++ b/wingui/faac_wingui.h
@@ -1,0 +1,82 @@
+// faac_wingui.h : main header file for the FAAC_WINGUI application
+// Author: MSVC6.0 Wizard and Torsten Landmann :)
+// 
+/////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_FAAC_WINGUI_H__DFE38E65_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_FAAC_WINGUI_H__DFE38E65_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifndef __AFXWIN_H__
+	#error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h"		// main symbols
+#include "JobList.h"
+#include "PropertiesDummyParentDialog.h"
+#include "FaacWinguiProgramSettings.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CFaac_winguiApp:
+// See faac_wingui.cpp for the implementation of this class
+//
+
+class CFaac_winguiApp : public CWinApp
+{
+public:
+	CFaac_winguiApp();
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CFaac_winguiApp)
+	public:
+	virtual BOOL InitInstance();
+	//}}AFX_VIRTUAL
+
+	const CJobList& GetGlobalJobList() const			{ return m_oGlobalJobList; }
+	CJobList& GetGlobalJobList()						{ return m_oGlobalJobList; }
+	const CFaacWinguiProgramSettings& GetGlobalProgramSettings() const		{ return m_oGlobalProgramSettings; }
+	CFaacWinguiProgramSettings& GetGlobalProgramSettings()					{ return m_oGlobalProgramSettings; }
+
+	// these two members are not an exact pair (getter/setter); however they
+	// work closely together
+	void SetGlobalPropertiesDummyParentDialogSingleton(CPropertiesDummyParentDialog *poPropertyContainer);
+	CPropertiesDummyParentDialog* GetGlobalPropertiesDummyParentDialogSingleton();
+
+// Implementation
+
+	//{{AFX_MSG(CFaac_winguiApp)
+		// NOTE - the ClassWizard will add and remove member functions here.
+		//    DO NOT EDIT what you see in these blocks of generated code !
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+private:
+	// this list is the global job list within this application
+	CJobList m_oGlobalJobList;
+
+	// this object contains all global program settings
+	CFaacWinguiProgramSettings m_oGlobalProgramSettings;
+
+	// global program settings
+	CFaacWinguiProgramSettings m_oProgramSettings;
+
+	// this member saves a pointer to the entry point to display
+	// properties of jobs
+	CPropertiesDummyParentDialog *m_poCurPropertiesDummyParentDialogSingletonContainer;
+
+
+	// something like the destructor of the application
+	void PerformAppCleanup();
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_FAAC_WINGUI_H__DFE38E65_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/faac_wingui.rc
@@ -1,0 +1,844 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// German (Germany) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+    "#ifdef _WIN32\r\n"
+    "LANGUAGE 9, 1\r\n"
+    "#pragma code_page(1252)\r\n"
+    "#endif //_WIN32\r\n"
+    "#include ""res\\faac_wingui.rc2""  // non-Microsoft Visual C++ edited resources\r\n"
+    "#include ""afxres.rc""         // Standard components\r\n"
+    "#endif\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME           ICON    DISCARDABLE     "res\\faac_wingui.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_PROPERTIESDUMMYPARENTDIALOG DIALOG DISCARDABLE  0, 0, 186, 95
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+    LTEXT           "This dialog serves as an instance to normalize coordinates for different property dialog locations (docked, floating window).",
+                    IDC_STATIC,10,10,159,26,NOT WS_VISIBLE
+    LTEXT           "The order in which dialogs contain each other is as follows:\nparent window (floating, main dlg, etc.)\nthis dialog\npropertiestabparentdialog\nproperty pages",
+                    IDC_STATIC,10,37,159,48,NOT WS_VISIBLE
+    LTEXT           "Dummy",IDC_LABELDEBUGTAG,157,87,24,8,NOT WS_VISIBLE
+END
+
+IDD_ENCODERQUALITYPAGEDIALOG DIALOG DISCARDABLE  0, 0, 253, 131
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+    LTEXT           "Output Bitrate",IDC_STATIC,5,10,44,8,WS_TABSTOP
+    EDITTEXT        IDC_EDITBITRATE,64,7,52,14,ES_AUTOHSCROLL
+    LTEXT           "bit/s",IDC_STATIC,119,10,15,8
+    LTEXT           "Bandwidth",IDC_STATIC,5,28,34,8
+    EDITTEXT        IDC_EDITBANDWIDTH,64,25,52,14,ES_AUTOHSCROLL
+    LTEXT           "Hz",IDC_STATIC,119,28,10,8
+    CONTROL         "Allow Mid/Side",IDC_CHECKMIDSIDE,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,24,49,63,10
+    CONTROL         "Use TNS",IDC_CHECKUSETNS,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,24,60,45,10
+    CONTROL         "Use LTP",IDC_CHECKUSELTP,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,24,72,44,10
+    CONTROL         "Use LFE",IDC_CHECKUSELFE,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,24,83,43,10
+    GROUPBOX        "AAC Profile",IDC_STATIC,133,46,47,48
+    CONTROL         "LC",IDC_RADIOAACPROFILELC,"Button",BS_AUTORADIOBUTTON | 
+                    WS_GROUP | WS_TABSTOP,142,58,25,10
+    CONTROL         "Main",IDC_RADIOAACPROFILEMAIN,"Button",
+                    BS_AUTORADIOBUTTON,142,69,31,10
+    CONTROL         "SSR",IDC_RADIOAACPROFILESSR,"Button",BS_AUTORADIOBUTTON,
+                    142,79,31,10
+    DEFPUSHBUTTON   "Enter Attractor",IDC_BUTTON1,198,112,50,14,NOT 
+                    WS_VISIBLE
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE 
+BEGIN
+    IDD_PROPERTIESDUMMYPARENTDIALOG, DIALOG
+    BEGIN
+        VERTGUIDE, 10
+        VERTGUIDE, 169
+    END
+
+    IDD_ENCODERQUALITYPAGEDIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 5
+        RIGHTMARGIN, 248
+        VERTGUIDE, 24
+        VERTGUIDE, 64
+        VERTGUIDE, 116
+        VERTGUIDE, 119
+        VERTGUIDE, 142
+        TOPMARGIN, 5
+        BOTTOMMARGIN, 126
+        HORZGUIDE, 14
+        HORZGUIDE, 32
+        HORZGUIDE, 49
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+#endif    // German (Germany) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOG DISCARDABLE  0, 0, 244, 55
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About faac_wingui"
+FONT 8, "MS Sans Serif"
+BEGIN
+    ICON            IDR_MAINFRAME,IDC_STATIC,11,17,21,20
+    LTEXT           "faac_wingui Version 1.0",IDC_STATIC,40,10,119,8,
+                    SS_NOPREFIX
+    LTEXT           "Copyright (C) 2001",IDC_STATIC,39,33,119,8
+    DEFPUSHBUTTON   "OK",IDOK,187,34,50,14,WS_GROUP
+    LTEXT           "GUI written by Torsten Landmann as part of the faac Project",
+                    IDC_STATIC,40,22,190,8
+END
+
+IDD_FAAC_WINGUI_DIALOG DIALOGEX 0, 0, 422, 199
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "winfaac"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "Bye",IDOK,365,178,50,14
+    CONTROL         "List1",IDC_LISTJOBS,"SysListView32",LVS_REPORT | 
+                    LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | 
+                    WS_TABSTOP,7,7,408,131
+    PUSHBUTTON      "&Add Encoder Jobs...",IDC_BUTTONADDENCODERJOB,7,143,71,
+                    14
+    PUSHBUTTON      "&Delete Jobs",IDC_BUTTONDELETEJOBS,83,143,50,14
+    PUSHBUTTON      "&Process Selected",IDC_BUTTONPROCESSSELECTED,7,161,66,
+                    14
+    CONTROL         "Remove Processed Jobs From List",
+                    IDC_CHECKREMOVEPROCESSEDJOBS,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,7,182,125,10
+    PUSHBUTTON      "&Save Joblist...",IDC_BUTTONSAVEJOBLIST,301,143,54,14
+    PUSHBUTTON      "&Load Joblist...",IDC_BUTTONLOADJOBLIST,361,143,54,14
+    PUSHBUTTON      "D&uplicate Selected",IDC_BUTTONDUPLICATESELECTED,139,
+                    143,69,14
+END
+
+IDD_PROPERTIESTABPARENTDIALOG DIALOG DISCARDABLE  0, 0, 186, 95
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "Tab1",IDC_TAB1,"SysTabControl32",0x0,51,44,50,30
+    LTEXT           "No appropriate selection of jobs",IDC_LABELNOSELECTION,
+                    25,32,100,8
+    LTEXT           "TabParent",IDC_LABELDEBUGTAG,152,87,34,8,NOT WS_VISIBLE
+END
+
+IDD_ENCODERGENERALPAGEDIALOG DIALOG DISCARDABLE  0, 0, 253, 131
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+    LTEXT           "&Source Directory",IDC_STATIC,5,5,54,8
+    EDITTEXT        IDC_EDITSOURCEDIR,5,14,187,14,ES_AUTOHSCROLL
+    PUSHBUTTON      "&Browse...",IDC_BUTTONBROWSESOURCEDIR,198,14,50,14
+    LTEXT           "Source &File Name:",IDC_STATIC,5,33,59,8
+    EDITTEXT        IDC_EDITSOURCEFILE,67,30,125,14,ES_AUTOHSCROLL
+    PUSHBUTTON      "Br&owse...",IDC_BUTTONBROWSESOURCEFILE,198,30,50,14
+    CONTROL         "&Recursive",IDC_CHECKRECURSIVE,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,67,46,48,10
+    LTEXT           "&Target Directory",IDC_STATIC,5,62,52,8
+    EDITTEXT        IDC_EDITTARGETDIR,5,73,187,14,ES_AUTOHSCROLL
+    PUSHBUTTON      "Bro&wse...",IDC_BUTTONBROWSETARGETDIR,198,73,50,14
+    LTEXT           "Target File &Name:",IDC_STATIC,5,93,57,8
+    EDITTEXT        IDC_EDITTARGETFILE,67,90,125,14,ES_AUTOHSCROLL
+    PUSHBUTTON      "Brows&e...",IDC_BUTTONBROWSETARGETFILE,198,90,50,14
+    DEFPUSHBUTTON   "Enter Attractor",IDC_BUTTON1,198,112,50,14,NOT 
+                    WS_VISIBLE
+END
+
+IDD_FLOATINGPROPERTYDIALOG DIALOGEX 0, 0, 258, 148
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOOLWINDOW
+CAPTION "Properties"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+    LTEXT           "Properties",IDC_LABELDEBUGTAG,225,140,32,8,NOT 
+                    WS_VISIBLE
+END
+
+IDD_ENCODERID3PAGEDIALOG DIALOG DISCARDABLE  0, 0, 253, 131
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+    LTEXT           "Artist:",IDC_STATIC,5,10,18,8
+    LTEXT           "Track:",IDC_STATIC,5,27,22,8
+    LTEXT           "Genre",IDC_STATIC,5,95,20,8
+    LTEXT           "Title:",IDC_STATIC,5,44,16,8
+    LTEXT           "URL",IDC_STATIC,5,78,16,8
+    EDITTEXT        IDC_EDITARTIST,33,7,215,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_EDITTRACK,33,24,18,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_EDITTITLE,33,41,165,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_EDITURL,33,75,215,14,ES_AUTOHSCROLL
+    LTEXT           "Album:",IDC_STATIC,59,27,22,8
+    EDITTEXT        IDC_EDITALBUM,83,24,110,14,ES_AUTOHSCROLL
+    LTEXT           "Year:",IDC_STATIC,200,27,18,8
+    EDITTEXT        IDC_EDITYEAR,220,24,28,14,ES_AUTOHSCROLL
+    LTEXT           "Composer:",IDC_STATIC,131,61,34,8
+    EDITTEXT        IDC_EDITCOMPOSER,172,58,76,14,ES_AUTOHSCROLL
+    LTEXT           "Orig. Artist:",IDC_STATIC,5,61,35,8
+    EDITTEXT        IDC_EDITORIGINALARTIST,48,58,80,14,ES_AUTOHSCROLL
+    CONTROL         "Copyright",IDC_CHECKCOPYRIGHT,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,203,43,45,10
+    LTEXT           "Comment",IDC_STATIC,135,95,30,8
+    EDITTEXT        IDC_EDITCOMMENT,135,105,113,21,ES_MULTILINE | WS_VSCROLL
+    LTEXT           "Encoded by:",IDC_STATIC,5,114,41,8
+    EDITTEXT        IDC_EDITENCODEDBY,48,111,80,14,ES_AUTOHSCROLL
+    COMBOBOX        IDC_COMBOGENRE,33,93,95,198,CBS_DROPDOWNLIST | CBS_SORT | 
+                    WS_VSCROLL | WS_TABSTOP
+    DEFPUSHBUTTON   "Enter Attractor",IDC_BUTTON1,198,92,50,14,NOT 
+                    WS_VISIBLE
+END
+
+IDD_PROCESSJOBSTATUSDIALOG DIALOG DISCARDABLE  0, 0, 354, 109
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
+CAPTION "Processing Job..."
+FONT 8, "MS Sans Serif"
+BEGIN
+    CTEXT           "Static",IDC_LABELTOPSTATUSTEXT,7,7,340,39
+    CTEXT           "Static",IDC_LABELBOTTOMSTATUSTEXT,7,58,340,23
+    CONTROL         "Progress1",IDC_PROGRESS1,"msctls_progress32",WS_BORDER,
+                    23,47,307,10
+    PUSHBUTTON      "Abort",IDC_BUTTONABORT,152,88,50,14,NOT WS_VISIBLE
+    PUSHBUTTON      "Pause",IDC_BUTTONPAUSE,207,88,50,14,NOT WS_VISIBLE
+    PUSHBUTTON      "Continue",IDC_BUTTONCONTINUE,262,88,50,14,NOT 
+                    WS_VISIBLE | WS_DISABLED
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE 
+BEGIN
+    IDD_ABOUTBOX, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 237
+        VERTGUIDE, 40
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 48
+    END
+
+    IDD_FAAC_WINGUI_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 415
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 192
+        HORZGUIDE, 150
+        HORZGUIDE, 168
+    END
+
+    IDD_PROPERTIESTABPARENTDIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        TOPMARGIN, 6
+    END
+
+    IDD_ENCODERGENERALPAGEDIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 5
+        RIGHTMARGIN, 248
+        VERTGUIDE, 67
+        VERTGUIDE, 192
+        VERTGUIDE, 198
+        TOPMARGIN, 5
+        BOTTOMMARGIN, 126
+        HORZGUIDE, 21
+        HORZGUIDE, 37
+        HORZGUIDE, 51
+        HORZGUIDE, 66
+        HORZGUIDE, 80
+        HORZGUIDE, 97
+    END
+
+    IDD_FLOATINGPROPERTYDIALOG, DIALOG
+    BEGIN
+        RIGHTMARGIN, 257
+    END
+
+    IDD_ENCODERID3PAGEDIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 5
+        RIGHTMARGIN, 248
+        VERTGUIDE, 33
+        VERTGUIDE, 48
+        VERTGUIDE, 128
+        VERTGUIDE, 135
+        TOPMARGIN, 5
+        BOTTOMMARGIN, 126
+        HORZGUIDE, 14
+        HORZGUIDE, 31
+        HORZGUIDE, 48
+        HORZGUIDE, 65
+        HORZGUIDE, 82
+        HORZGUIDE, 99
+        HORZGUIDE, 118
+    END
+
+    IDD_PROCESSJOBSTATUSDIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 347
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 102
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904B0"
+        BEGIN
+            VALUE "CompanyName", "\0"
+            VALUE "FileDescription", "faac_wingui MFC Application\0"
+            VALUE "FileVersion", "1, 0, 0, 1\0"
+            VALUE "InternalName", "faac_wingui\0"
+            VALUE "LegalCopyright", "Copyright (C) 2001\0"
+            VALUE "LegalTrademarks", "\0"
+            VALUE "OriginalFilename", "faac_wingui.EXE\0"
+            VALUE "ProductName", "faac_wingui Application\0"
+            VALUE "ProductVersion", "1, 0, 0, 1\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_ENCODERID3PAGEDIALOG DLGINIT
+BEGIN
+    IDC_COMBOGENRE, 0x403, 1, 0
+"\000" 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x2041, 0x6143, 0x7070, 0x6c65, 0x616c, "\000" 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6341, 0x6469, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6341, 0x6469, 0x4a20, 0x7a61, 0x007a, 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6341, 0x6469, 0x5020, 0x6e75, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x6341, 0x756f, 0x7473, 0x6369, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6c41, 0x2e74, 0x5220, 0x636f, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6c41, 0x6574, 0x6e72, 0x7461, 0x7669, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x6d41, 0x6962, 0x6e65, 0x0074, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6e41, 0x6d69, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x7641, 0x6e61, 0x6774, 0x7261, 0x6564, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6142, 0x6c6c, 0x6461, "\000" 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6142, 0x7373, "\000" 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6542, 0x7461, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6542, 0x6f62, 0x0062, 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x6942, 0x2067, 0x6142, 0x646e, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6c42, 0x6361, 0x206b, 0x654d, 0x6174, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6c42, 0x6575, 0x7267, 0x7361, 0x0073, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6c42, 0x6575, 0x0073, 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x6f42, 0x746f, 0x2079, 0x6142, 0x7373, "\000" 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x7242, 0x7469, 0x6f50, 0x0070, 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x6143, 0x6162, 0x6572, 0x0074, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6543, 0x746c, 0x6369, "\000" 
+    IDC_COMBOGENRE, 0x403, 14, 0
+0x6843, 0x6d61, 0x6562, 0x2072, 0x754d, 0x6973, 0x0063, 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x6843, 0x6e61, 0x6f73, 0x006e, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6843, 0x726f, 0x7375, "\000" 
+    IDC_COMBOGENRE, 0x403, 22, 0
+0x6843, 0x6972, 0x7473, 0x6169, 0x206e, 0x6147, 0x676e, 0x7473, 0x2061, 
+0x6152, 0x0070, 
+    IDC_COMBOGENRE, 0x403, 14, 0
+0x6843, 0x6972, 0x7473, 0x6169, 0x206e, 0x6152, 0x0070, 
+    IDC_COMBOGENRE, 0x403, 15, 0
+0x6843, 0x6972, 0x7473, 0x6169, 0x206e, 0x6f52, 0x6b63, "\000" 
+    IDC_COMBOGENRE, 0x403, 13, 0
+0x6c43, 0x7361, 0x6973, 0x2063, 0x6f52, 0x6b63, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6c43, 0x7361, 0x6973, 0x6163, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6c43, 0x6275, "\000" 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x6c43, 0x6275, 0x482d, 0x756f, 0x6573, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6f43, 0x656d, 0x7964, "\000" 
+    IDC_COMBOGENRE, 0x403, 23, 0
+0x6f43, 0x746e, 0x6d65, 0x6f70, 0x6172, 0x7972, 0x4320, 0x7268, 0x7369, 
+0x6974, 0x6e61, "\000" 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x6f43, 0x6e75, 0x7274, 0x0079, 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x7243, 0x736f, 0x6f73, 0x6576, 0x0072, 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x7543, 0x746c, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6144, 0x636e, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x6144, 0x636e, 0x2065, 0x6148, 0x6c6c, "\000" 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x6144, 0x6b72, 0x6177, 0x6576, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6544, 0x7461, 0x2068, 0x654d, 0x6174, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6944, 0x6373, 0x006f, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x7244, 0x6165, 0x006d, 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x7244, 0x6d75, 0x2620, 0x4220, 0x7361, 0x0073, 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x7244, 0x6d75, 0x5320, 0x6c6f, 0x006f, 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x7544, 0x7465, "\000" 
+    IDC_COMBOGENRE, 0x403, 15, 0
+0x6145, 0x7973, 0x4c20, 0x7369, 0x6574, 0x696e, 0x676e, "\000" 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x6c45, 0x6365, 0x7274, 0x6e6f, 0x6369, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7445, 0x6e68, 0x6369, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x7545, 0x6f72, 0x6164, 0x636e, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x7545, 0x6f72, 0x482d, 0x756f, 0x6573, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x7545, 0x6f72, 0x542d, 0x6365, 0x6e68, 0x006f, 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6146, 0x7473, 0x462d, 0x7375, 0x6f69, 0x006e, 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6f46, 0x6b6c, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6f46, 0x6b6c, 0x522f, 0x636f, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x6f46, 0x6b6c, 0x6f6c, 0x6572, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x7246, 0x6565, 0x7473, 0x6c79, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x7546, 0x6b6e, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7546, 0x6973, 0x6e6f, "\000" 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6147, 0x656d, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6147, 0x676e, 0x7473, 0x2061, 0x6152, 0x0070, 
+    IDC_COMBOGENRE, 0x403, 4, 0
+0x6f47, 0x0061, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6f47, 0x7073, 0x6c65, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6f47, 0x6874, 0x6369, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6f47, 0x6874, 0x6369, 0x5220, 0x636f, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7247, 0x6e75, 0x6567, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6148, 0x6472, 0x5220, 0x636f, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x6148, 0x6472, 0x6f63, 0x6572, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6548, 0x7661, 0x2079, 0x654d, 0x6174, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x6948, 0x2d70, 0x6f48, 0x0070, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6f48, 0x7375, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7548, 0x6f6d, 0x7275, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6e49, 0x6964, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x6e49, 0x7564, 0x7473, 0x6972, 0x6c61, "\000" 
+    IDC_COMBOGENRE, 0x403, 13, 0
+0x6e49, 0x7473, 0x7572, 0x656d, 0x746e, 0x6c61, "\000" 
+    IDC_COMBOGENRE, 0x403, 17, 0
+0x6e49, 0x7473, 0x7572, 0x656d, 0x746e, 0x6c61, 0x5020, 0x706f, "\000" 
+    IDC_COMBOGENRE, 0x403, 18, 0
+0x6e49, 0x7473, 0x7572, 0x656d, 0x746e, 0x6c61, 0x5220, 0x636f, 0x006b, 
+
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x614a, 0x7a7a, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x614a, 0x7a7a, 0x462b, 0x6e75, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x504a, 0x706f, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x754a, 0x676e, 0x656c, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x614c, 0x6974, 0x006e, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6f4c, 0x462d, 0x0069, 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x654d, 0x6964, 0x6174, 0x6974, 0x6576, "\000" 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x654d, 0x6572, 0x676e, 0x6575, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x654d, 0x6174, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x754d, 0x6973, 0x6163, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 14, 0
+0x614e, 0x6974, 0x6e6f, 0x6c61, 0x4620, 0x6c6f, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 16, 0
+0x614e, 0x6974, 0x6576, 0x4120, 0x656d, 0x6972, 0x6163, 0x006e, 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x654e, 0x6567, 0x7072, 0x6e75, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x654e, 0x2077, 0x6741, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x654e, 0x2077, 0x6157, 0x6576, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6f4e, 0x7369, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6c4f, 0x6964, 0x7365, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x704f, 0x7265, 0x0061, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x744f, 0x6568, 0x0072, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6f50, 0x6b6c, 0x0061, 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x6f50, 0x736c, 0x206b, 0x7550, 0x6b6e, "\000" 
+    IDC_COMBOGENRE, 0x403, 4, 0
+0x6f50, 0x0070, 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x6f50, 0x2f70, 0x7546, 0x6b6e, "\000" 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x6f50, 0x2d70, 0x6f46, 0x6b6c, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6f50, 0x6e72, 0x4720, 0x6f72, 0x766f, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 13, 0
+0x6f50, 0x6577, 0x2072, 0x6142, 0x6c6c, 0x6461, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7250, 0x6e61, 0x736b, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7250, 0x6d69, 0x7375, "\000" 
+    IDC_COMBOGENRE, 0x403, 17, 0
+0x7250, 0x676f, 0x6572, 0x7373, 0x7669, 0x2065, 0x6f52, 0x6b63, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x7350, 0x6379, 0x6568, 0x6564, 0x696c, 0x0063, 
+    IDC_COMBOGENRE, 0x403, 17, 0
+0x7350, 0x6379, 0x6568, 0x6564, 0x696c, 0x2063, 0x6f52, 0x6b63, "\000" 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x7550, 0x6b6e, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x7550, 0x6b6e, 0x5220, 0x636f, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 4, 0
+0x2652, 0x0042, 
+    IDC_COMBOGENRE, 0x403, 4, 0
+0x6152, 0x0070, 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6152, 0x6576, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6552, 0x6767, 0x6561, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6552, 0x7274, 0x006f, 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x6552, 0x6976, 0x6176, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 14, 0
+0x6852, 0x7479, 0x6d68, 0x6369, 0x5320, 0x756f, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6f52, 0x6b63, "\000" 
+    IDC_COMBOGENRE, 0x403, 12, 0
+0x6f52, 0x6b63, 0x2620, 0x5220, 0x6c6f, 0x006c, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6153, 0x736c, 0x0061, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6153, 0x626d, 0x0061, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6153, 0x6974, 0x6572, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6853, 0x776f, 0x7574, 0x656e, 0x0073, 
+    IDC_COMBOGENRE, 0x403, 4, 0
+0x6b53, 0x0061, 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x6c53, 0x776f, 0x4a20, 0x6d61, "\000" 
+    IDC_COMBOGENRE, 0x403, 10, 0
+0x6c53, 0x776f, 0x5220, 0x636f, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6f53, 0x616e, 0x6174, "\000" 
+    IDC_COMBOGENRE, 0x403, 5, 0
+0x6f53, 0x6c75, "\000" 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x6f53, 0x6e75, 0x2064, 0x6c43, 0x7069, "\000" 
+    IDC_COMBOGENRE, 0x403, 11, 0
+0x6f53, 0x6e75, 0x7464, 0x6172, 0x6b63, "\000" 
+    IDC_COMBOGENRE, 0x403, 14, 0
+0x6f53, 0x7475, 0x6568, 0x6e72, 0x5220, 0x636f, 0x006b, 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x7053, 0x6361, 0x0065, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7053, 0x6565, 0x6863, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x7753, 0x6e69, 0x0067, 
+    IDC_COMBOGENRE, 0x403, 15, 0
+0x7953, 0x706d, 0x6f68, 0x696e, 0x2063, 0x6f52, 0x6b63, "\000" 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x7953, 0x706d, 0x6f68, 0x796e, "\000" 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x7953, 0x746e, 0x7068, 0x706f, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6154, 0x676e, 0x006f, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6554, 0x6863, 0x6f6e, "\000" 
+    IDC_COMBOGENRE, 0x403, 18, 0
+0x6554, 0x6863, 0x6f6e, 0x492d, 0x646e, 0x7375, 0x7274, 0x6169, 0x006c, 
+
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6554, 0x7272, 0x726f, "\000" 
+    IDC_COMBOGENRE, 0x403, 13, 0
+0x6854, 0x6172, 0x6873, 0x4d20, 0x7465, 0x6c61, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x6f54, 0x2070, 0x3034, "\000" 
+    IDC_COMBOGENRE, 0x403, 8, 0
+0x7254, 0x6961, 0x656c, 0x0072, 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7254, 0x6e61, 0x6563, "\000" 
+    IDC_COMBOGENRE, 0x403, 7, 0
+0x7254, 0x6269, 0x6c61, "\000" 
+    IDC_COMBOGENRE, 0x403, 9, 0
+0x7254, 0x7069, 0x482d, 0x706f, "\000" 
+    IDC_COMBOGENRE, 0x403, 6, 0
+0x6f56, 0x6163, 0x006c, 
+    0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Toolbar
+//
+
+IDR_TOOLBARMAIN TOOLBAR DISCARDABLE  16, 15
+BEGIN
+    BUTTON      ID_BUTTON32771
+    BUTTON      ID_BUTTON32772
+    BUTTON      ID_BUTTON32773
+    BUTTON      ID_BUTTON32774
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDR_TOOLBARMAIN         BITMAP  DISCARDABLE     "res\\toolbarm.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    IDS_ABOUTBOX            "&About faac_wingui..."
+    IDS_UndefinedShort      "U"
+    IDS_UndefinedLong       "Undefined"
+    IDS_InvalidJob          "Invalid Job"
+    IDS_EncoderJobShort     "Enc"
+    IDS_EncoderJobLong      "Encoder Job"
+    IDS_MidSide             "Mid/Side"
+    IDS_UseLfe              "LFE"
+    IDS_NoListItemSelected  "You must select a list item before this operation can be performed."
+    IDS_JobTypeColumn       "Type"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    IDS_JobInfoColumn       "Job Description"
+    IDS_EncoderGeneralShort "Enc. General"
+    IDS_EncoderId3Short     "ID3"
+    IDS_TabUndefined        "undefined"
+    IDS_EncoderQualityShort "Enc. Quality"
+    IDS_SelectSourceDirDlgCaption "Select Source Directory"
+    IDS_SelectTargetDirDlgCaption "Select Target Directory"
+    IDS_ErrorDuringDirectorySelection 
+                            "Unrecognized error during directory selection."
+    IDS_AllFilesFilter      "All Files (*.*)|*.*"
+    IDS_WavFilesFilter      "Wave Files (*.wav)|*.wav"
+    IDS_EndSourceFileStandardExtension "wav"
+    IDS_ErrorDuringFileSelection "Unrecognized error during file selection."
+    IDS_AacFilesFilter      "Advanced Audio Coding Files (*.aac)|*.aac"
+    IDS_EndTargetFileStandardExtension "aac"
+    IDS_UseTns              "TNS"
+    IDS_UseLtp              "LTP"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    IDS_AacProfileLc        "LC"
+    IDS_AacProfileMain      "Main"
+    IDS_AacProfileSsr       "Ssr"
+    IDS_DetailedEncoderJobDescriptionString 
+                            "%s -> %s\nProfile: %s\nParameters: %d bit/s - %d Hz"
+    IDS_JobListFileFilter   "Job List File (*.jbl)|*.jbl"
+    IDS_JobListStandardExtension "jbl"
+    IDS_ErrorWhileSavingJobList "Error while saving joblist."
+    IDS_SearchParametersInvalid 
+                            "Search Parameters dir=""%s"" filter=""%s"" are invalid."
+    IDS_ErrorProcessingJobSelection 
+                            "Error Processing Job\nDo you want to proceed with remaining jobs in the selection?"
+    IDS_FilterDidntFindFiles 
+                            "The file filter ""%s"" didn't find any files. This might be due to an error in the filter format or because no files exist.\nThe job completes with an error."
+    IDS_ErrorCreatingNestedEncoderJob 
+                            "Could not process nested file ""%s"". Would you like to continue processing remaining files of encoder job ""%s""?"
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "res\faac_wingui.rc2"  // non-Microsoft Visual C++ edited resources
+#include "afxres.rc"         // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
--- /dev/null
+++ b/wingui/faac_winguiDlg.cpp
@@ -1,0 +1,653 @@
+// faac_winguiDlg.cpp : implementation file
+// Author: Torsten Landmann
+//
+///////////////////////////////////
+
+#include "stdafx.h"
+#include "faac_wingui.h"
+#include "faac_winguiDlg.h"
+#include "WindowUtil.h"
+#include "FloatingPropertyDialog.h"
+#include "FileListQueryManager.h"
+#include "FileMaskAssembler.h"
+#include "FileSerializableJobList.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CAboutDlg dialog used for App About
+
+class CAboutDlg : public CDialog
+{
+public:
+	CAboutDlg();
+
+// Dialog Data
+	//{{AFX_DATA(CAboutDlg)
+	enum { IDD = IDD_ABOUTBOX };
+	//}}AFX_DATA
+
+	// ClassWizard generated function overrides
+	//{{AFX_VIRTUAL(CAboutDlg)
+	protected:
+	void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+	//{{AFX_MSG(CAboutDlg)
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+	//{{AFX_DATA_INIT(CAboutDlg)
+	//}}AFX_DATA_INIT
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CAboutDlg)
+	//}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+	//{{AFX_MSG_MAP(CAboutDlg)
+		// No message handlers
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CFaac_winguiDlg dialog
+
+CFaac_winguiDlg::CFaac_winguiDlg(CWnd* pParent /*=NULL*/)
+	: CDialog(CFaac_winguiDlg::IDD, pParent),
+	m_iListCtrlUpdatesCounter(-1),
+	m_poCurrentStandardFile(0)
+{
+	//{{AFX_DATA_INIT(CFaac_winguiDlg)
+	m_bCheckRemoveProcessedJobs = FALSE;
+	//}}AFX_DATA_INIT
+	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+CFaac_winguiDlg::~CFaac_winguiDlg()
+{
+	ReleaseStandardFile();
+}
+
+void CFaac_winguiDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CFaac_winguiDlg)
+	DDX_Control(pDX, IDC_LISTJOBS, m_ctrlListJobs);
+	DDX_Check(pDX, IDC_CHECKREMOVEPROCESSEDJOBS, m_bCheckRemoveProcessedJobs);
+	//}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CFaac_winguiDlg, CDialog)
+	//{{AFX_MSG_MAP(CFaac_winguiDlg)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	ON_BN_CLICKED(IDC_BUTTONADDENCODERJOB, OnButtonAddEncoderJob)
+	ON_NOTIFY(NM_CLICK, IDC_LISTJOBS, OnClickListJobs)
+	ON_NOTIFY(LVN_KEYDOWN, IDC_LISTJOBS, OnKeydownListJobs)
+	ON_BN_CLICKED(IDC_BUTTONDELETEJOBS, OnButtonDeleteJobs)
+	ON_BN_CLICKED(IDC_BUTTONPROCESSSELECTED, OnButtonProcessSelected)
+	ON_NOTIFY(NM_RCLICK, IDC_LISTJOBS, OnRclickListJobs)
+	ON_BN_CLICKED(IDC_BUTTONSAVEJOBLIST, OnButtonSaveJobList)
+	ON_BN_CLICKED(IDC_BUTTONLOADJOBLIST, OnButtonLoadJobList)
+	ON_BN_CLICKED(IDC_BUTTONDUPLICATESELECTED, OnButtonDuplicateSelected)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CFaac_winguiDlg message handlers
+
+BOOL CFaac_winguiDlg::OnInitDialog()
+{
+	CDialog::OnInitDialog();
+
+	// Add "About..." menu item to system menu.
+
+	// IDM_ABOUTBOX must be in the system command range.
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != NULL)
+	{
+		CString strAboutMenu;
+		strAboutMenu.LoadString(IDS_ABOUTBOX);
+		if (!strAboutMenu.IsEmpty())
+		{
+			pSysMenu->AppendMenu(MF_SEPARATOR);
+			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+		}
+	}
+
+	// Set the icon for this dialog.  The framework does this automatically
+	//  when the application's main window is not a dialog
+	SetIcon(m_hIcon, TRUE);			// Set big icon
+	SetIcon(m_hIcon, FALSE);		// Set small icon
+	
+	// TODO: Add extra initialization here
+	{
+		CString oTypeColumn;
+		oTypeColumn.LoadString(IDS_JobTypeColumn);
+		CString oInfoColumn;
+		oInfoColumn.LoadString(IDS_JobInfoColumn);
+		CWindowUtil::AddListCtrlColumn(&m_ctrlListJobs, 0, oTypeColumn, 0.1);
+		CWindowUtil::AddListCtrlColumn(&m_ctrlListJobs, 1, oInfoColumn, 0.895);
+		ListView_SetExtendedListViewStyleEx(m_ctrlListJobs, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
+		ReFillInJobListCtrl();
+
+		// create a floating property window
+		CFloatingPropertyDialog::CreateFloatingPropertiesDummyParentDialog();
+
+		// make sure the floating window is initialized properly
+		OnJobListCtrlSelChange();
+	}
+	
+	return TRUE;  // return TRUE  unless you set the focus to a control
+}
+
+void CFaac_winguiDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialog::OnSysCommand(nID, lParam);
+	}
+}
+
+// If you add a minimize button to your dialog, you will need the code below
+//  to draw the icon.  For MFC applications using the document/view model,
+//  this is automatically done for you by the framework.
+
+void CFaac_winguiDlg::OnPaint() 
+{
+	if (IsIconic())
+	{
+		CPaintDC dc(this); // device context for painting
+
+		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
+
+		// Center icon in client rectangle
+		int cxIcon = GetSystemMetrics(SM_CXICON);
+		int cyIcon = GetSystemMetrics(SM_CYICON);
+		CRect rect;
+		GetClientRect(&rect);
+		int x = (rect.Width() - cxIcon + 1) / 2;
+		int y = (rect.Height() - cyIcon + 1) / 2;
+
+		// Draw the icon
+		dc.DrawIcon(x, y, m_hIcon);
+	}
+	else
+	{
+		CDialog::OnPaint();
+	}
+}
+
+// The system calls this to obtain the cursor to display while the user drags
+//  the minimized window.
+HCURSOR CFaac_winguiDlg::OnQueryDragIcon()
+{
+	return (HCURSOR) m_hIcon;
+}
+
+void CFaac_winguiDlg::ReFillInJobListCtrl(CListCtrlStateSaver *poSelectionStateToUse, bool bSimpleUpdate)
+{
+	if (m_iListCtrlUpdatesCounter>=0)
+	{
+		m_iListCtrlUpdatesCounter++;
+		return;
+	}
+
+	CJobList *poJobList=GetGlobalJobList();
+
+	if (!bSimpleUpdate)
+	{
+		// complete update
+
+		// save the current list selection
+		bool bMustDeleteSelection=false;
+		if (poSelectionStateToUse==0)
+		{
+			poSelectionStateToUse=new CListCtrlStateSaver(&m_ctrlListJobs);
+			bMustDeleteSelection=true;
+		}
+
+		CWindowUtil::DeleteAllListCtrlItems(&m_ctrlListJobs);
+
+		// loop through all jobs and add them to the list control
+		CBListReader oReader(poJobList->BeginReadEx());
+		CJob *poCurrentJob;
+		long lCurrentJobIndex;
+		while ((poCurrentJob=poJobList->GetNextJob(oReader, &lCurrentJobIndex))!=0)
+		{
+			long lCurListItem=CWindowUtil::AddListCtrlItem(&m_ctrlListJobs, poCurrentJob->DescribeJobTypeShort(), lCurrentJobIndex);
+			CWindowUtil::SetListCtrlItem(&m_ctrlListJobs, lCurListItem, 1, poCurrentJob->DescribeJob());
+		}
+
+		// restore the previous list selection
+		poSelectionStateToUse->RestoreState(&m_ctrlListJobs);
+		if (bMustDeleteSelection)
+		{
+			delete poSelectionStateToUse;
+		}
+	}
+	else
+	{
+		// simple update
+		int iNumberOfListCtrlItems=m_ctrlListJobs.GetItemCount();
+
+		for (int iCurItem=0; iCurItem<iNumberOfListCtrlItems; iCurItem++)
+		{
+			long lItemLParam=m_ctrlListJobs.GetItemData(iCurItem);
+
+			// get the job that belongs to the item
+			CJob *poCurJob=poJobList->GetJob(lItemLParam);
+			CWindowUtil::SetListCtrlItem(&m_ctrlListJobs, iCurItem, 1, poCurJob->DescribeJob());
+		}
+	}
+}
+
+void CFaac_winguiDlg::OnJobListCtrlUserAction()
+{
+	// check if the selection has changed
+	TItemList<long> m_oSelectedJobsIds=CWindowUtil::GetAllSelectedListCtrlItemLParams(&m_ctrlListJobs, true);
+
+	if (((m_lLastJobListSelection-m_oSelectedJobsIds).GetNumber()==0) &&
+		((m_oSelectedJobsIds-m_lLastJobListSelection).GetNumber()==0))
+	{
+		// the selection hasn't changed
+		return;
+	}
+
+	// the selection has changed
+	m_iListCtrlUpdatesCounter=0;		// make sure no more than one list update is done
+	m_lLastJobListSelection=m_oSelectedJobsIds;
+	OnJobListCtrlSelChange();
+	m_ctrlListJobs.SetFocus();
+
+	if (m_iListCtrlUpdatesCounter>0)
+	{
+		// need a refill
+		m_iListCtrlUpdatesCounter=-1;
+		ReFillInJobListCtrl();
+	}
+	m_iListCtrlUpdatesCounter=-1;
+}
+
+void CFaac_winguiDlg::OnButtonAddEncoderJob() 
+{
+	CJobList *poJobList=GetGlobalJobList();
+
+	CString oSourceFileExtension;
+	CString oTargetFileExtension;
+	oSourceFileExtension.LoadString(IDS_EndSourceFileStandardExtension);
+	oTargetFileExtension.LoadString(IDS_EndTargetFileStandardExtension);
+
+	// assemble the filter string
+	CString oFilter;
+	{
+		// assemble a list of allowed filters
+		TItemList<int> oFilters;
+		oFilters.AddNewElem(IDS_WavFilesFilter, 1);
+		oFilters.AddNewElem(IDS_AllFilesFilter, 2);
+		oFilter=CFileMaskAssembler::GetFileMask(oFilters);
+	}
+
+	TItemList<CString> oUserSelection=
+		CFileListQueryManager::GetFilePaths(
+		true,
+		&GetGlobalProgramSettings()->m_oDefaultEncSourceDir,
+		oSourceFileExtension,
+		oFilter);
+
+	CBListReader oReader(oUserSelection);
+	CString oCurString;
+	TItemList<long> m_oIndicesOfAddedItems;
+	while (oUserSelection.GetNextElemContent(oReader, oCurString))
+	{
+		// create a new job for the current file
+		CEncoderJob oNewJob;
+		GetGlobalProgramSettings()->ApplyToJob(oNewJob);
+
+		CString oSourceDir(oCurString);
+		CFilePathCalc::MakePath(oSourceDir);
+		CString oSourceFileName;
+		CFilePathCalc::ExtractFileName(oCurString, oSourceFileName);
+		CString oTargetDir(oNewJob.GetFiles().GetTargetFileDirectory());
+		CString oDummy;
+		CString oTargetFileName;
+		CFilePathCalc::SplitFileAndExtension(oSourceFileName, oTargetFileName, oDummy);
+		oTargetFileName+=_T(".")+oTargetFileExtension;
+
+		oNewJob.GetFiles().SetSourceFileDirectory(oSourceDir);
+		oNewJob.GetFiles().SetSourceFileName(oSourceFileName);
+		oNewJob.GetFiles().SetTargetFileDirectory(oTargetDir);
+		oNewJob.GetFiles().SetTargetFileName(oTargetFileName);
+
+		long lNewIndex=poJobList->AddJob(oNewJob);
+		m_oIndicesOfAddedItems.AddNewElem(lNewIndex);
+	}
+
+	
+	CListCtrlStateSaver oSelection;
+	oSelection.SetToSelected(m_oIndicesOfAddedItems);
+	ReFillInJobListCtrl(&oSelection, false);
+
+	m_ctrlListJobs.SetFocus();
+
+	OnJobListCtrlUserAction();
+}
+
+void CFaac_winguiDlg::OnJobListCtrlSelChange(TItemList<long> *poNewSelection)
+{
+	// determine which jobs are selected
+	TItemList<long> m_oSelectedJobsIds;
+	if (poNewSelection!=0)
+	{
+		m_oSelectedJobsIds=*poNewSelection;
+	}
+	else
+	{
+		m_oSelectedJobsIds=CWindowUtil::GetAllSelectedListCtrlItemLParams(&m_ctrlListJobs, true);
+	}
+	CJobList &oJobs=((CFaac_winguiApp*)AfxGetApp())->GetGlobalJobList();
+
+	CPropertiesDummyParentDialog *poPropertiesDialog=((CFaac_winguiApp*)AfxGetApp())->GetGlobalPropertiesDummyParentDialogSingleton();
+	if (poPropertiesDialog==0)
+	{
+		// nothing to do here
+		return;
+	}
+
+	// ask them all which pages they support
+	CBListReader oReader(m_oSelectedJobsIds);
+	long lCurJobIndex;
+	CSupportedPropertyPagesData* poSupportedPages=0;
+	TItemList<CJob*> oSelectedJobs;
+	while (m_oSelectedJobsIds.GetNextElemContent(oReader, lCurJobIndex))
+	{
+		CJob *poCurJob=oJobs.GetJob(lCurJobIndex);
+		if (poSupportedPages==0)
+		{
+			poSupportedPages=new CSupportedPropertyPagesData;
+			*poSupportedPages=poCurJob->GetSupportedPropertyPages();
+		}
+		else
+		{
+			(*poSupportedPages)*=poCurJob->GetSupportedPropertyPages();
+		}
+
+		oSelectedJobs.AddNewElem(poCurJob, lCurJobIndex);
+	}
+
+	if (poSupportedPages==0)
+	{
+		// no list item selected -> no page accepted
+		poSupportedPages=new CSupportedPropertyPagesData;
+	}
+
+	// display the property pages
+	poPropertiesDialog->SetContent(*poSupportedPages, oSelectedJobs, this);
+
+	if (poSupportedPages!=0)
+	{
+		delete poSupportedPages;
+	}
+}
+
+void CFaac_winguiDlg::OnClickListJobs(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	// TODO: Add your control notification handler code here
+	OnJobListCtrlUserAction();
+	
+	*pResult = 0;
+}
+
+void CFaac_winguiDlg::OnKeydownListJobs(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
+	// TODO: Add your control notification handler code here
+
+	OnJobListCtrlUserAction();
+	
+	*pResult = 0;
+}
+
+void CFaac_winguiDlg::OnButtonDeleteJobs() 
+{
+	// TODO: Add your control notification handler code here
+
+	// make sure the property pages won't crash
+	OnJobListCtrlSelChange(&TItemList<long>());
+
+	// delete the selection
+	TItemList<long> oCurSelection(CWindowUtil::GetAllSelectedListCtrlItemLParams(&m_ctrlListJobs, false));
+	GetGlobalJobList()->DeleteElems(oCurSelection);
+
+	// update the list control
+	ReFillInJobListCtrl(0, false);
+}
+
+void CFaac_winguiDlg::OnButtonProcessSelected() 
+{
+	if (!UpdateData(TRUE)) return;
+
+	CJobList *poJobList=GetGlobalJobList();
+
+	TItemList<long> oCurSelection(CWindowUtil::GetAllSelectedListCtrlItemLParams(&m_ctrlListJobs, false));
+
+	TItemList<long> oItemsToRemove;
+
+	CBListReader oReader(oCurSelection);
+	long lCurIndex;
+	bool bContinue=true;
+	while (bContinue && oCurSelection.GetNextElemContent(oReader, lCurIndex))
+	{
+		// get the current job
+		CJob *poJob=poJobList->GetJob(lCurIndex);
+
+		if (!poJob->ProcessJob())
+		{
+			if (AfxMessageBox(IDS_ErrorProcessingJobSelection, MB_YESNO)!=IDYES)
+			{
+				bContinue=false;
+			}
+		}
+		else
+		{
+			// successfully processed
+			if (m_bCheckRemoveProcessedJobs)
+			{
+				int iListItem=CWindowUtil::GetListCtrlItemIdByLParam(&m_ctrlListJobs, lCurIndex);
+				ASSERT(iListItem>=0);		// must exist (logically)
+				m_ctrlListJobs.DeleteItem(iListItem);
+
+				oItemsToRemove.AddNewElem(lCurIndex);
+			}
+		}
+	}
+
+	if (oItemsToRemove.GetNumber()>0)
+	{
+		OnJobListCtrlUserAction();	// this call is very important since the property dialog must be informed about the new selection before the underlying jobs are deleted
+		poJobList->DeleteElems(oItemsToRemove);
+		ReFillInJobListCtrl(0, false);
+
+		// the selection may have changed, so make sure the property
+		// dialog is updated
+		OnJobListCtrlUserAction();
+	}
+}
+
+void CFaac_winguiDlg::OnRclickListJobs(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	// TODO: Add your control notification handler code here
+	OnJobListCtrlUserAction();
+	
+	*pResult = 0;
+}
+
+void CFaac_winguiDlg::OnButtonSaveJobList() 
+{
+	// TODO: Add your control notification handler code here
+
+	//UpdateData(TRUE);
+	// determine the standard file
+	CString *poStandardFile=m_poCurrentStandardFile;
+
+	// assemble the filter string
+	CString oFilter;
+	{
+		// assemble a list of allowed filters
+		TItemList<int> oFilters;
+		oFilters.AddNewElem(IDS_JobListFileFilter, 1);
+		oFilters.AddNewElem(IDS_AllFilesFilter, 2);
+		oFilter=CFileMaskAssembler::GetFileMask(oFilters);
+	}
+
+	// find out the default extension
+	CString oDefaultExt;
+	oDefaultExt.LoadString(IDS_JobListFileFilter);
+
+	CFileDialog oOpenDialog(
+		FALSE,										// file save mode
+		oDefaultExt,								// default extension
+		(poStandardFile!=0 ? *poStandardFile : (LPCTSTR)0),	// default file
+		OFN_HIDEREADONLY,
+		oFilter);
+	if (oOpenDialog.DoModal()==IDOK)
+	{
+		// the file has been selected
+		CFileSerializableJobList oJobList(*GetGlobalJobList());
+		ReleaseStandardFile();
+		m_poCurrentStandardFile=new CString(oOpenDialog.GetPathName());
+		if (!oJobList.SaveToFile(oOpenDialog.GetPathName(), 1))
+		{
+			AfxMessageBox(IDS_ErrorWhileSavingJobList, MB_OK | MB_ICONSTOP);
+		}
+	}
+	else
+	{
+		// user abort or error
+		if (CommDlgExtendedError()!=0)
+		{
+			// an error occured
+			AfxMessageBox(IDS_ErrorDuringFileSelection);
+		}
+	}
+
+	//UpdateData(FALSE);
+}
+
+void CFaac_winguiDlg::OnButtonLoadJobList() 
+{
+	// TODO: Add your control notification handler code here
+	//UpdateData(TRUE);
+	// determine the standard file
+	CString *poStandardFile=m_poCurrentStandardFile;
+
+	// assemble the filter string
+	CString oFilter;
+	{
+		// assemble a list of allowed filters
+		TItemList<int> oFilters;
+		oFilters.AddNewElem(IDS_JobListFileFilter, 1);
+		oFilters.AddNewElem(IDS_AllFilesFilter, 2);
+		oFilter=CFileMaskAssembler::GetFileMask(oFilters);
+	}
+
+	// find out the default extension
+	CString oDefaultExt;
+	oDefaultExt.LoadString(IDS_JobListFileFilter);
+
+	CFileDialog oOpenDialog(
+		TRUE,										// file open mode
+		oDefaultExt,								// default extension
+		(poStandardFile!=0 ? *poStandardFile : (LPCTSTR)0),	// default file
+		OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
+		oFilter);
+	if (oOpenDialog.DoModal()==IDOK)
+	{
+		// the file has been selected
+		CFileSerializableJobList oJobList;
+		ReleaseStandardFile();
+		m_poCurrentStandardFile=new CString(oOpenDialog.GetPathName());
+		if (!oJobList.LoadFromFile(oOpenDialog.GetPathName(), 1))
+		{
+			AfxMessageBox(IDS_ErrorWhileSavingJobList, MB_OK | MB_ICONSTOP);
+		}
+		else
+		{
+			*GetGlobalJobList()=oJobList;
+			ReFillInJobListCtrl(0, false);
+		}
+	}
+	else
+	{
+		// user abort or error
+		if (CommDlgExtendedError()!=0)
+		{
+			// an error occured
+			AfxMessageBox(IDS_ErrorDuringFileSelection);
+		}
+	}
+
+	//UpdateData(FALSE);
+}
+
+void CFaac_winguiDlg::OnButtonDuplicateSelected() 
+{
+	// TODO: Add your control notification handler code here
+
+	CJobList *poJobList=GetGlobalJobList();
+
+	TItemList<long> oCurSelection(CWindowUtil::GetAllSelectedListCtrlItemLParams(&m_ctrlListJobs, true));
+	if (oCurSelection.GetNumber()==0)
+	{
+		// error message corresponds to last argument of the CWindowUtil::GetAll[...] call
+		// currently we don't display an error message if no item is selected
+		return;
+	}
+	TItemList<long> oNewSelection(oCurSelection);
+	//TItemList<long> oNewSelection;		// enable this line instead of the previous one if you don't want to keep the previously selected items selected
+
+	CBListReader oReader(oCurSelection);
+	long lCurIndex;
+	while (oCurSelection.GetNextElemContent(oReader, lCurIndex))
+	{
+		// get the current job
+		CJob *poJob=poJobList->GetJob(lCurIndex);
+		long lNewIndex=poJobList->AddJob(*poJob);
+		oNewSelection.AddNewElem(lNewIndex);
+	}
+
+	// update the list control
+	{
+		CListCtrlStateSaver oNewSelectionState;
+		oNewSelectionState.SetToSelected(oNewSelection);
+		ReFillInJobListCtrl(&oNewSelectionState, false);
+
+		// the selection may have changed, so make sure the property
+		// dialog is updated
+		OnJobListCtrlUserAction();
+	}
+}
--- /dev/null
+++ b/wingui/faac_winguiDlg.h
@@ -1,0 +1,97 @@
+// faac_winguiDlg.h : header file
+// Author: Torsten Landmann
+//
+///////////////////////////////////
+
+#if !defined(AFX_FAAC_WINGUIDLG_H__DFE38E67_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
+#define AFX_FAAC_WINGUIDLG_H__DFE38E67_0E81_11D5_8402_0080C88C25BD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "ListCtrlStateSaver.h"
+#include "JobListUpdatable.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CFaac_winguiDlg dialog
+
+class CFaac_winguiDlg : public CDialog, public CJobListUpdatable
+{
+// Construction
+public:
+	CFaac_winguiDlg(CWnd* pParent = NULL);	// standard constructor
+	virtual ~CFaac_winguiDlg();
+
+// Dialog Data
+	//{{AFX_DATA(CFaac_winguiDlg)
+	enum { IDD = IDD_FAAC_WINGUI_DIALOG };
+	CListCtrl	m_ctrlListJobs;
+	BOOL	m_bCheckRemoveProcessedJobs;
+	//}}AFX_DATA
+
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CFaac_winguiDlg)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
+	//}}AFX_VIRTUAL
+
+	CJobList* GetGlobalJobList()								{ return &((CFaac_winguiApp*)AfxGetApp())->GetGlobalJobList(); }
+	CFaacWinguiProgramSettings* GetGlobalProgramSettings()		{ return &((CFaac_winguiApp*)AfxGetApp())->GetGlobalProgramSettings(); }
+
+// Implementation
+protected:
+	HICON m_hIcon;
+
+	// Generated message map functions
+	//{{AFX_MSG(CFaac_winguiDlg)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+	afx_msg void OnPaint();
+	afx_msg HCURSOR OnQueryDragIcon();
+	afx_msg void OnButtonAddEncoderJob();
+	afx_msg void OnClickListJobs(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnKeydownListJobs(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnButtonDeleteJobs();
+	afx_msg void OnButtonProcessSelected();
+	afx_msg void OnRclickListJobs(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnButtonSaveJobList();
+	afx_msg void OnButtonLoadJobList();
+	afx_msg void OnButtonDuplicateSelected();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+	friend class CPropertiesTabParentDialog;
+
+	// implementation to CJobListUpdatable;
+	// this method refills the job list control;
+	// if no explicit selection state is specified the current
+	// selection is preserved;
+	// bSimpleUpdate may be set to true; if it is, no items are added
+	// or removed and only the info column is updated
+	void ReFillInJobListCtrl(CListCtrlStateSaver *poSelectionStateToUse=0, bool bSimpleUpdate=true);
+
+	TItemList<long> m_lLastJobListSelection;
+	void OnJobListCtrlUserAction();
+
+	// by defining the parameter you can define which new selection is
+	// to be assumed; if 0 is specified the method determines the actual
+	// selection
+	void OnJobListCtrlSelChange(TItemList<long> *poNewSelection=0);
+
+	// this is a very special variable; if it is <0 it affects nothing;
+	// if, however, it is >=0 it is incremented each time a call to
+	// ReFillInJobListCtrl()) is made; in this case the call is ignored
+	// (no list control operation is done)
+	int m_iListCtrlUpdatesCounter;
+
+	// when this variable is !=0 it contains the current file to
+	// propose when file interaction is done
+	CString *m_poCurrentStandardFile;
+	void ReleaseStandardFile()			{ if (m_poCurrentStandardFile!=0) delete m_poCurrentStandardFile; }
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_FAAC_WINGUIDLG_H__DFE38E67_0E81_11D5_8402_0080C88C25BD__INCLUDED_)
--- /dev/null
+++ b/wingui/listobj.h
@@ -1,0 +1,266 @@
+// list class
+// Copyright 1999, Torsten Landmann
+// successfully compiled and tested under MSVC 6.0
+//
+// revised 2001 by Torsten Landmann
+// successfully compiled and tested under MSVC 6.0
+//
+//////////////////////////////////////////////////////
+
+#ifndef __Listobj_h__
+#define __Listobj_h__
+
+#include "stdafx.h"
+
+typedef signed long TBListErr;
+
+const long iMaxNumberOfCBListItems=100000000;
+const TBListErr siListNoErr=0;
+const TBListErr siListErr=-1;		// error codes
+const TBListErr siListSavErr=-2;
+const long lMaxNumRS=256;			// maximum number of reading sessions
+
+// public use of this type is obsolete; use CBListReader instead
+typedef signed long HRead;
+
+// objects of this class can be compared with a moving pointer to
+// a certain element in a list; it's used during sequential reading
+// of lists;
+// this class wraps HRead and automatically finishes the read
+// session once an instance becomes destructed
+class CBListReader
+{
+	friend class CBList;
+
+public:
+	// simplest way to get a reader
+	CBListReader(CBList &oList);
+
+	// copy constructor
+	CBListReader(const CBListReader &oSource);
+
+	virtual ~CBListReader();
+
+	// makes this class compatible with former HRead
+	operator HRead() const	{ return m_hRead; }
+
+	CBListReader& operator=(const CBListReader &oRight);
+
+	void EndReaderSession()		{ AbandonCurrentContent(); }
+
+protected:
+	CBListReader(CBList *poList, HRead hRead);
+
+private:
+	CBList *m_poList;
+	HRead m_hRead;
+	int *m_piUsageStack;
+
+	void AbandonCurrentContent();
+};
+
+enum ESortMode
+{
+	eAscending,
+	eDescending
+};
+
+class CBList;
+
+class CBBaseElem
+{
+	friend class CBList;
+
+public:
+	class CBBaseElem *GetNext() const { return pNext; }
+	class CBBaseElem *GetPrevious() const { return pPrevious; }
+	long GetIndex() const { return lIndex; }
+	class CBList *GetParentList() const { return pParentList; }
+
+	// -1: parameter element is higher
+	//  0: same
+	//  1: parameter element is smaller
+	// in this base class elements are sorted by their index
+	virtual signed long IsHigher(class CBBaseElem *pElem);
+
+protected:
+	CBBaseElem();     // only allowed for derivations and for CBList (=friend)
+	virtual ~CBBaseElem();
+
+	// override these members if you want to put your list
+	// to a stream or retreive it from there;
+	// do never forget to call these ones if you override them
+	virtual bool PutToArchive(CArchive &oArchive, long lSaveParams) const;
+	virtual bool GetFromArchive(CArchive &oArchive, long lLoadParams);
+private:
+	long lIndex;
+	class CBBaseElem *pNext, *pPrevious;
+	class CBList *pParentList;
+};
+
+typedef CBBaseElem *PBBaseElem;
+
+class CBList
+{
+public:
+	CBList();
+	virtual ~CBList();
+	TBListErr DeleteAll();
+
+	TBListErr DeleteElem(long lIndex);
+	bool Exists(long lIndex) const;
+
+	// number of elements; error: siListErr
+	signed long GetNumber() const;
+		
+	// error: 0
+	PBBaseElem GetElem(long lIndex) const;
+
+	// returns the element that is at the 0-based position
+	// that's given by parameter; always count from first Element
+	// on; error: 0
+	PBBaseElem GetPos(long lPos) const;
+		
+	// finds out the position of the element with the specified
+	// index; siListErr in case of errors
+	long GetIndexPos(long lIndex) const;
+		
+	// sort using method "IsHigher()"
+		// error: siListErr
+	TBListErr Sort(ESortMode eSortMode=eAscending);
+		
+	// returns old state
+	bool SetSortBeforeReading(bool bNewValue);
+		
+
+	PBBaseElem GetFirst()			{ return pFirst; }
+	PBBaseElem GetLast()			{ return pLast; }
+
+
+	// *******************************************
+	// using the following methods you get the elements in the order
+	// in which they are in the list
+	// if a call of SetSortBeforeReading(true) has taken place, the
+	// list is sorted beforehands;
+	// as long as reading sessions are open the list is locked
+	// and no data can be changed!! this includes that you cannot
+	// sort or change the sort-before-reading-state
+
+	// initializes a new reading session
+	// returns a handle to this reading session
+	// list is sorted if set using method "setsortbeforereading()"
+	// error: siListErr
+	// maximum number of reading sessions is limited by constant
+	// iMaxNumRS
+	HRead BeginRead();		// obsolete; use CBListReader BeginReadEx() instead!
+	CBListReader BeginReadEx();
+		
+
+	// error: 0
+	PBBaseElem ReadElem(HRead hRead);
+
+	// end reading session designated by hRead
+	TBListErr EndRead(HRead hRead);
+
+	// usually you do not need to call this method; you have the choice to
+	// call oReader.EndReaderSession() instead or not explicitely ending the
+	// sessiion at all;
+	// explicitely ending the session might be useful if you know that the
+	// parent list will be destructed before the reader;
+	TBListErr EndRead(CBListReader &oReader);
+
+	// performs calls the OnMapHandle() member exactly one time for
+	// each of the list element in the order in which they are in
+	// the list; if SetSortBeforeReading(true) has been done the list is
+	// sorted;
+	// the return value is true if each call of OnMapHandle() returned
+	// true, false otherwise;
+	// note that the first sentence in this comment isn't quite correct;
+	// if OnMapHandle() returns false, the operation is not continued
+	bool Map(long lTask, long lHint);
+
+
+	// puts the whole list with all its data to a stream
+	// or retreives it from there
+	TBListErr PutToArchive(CArchive &oArchive, long lSaveParams=-1) const;
+	TBListErr GetFromArchive(CArchive &oArchive, long lLoadParams=-1);
+
+	// self explaining
+	TBListErr SaveToFile(const char *lpszFileName, long lSaveParams=-1);
+	TBListErr LoadFromFile(const char *lpszFileName, long lLoadParams=-1);
+
+protected:
+	// properly inserts a new element in the list
+	// a pointer to it is given back;
+	// the new element has an index between (including)
+	// 1 and iMaxNumberOfCBListItems
+	PBBaseElem Add();
+	// this version tries to give the given index
+	// to the new element, if possible; negative values and 0
+	// are NOT used!
+	PBBaseElem Add(long lDesiredIndex);
+
+	// this member works together with the Map() member; look there for
+	// further information
+	virtual bool OnMapHandle(CBBaseElem *poElem, long lTask, long lHint);
+
+	// the following method must be overriden by every
+	// subclass returning an element of the type of the particular
+	// subclass of PBBaseElem
+	virtual PBBaseElem CreateElem()=0;
+
+	// this method is called immediately before and element is
+	// to be deleted via delete;
+	// it does nothing here but you may override it to free
+	// other variables the content is referring to
+	// !!! EXTREMELY IMPORTANT: !!!
+	// if you override this method you MUST call
+	// DeleteAll() in the destructor of your class
+	virtual void OnPreDeleteItem(PBBaseElem poElem);
+
+private:
+	// content of elements is not changed; their position in the list
+	// is exchanged; error: siListErr
+	TBListErr Exchange(PBBaseElem pOne, PBBaseElem pTwo);
+		
+	// Performs a bubble sort on the given interval
+	// note that there is no validation checking (e.g. if
+	// pLeft is really left of pRight)
+	// (sorting algorithms like quicksort or heapsort are not
+	// useful on lists. They work only good and fast on arrays,
+	// so I decided to implement bubble sort)
+	// pLeft and pRight refer to the pointers; a pNext-Pointer
+	// always points right, so by only using pNext-Pointers on
+	// pLeft you MUST reach pRight at some time; otherwise
+	// the programm will be going to crash with an access
+	// violation
+	// return value siListErr: error (e.g. no element in list)
+	TBListErr DoBubbleSort(PBBaseElem pLeft, PBBaseElem pRight, ESortMode eSortMode);
+		
+
+	// finds the lowest available index that can be given to
+	// a new element; used by method "Add()"
+	signed long GetSmallestIndex();
+
+	// finds an open reading position; used by method BeginRead()
+	signed long FindOpenReadPos() const;
+
+	// finds the lowest element in the list; used by "DoBubbleSort()"
+	PBBaseElem FindLowest(PBBaseElem pBeginFrom, PBBaseElem pGoTo, ESortMode eSortMode);
+
+	PBBaseElem pFirst, pLast;
+
+	PBBaseElem pReadPos[256];
+	bool bReadEntryUsed[256];
+	long lNumOfOpenReadingSessions;
+
+	bool SortBeforeReading;
+
+	// saves the last index number that has been given
+	// to a new element
+	long lCurrentIndex;
+	     
+};
+typedef CBList *PBList;
+
+#endif // #ifndef __Listobj_h__
\ No newline at end of file
binary files /dev/null b/wingui/res/faac_wingui.ico differ
--- /dev/null
+++ b/wingui/res/faac_wingui.rc2
@@ -1,0 +1,13 @@
+//
+// FAAC_WINGUI.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+	#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
binary files /dev/null b/wingui/res/toolbarm.bmp differ
--- /dev/null
+++ b/wingui/resource.h
@@ -1,0 +1,116 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by faac_wingui.rc
+//
+#define IDM_ABOUTBOX                    0x0010
+#define IDD_ABOUTBOX                    100
+#define IDS_ABOUTBOX                    101
+#define IDD_FAAC_WINGUI_DIALOG          102
+#define IDS_UndefinedShort              102
+#define IDS_UndefinedLong               103
+#define IDS_InvalidJob                  104
+#define IDS_EncoderJobShort             105
+#define IDS_EncoderJobLong              106
+#define IDS_MidSide                     107
+#define IDS_UseLfe                      109
+#define IDS_NoListItemSelected          110
+#define IDS_JobTypeColumn               111
+#define IDS_JobInfoColumn               112
+#define IDS_EncoderGeneralShort         113
+#define IDS_EncoderId3Short             114
+#define IDS_TabUndefined                115
+#define IDS_EncoderQualityShort         116
+#define IDS_SelectSourceDirDlgCaption   117
+#define IDS_SelectTargetDirDlgCaption   118
+#define IDS_ErrorDuringDirectorySelection 119
+#define IDS_AllFilesFilter              120
+#define IDS_WavFilesFilter              121
+#define IDS_EndSourceFileStandardExtension 122
+#define IDS_ErrorDuringFileSelection    123
+#define IDS_AacFilesFilter              124
+#define IDS_EndTargetFileStandardExtension 125
+#define IDS_UseTns                      126
+#define IDS_UseLtp                      127
+#define IDR_MAINFRAME                   128
+#define IDS_AacProfileLc                128
+#define IDD_PROPERTIESTABPARENTDIALOG   129
+#define IDS_AacProfileMain              129
+#define IDD_ENCODERGENERALPAGEDIALOG    130
+#define IDS_AacProfileSsr               130
+#define IDD_FLOATINGPROPERTYDIALOG      131
+#define IDS_DetailedEncoderJobDescriptionString 131
+#define IDD_PROPERTIESDUMMYPARENTDIALOG 132
+#define IDS_JobListFileFilter           132
+#define IDD_ENCODERID3PAGEDIALOG        133
+#define IDS_JobListStandardExtension    133
+#define IDD_ENCODERQUALITYPAGEDIALOG    134
+#define IDS_ErrorWhileSavingJobList     134
+#define IDS_SearchParametersInvalid     135
+#define IDD_PROCESSJOBSTATUSDIALOG      136
+#define IDS_ErrorProcessingJobSelection 136
+#define IDR_TOOLBARMAIN                 137
+#define IDS_FilterDidntFindFiles        137
+#define IDS_ErrorCreatingNestedEncoderJob 138
+#define IDC_LISTJOBS                    1000
+#define IDC_BUTTONADDENCODERJOB         1001
+#define IDC_TAB1                        1002
+#define IDC_LABELNOSELECTION            1004
+#define IDC_EDITSOURCEDIR               1006
+#define IDC_BUTTONBROWSESOURCEDIR       1007
+#define IDC_EDITTARGETDIR               1008
+#define IDC_BUTTONBROWSETARGETDIR       1009
+#define IDC_EDITSOURCEFILE              1010
+#define IDC_BUTTONBROWSESOURCEFILE      1011
+#define IDC_EDITTARGETFILE              1012
+#define IDC_BUTTONBROWSETARGETFILE      1013
+#define IDC_EDITBITRATE                 1014
+#define IDC_EDITBANDWIDTH               1015
+#define IDC_CHECKMIDSIDE                1016
+#define IDC_CHECKUSELFE                 1017
+#define IDC_LABELDEBUGTAG               1018
+#define IDC_EDITARTIST                  1019
+#define IDC_EDITTRACK                   1020
+#define IDC_EDITTITLE                   1021
+#define IDC_EDITURL                     1023
+#define IDC_EDITALBUM                   1024
+#define IDC_EDITYEAR                    1025
+#define IDC_EDITCOMPOSER                1026
+#define IDC_EDITORIGINALARTIST          1027
+#define IDC_CHECKCOPYRIGHT              1029
+#define IDC_EDITCOMMENT                 1030
+#define IDC_EDITENCODEDBY               1031
+#define IDC_COMBOGENRE                  1032
+#define IDC_BUTTONDELETEJOBS            1033
+#define IDC_BUTTONPROCESSSELECTED       1034
+#define IDC_LABELTOPSTATUSTEXT          1035
+#define IDC_PROGRESS1                   1036
+#define IDC_LABELBOTTOMSTATUSTEXT       1037
+#define IDC_BUTTONABORT                 1038
+#define IDC_BUTTONPAUSE                 1039
+#define IDC_BUTTONCONTINUE              1041
+#define IDC_CHECKREMOVEPROCESSEDJOBS    1042
+#define IDC_CHECKUSETNS                 1043
+#define IDC_CHECKUSELTP                 1044
+#define IDC_RADIOAACPROFILELC           1045
+#define IDC_RADIOAACPROFILEMAIN         1046
+#define IDC_RADIOAACPROFILESSR          1047
+#define IDC_BUTTON1                     1048
+#define IDC_BUTTONSAVEJOBLIST           1049
+#define IDC_BUTTONLOADJOBLIST           1050
+#define IDC_BUTTONDUPLICATESELECTED     1051
+#define IDC_CHECKRECURSIVE              1052
+#define ID_BUTTON32771                  32771
+#define ID_BUTTON32772                  32772
+#define ID_BUTTON32773                  32773
+#define ID_BUTTON32774                  32774
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        139
+#define _APS_NEXT_COMMAND_VALUE         32775
+#define _APS_NEXT_CONTROL_VALUE         1053
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif