DOCUMENT.CPP

// Document.cpp: implementation of the CDocument class. 
//
//////////////////////////////////////////////////////////////////////


#define _WIN32_WINNT 0x0400
#define _ATL_APARTMENT_THREADED

#include "vcproj.h"
extern TCHAR g_szStart[];
extern TCHAR g_szEnd[];
extern TCHAR g_szAll[];
extern char szAppName[];
LPTSTR GetStringRes (int id);

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


CDocument::~CDocument()
{

}


BOOL CDocument::Initialize(HWND hwndDoc)
{
m_hWnd = hwndDoc;
return m_ClipList.Initialize(hwndDoc);
}

void inline WriteLong(IStream *pStream, long val)
{
pStream->Write(&val, sizeof(val), NULL);
}

long inline ReadLong(IStream *pStream)
{
long val;
pStream->Read(&val, sizeof(val), NULL);
return val;
}

void CDocument::ResetContents(void)
{
m_TargetFileName.Empty();
m_VideoCodecDisplayName.Empty();
m_AudioCodecDisplayName.Empty();
m_ClipList.ResetContents();
}

BOOL CDocument::ReadFromStream(IStream * pStream)
{
ResetContents();

m_TargetFileName.ReadFromStream(pStream);
m_VideoCodecDisplayName.ReadFromStream(pStream);
m_AudioCodecDisplayName.ReadFromStream(pStream);
m_Height = ReadLong(pStream);
m_Width = ReadLong(pStream);
m_PixelDepth = ReadLong(pStream);

m_ClipList.ReadFromStream(pStream);
return TRUE;
}

BOOL CDocument::WriteToStream(IStream * pStream)
{
m_TargetFileName.WriteToStream(pStream);
m_VideoCodecDisplayName.WriteToStream(pStream);
m_AudioCodecDisplayName.WriteToStream(pStream);
WriteLong(pStream, m_Height);
WriteLong(pStream, m_Width);
WriteLong(pStream, m_PixelDepth);
m_ClipList.WriteToStream(pStream);
return TRUE;
}


BOOL CDocument::NewClip()
{
CClip *pClip;
int i = m_ClipList.CurSelClipIndex();
if (i < 0) { // Nothing selected = -1; Add to end.
i = m_ClipList.NumClips();
}
m_ClipList.AddClip(i, &pClip);
if (pClip->DoSettingsDialog(m_hWnd)) {
m_ClipList.UpdateClipView(i);
MarkDirty();
} else {
m_ClipList.DeleteClip(i);
}
return TRUE;
}

BOOL CDocument::DeleteClip()
{
int i = m_ClipList.CurSelClipIndex();
if (i >= 0) {
m_ClipList.DeleteClip(i);
MarkDirty();
}
return TRUE;
}

BOOL CDocument::EditClip()
{
int i = m_ClipList.CurSelClipIndex();
if (i >= 0) {
CClip *pClip = m_ClipList.GetClip(i);
if (pClip->DoSettingsDialog(m_hWnd)) {
m_ClipList.UpdateClipView(i);
MarkDirty();
}
}
return TRUE;
}

extern HINSTANCE hInst;



void InitOpenFileName(HWND hWnd, OPENFILENAME& OpenFileName, TCHAR * pszFileName)
{
OpenFileName.lStructSize = sizeof(OPENFILENAME);
OpenFileName.hwndOwner = hWnd;
OpenFileName.hInstance = hInst;
OpenFileName.lpstrFilter = NULL;
OpenFileName.lpstrCustomFilter = NULL;
OpenFileName.nMaxCustFilter = 0;
OpenFileName.nFilterIndex = 0;
OpenFileName.lpstrFile = pszFileName;
OpenFileName.nMaxFile = MAX_PATH;
OpenFileName.lpstrFileTitle = NULL;
OpenFileName.nMaxFileTitle = 0;
OpenFileName.lpstrInitialDir = NULL;
OpenFileName.lpstrTitle = NULL;
OpenFileName.nFileOffset = 0;
OpenFileName.nFileExtension = 0;
OpenFileName.lpstrDefExt = NULL;
OpenFileName.lCustData = 0;
OpenFileName.lpfnHook = NULL;
OpenFileName.lpTemplateName = NULL;
OpenFileName.Flags = OFN_SHOWHELP;
}


BOOL CDocument::OpenFile()
{
USES_CONVERSION;
BOOL bWorked = FALSE;
TCHAR szFile[MAX_PATH];

szFile[0] = 0;
OPENFILENAME OpenFileName;
InitOpenFileName(m_hWnd, OpenFileName, szFile);

if (GetOpenFileName(&OpenFileName)) {
CComBSTR szTryThisName(T2BSTR(szFile));
CComPtr<IStorage> pStorage;
HRESULT hr = StgOpenStorage(szTryThisName, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0,
&pStorage);
if (SUCCEEDED(hr)) {
CComPtr <IStream> pStream;
hr = pStorage->OpenStream(L"VidClip", NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream);
if (SUCCEEDED(hr)) {
bWorked = ReadFromStream(pStream);
if (bWorked) {
m_DocumentFileName = szTryThisName;
}
}
}
}
return bWorked;
}


BOOL CDocument::SaveAsFile(bool bShowDialog)
{
USES_CONVERSION;
BOOL bWorked = FALSE;
TCHAR szFile[MAX_PATH];

if (!m_DocumentFileName || bShowDialog) {
OPENFILENAME OpenFileName;
InitOpenFileName(m_hWnd, OpenFileName, szFile);
if (m_DocumentFileName) {
lstrcpy(szFile, OLE2T(m_DocumentFileName));
} else {
szFile[0] = 0;
}
if (!GetSaveFileName(&OpenFileName)) {
return FALSE;
}
m_DocumentFileName = T2OLE(szFile);
}

CComPtr<IStorage> pStorage;
HRESULT hr = StgCreateDocfile(m_DocumentFileName,
STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0,
&pStorage);
if (SUCCEEDED(hr)) {
CComPtr<IStream> pStream;
hr = pStorage->CreateStream(L"VidClip", STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream);
if (SUCCEEDED(hr)) {
bWorked = WriteToStream(pStream);
}
}
return bWorked;
}



//////////////////// CLIPS


void inline WriteStreamTime(IStream *pStream, STREAM_TIME val)
{
pStream->Write(&val, sizeof(val), NULL);
}

STREAM_TIME inline ReadStreamTime(IStream *pStream)
{
STREAM_TIME val;
pStream->Read(&val, sizeof(val), NULL);
return val;
}



BOOL CClip::WriteToStream(IStream *pStream)
{
m_FileName.WriteToStream(pStream);
WriteStreamTime(pStream, m_stStart);
WriteStreamTime(pStream, m_stEnd);
return TRUE;
}

BOOL CClip::ReadFromStream(IStream *pStream)
{
m_FileName.Empty();
m_FileName.ReadFromStream(pStream);
m_stStart = ReadStreamTime(pStream);
m_stEnd = ReadStreamTime(pStream);
return TRUE;
}

//////////////////// CLIP LIST

void CClipList::InsertCol(int iColNum, TCHAR * pszColHeader, int Width)
{
LV_COLUMN col = {LVCF_FMT | LVCF_WIDTH | LVCF_TEXT, LVCFMT_LEFT, Width, pszColHeader, 0, 0};
ListView_InsertColumn(m_hLV, iColNum, &col);
}

BOOL CClipList::Initialize(HWND hwndParent)
{
m_hLV = CreateWindowEx(0, WC_LISTVIEW, "ClipList", WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | LVS_REPORT | LVS_SINGLESEL,
0, 0, 0, 0, hwndParent, (HMENU)1, hInst, NULL);


InsertCol(0, "File Name", 400);
InsertCol(1, "Start", 100);
InsertCol(2, "Stop", 100);
return TRUE;
}


int CClipList::NumClips(void)
{
return ListView_GetItemCount(m_hLV);
}

int CClipList::CurSelClipIndex(void)
{
return ListView_GetNextItem(m_hLV, -1, LVNI_ALL | LVNI_SELECTED);
}

CClip * CClipList::GetClip(int i)
{
LV_ITEM lvi = {LVIF_PARAM, i, 0};
ListView_GetItem(m_hLV, &lvi);
return (CClip *)(lvi.lParam);
}

BOOL CClipList::AddClip(int i, CClip **ppClip)
{
CClip *pNewClip = new CClip();
if (!pNewClip) {
return FALSE;
}
LV_ITEM lvi = {LVIF_PARAM | LVIF_TEXT, i, 0};
lvi.pszText = "<New Clip>";
lvi.lParam = (LPARAM)pNewClip;
ListView_InsertItem(m_hLV, &lvi);
lvi.pszText = "----";
lvi.mask = LVIF_TEXT;
lvi.iSubItem = 1;
ListView_SetItem(m_hLV, &lvi);
lvi.iSubItem = 2;
ListView_SetItem(m_hLV, &lvi);
*ppClip = pNewClip;

return TRUE;
}

void CClipList::DeleteClip(int i)
{
delete GetClip(i);
ListView_DeleteItem(m_hLV, i);
}


void CClipList::UpdateClipView(int i)
{
USES_CONVERSION;
CClip *pClip = GetClip(i);

LV_ITEM lvi = {LVIF_TEXT, i, 0};
lvi.pszText = OLE2T(pClip->m_FileName);
ListView_SetItem(m_hLV, &lvi);


if (pClip->m_stStart == 0 && pClip->m_stEnd == 0) {
lvi.iSubItem = 1;
lvi.pszText = g_szAll;
ListView_SetItem(m_hLV, &lvi);
lvi.iSubItem = 2;
lvi.pszText = _T("");
ListView_SetItem(m_hLV, &lvi);
} else {
TCHAR s[20];
long Second = (long)(pClip->m_stStart / (STREAM_TIME)10000000);
wsprintf(s, _T("%li"), Second);
lvi.iSubItem = 1;
lvi.pszText = pClip->m_stStart == 0 ? g_szStart : s;
ListView_SetItem(m_hLV, &lvi);

Second = (long)(pClip->m_stEnd / (STREAM_TIME)10000000);
wsprintf(s, _T("%li"), Second);
lvi.iSubItem = 2;
lvi.pszText = pClip->m_stEnd == 0 ? g_szEnd : s;
ListView_SetItem(m_hLV, &lvi);
}
}



BOOL CClipList::WriteToStream(IStream *pStream)
{
int lNumClips = NumClips();
WriteLong(pStream, lNumClips);
for (int i = 0; i < lNumClips; i++) {
GetClip(i)->WriteToStream(pStream);
}
return TRUE;

}

void CClipList::ResetContents()
{
int lNumClips = NumClips();
for (int i = 0; i < lNumClips; i++) {
delete GetClip(i);
}
ListView_DeleteAllItems(m_hLV);
}

BOOL CClipList::ReadFromStream(IStream *pStream)
{
ResetContents();

int lNumClips = ReadLong(pStream);
for (int i = 0; i < lNumClips; i++) {
CClip *pClip;
AddClip(i, &pClip);
pClip->ReadFromStream(pStream);
UpdateClipView(i);
}
return TRUE;
}

void CClipList::SetSize(int Height, int Width)
{
MoveWindow(m_hLV, 0, 0, Height, Width, TRUE);
}


LRESULT CALLBACK ClipSettingsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);


BOOL CClip::DoSettingsDialog(HWND hwndParent)
{
return DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CLIP), hwndParent, (DLGPROC)ClipSettingsDlg, (LPARAM)this);
}


void inline SetEditSeconds(HWND hDlg, int ID, STREAM_TIME st)
{
long Second = (long)(st / (STREAM_TIME)10000000);
TCHAR s[20];
wsprintf(s, _T("%li"), Second);
SendDlgItemMessage(hDlg, ID, WM_SETTEXT, 0, (LPARAM)s);
}


void CClip::InitDialog(HWND hDlg)
{
USES_CONVERSION;
CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
SendDlgItemMessage(hDlg, IDC_EDIT_FILENAME, WM_SETTEXT, 0, (LPARAM)W2T(m_FileName));
SetEditSeconds(hDlg, IDC_EDIT_START, m_stStart);
SetEditSeconds(hDlg, IDC_EDIT_END, m_stEnd);
}


bool CClip::CleanUpDialog(HWND hDlg, bool bSaveSettings)
{
bool bWorked = true;
if (bSaveSettings) {
TCHAR szEditContents[MAX_PATH];
TCHAR *pUnused;
STREAM_TIME stStart, stEnd;

SendDlgItemMessage(hDlg, IDC_EDIT_START, WM_GETTEXT, sizeof(szEditContents) / sizeof(TCHAR), (LPARAM)szEditContents);
stStart = (STREAM_TIME)strtol(szEditContents, &pUnused, 10) * (STREAM_TIME)10000000;

SendDlgItemMessage(hDlg, IDC_EDIT_END, WM_GETTEXT, sizeof(szEditContents) / sizeof(TCHAR), (LPARAM)szEditContents);
stEnd = (STREAM_TIME)strtol(szEditContents, &pUnused, 10) * (STREAM_TIME)10000000;

SendDlgItemMessage(hDlg, IDC_EDIT_FILENAME, WM_GETTEXT, sizeof(szEditContents) / sizeof(TCHAR), (LPARAM)szEditContents);

if (stStart <= stEnd || stEnd == 0) {
HANDLE hTest = CreateFile(szEditContents, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hTest == INVALID_HANDLE_VALUE) {
bWorked = false;
MessageBox(hDlg, GetStringRes(IDS_FILE_DOES_NOT_EXIST), szAppName, MB_OK);
} else {
CloseHandle(hTest);
m_FileName = szEditContents;
m_stStart = stStart;
m_stEnd = stEnd;
}
} else {
bWorked = false;
MessageBox(hDlg, GetStringRes(IDS_INVALID_TIMES), szAppName, MB_OK);
}
}
return bWorked;
}

//
// FUNCTION: ClipSettings(HWND, unsigned, WORD, LONG)
//
//
// MESSAGES:
//
// WM_INITDIALOG - initialize dialog box
// WM_COMMAND - Input received
//
//

LRESULT CALLBACK ClipSettingsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
CClip *pClip = (CClip *)GetWindowLong(hDlg, DWL_USER);
switch (message) {
case WM_INITDIALOG:
pClip = (CClip *)lParam;
SetWindowLong(hDlg, DWL_USER, lParam);
pClip->InitDialog(hDlg);
return TRUE;



case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
if (pClip->CleanUpDialog(hDlg, LOWORD(wParam) == IDOK)) {
EndDialog(hDlg, LOWORD(wParam) == IDOK);
}
return TRUE;
}
if (LOWORD(wParam) == IDC_BUTTON_BROWSE) {
TCHAR szFile[MAX_PATH];
szFile[0] = 0;
OPENFILENAME OpenFileName;
InitOpenFileName(hDlg, OpenFileName, szFile);
if (GetOpenFileName(&OpenFileName)) {
SendDlgItemMessage(hDlg, IDC_EDIT_FILENAME, WM_SETTEXT, 0, (LPARAM)szFile);
}
return TRUE;
}
break;
}

return FALSE;
}