|
|
//****************************************************************************
//
// Module: MMSE.DLL
// File: mmse.c
// Content: This file contains the moudle initialization.
// History:
// 06/1994 -By- Vij Rajarajan (VijR)
//
// Copyright (c) Microsoft Corporation 1991-1994
//
//****************************************************************************
#define INITGUID
#include "mmcpl.h"
#include <coguid.h>
#include <oleguid.h>
#include <shlguid.h>
#include <mmddk.h>
#include <mmreg.h>
#include <msacm.h>
#include <msacmdrv.h>
#include <vfw.h>
#include <shlobj.h>
#undef INITGUID
#include <shlobjp.h>
//****************************************************************************
// Initialize GUIDs (should be done only and at-least once per DLL/EXE)
//****************************************************************************
#include <commctrl.h>
#include <prsht.h>
#include "draw.h"
#include "utils.h"
#include "medhelp.h"
/*
*************************************************************** * Typedefs *************************************************************** */ typedef HWND (VFWAPIV * FN_MCIWNDCREATE)();
//---------------------------------------------------------------------------
// MMPSH class
//---------------------------------------------------------------------------
typedef struct _mmInfoList MMINFOLIST; typedef MMINFOLIST * PMMINFOLIST;
typedef struct _mmInfoList { TCHAR szInfoDesc[80]; LPSTR pszInfo; FOURCC ckid; PMMINFOLIST pNext; };
// mmse class structure. This is used for instances of
// IPersistFolder, IShellFolder, and IShellDetails.
typedef struct _mmpsh { // We use the pf also as our IUnknown interface
IShellExtInit sei; // 1st base class
IShellPropSheetExt pse; // 2nd base class
LPDATAOBJECT pdtobj; UINT cRef; // reference count
LPTSTR pszFileObj; UINT uLen; short iMediaType; PVOID pAudioFormatInfo; PVOID pVideoFormatInfo; HPALETTE hPal; HBITMAP hDispBMP; HICON hIcon; PMMINFOLIST pInfoList; } mmpsh, * PMMPSH;
/*
*************************************************************** * Defines *************************************************************** */ #define MIDICOPYRIGHTSTR pAudioFormatInfo
#define MIDISEQNAMESTR pVideoFormatInfo
#define MAXNUMSTREAMS 50
/*
*************************************************************** * File Globals *************************************************************** */ int g_cRef = 0;
SZCODE cszWavExt[] = TEXT(".WAV"); SZCODE cszMIDIExt[] = TEXT(".MID"); SZCODE cszRMIExt[] = TEXT(".RMI"); SZCODE cszAVIExt[] = TEXT(".AVI"); SZCODE cszASFExt[] = TEXT(".ASF"); SZCODE cszSlash[] = TEXT("\\");
static SZCODE aszMIDIDev[] = TEXT("sequencer");
static TCHAR szDetailsTab[64]; static TCHAR szPreviewTab[64];
/*
*************************************************************** * Prototypes *************************************************************** */ LPTSTR PASCAL NiceName(LPTSTR sz, BOOL fNukePath);
/*
*************************************************************** *************************************************************** */
DWORD mmpshGetFileSize(LPTSTR szFile) { HANDLE hFile; OFSTRUCT of; DWORD dwSize = 0;
hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE != hFile) { dwSize = GetFileSize(hFile, NULL); CloseHandle(hFile); } return dwSize; }
STATIC void ReleaseInfoList(PMMPSH pmmpsh) { PMMINFOLIST pCur;
pCur = pmmpsh->pInfoList; while (pCur) { PMMINFOLIST pTmp;
pTmp = pCur; pCur = pCur->pNext; LocalFree((HLOCAL)pTmp->pszInfo); LocalFree((HLOCAL)pTmp); } pmmpsh->pInfoList = NULL; }
STATIC BOOL AddInfoToList(PMMPSH pmmpsh, LPSTR pInfo, FOURCC ckid) { PMMINFOLIST pCur; int idStr;
for (pCur = pmmpsh->pInfoList; pCur && pCur->pNext ; pCur = pCur->pNext) if (pCur->ckid == ckid) return TRUE;
if (!pCur) { pCur = pmmpsh->pInfoList = (PMMINFOLIST)LocalAlloc(LPTR, sizeof(MMINFOLIST)); } else { pCur->pNext = (PMMINFOLIST)LocalAlloc(LPTR, sizeof(MMINFOLIST)); pCur = pCur->pNext; } if (!pCur) return FALSE;
pCur->ckid = ckid; pCur->pszInfo = pInfo;
switch (ckid) { case FOURCC_INAM: idStr = IDS_FOURCC_INAM; break; case FOURCC_ICOP: idStr = IDS_FOURCC_ICOP; break; case FOURCC_ICMT: idStr = IDS_FOURCC_ICMT; break; case FOURCC_ISBJ: idStr = IDS_FOURCC_ISBJ; break; case FOURCC_ICRD: idStr = IDS_FOURCC_ICRD; break; case FOURCC_IART: idStr = IDS_FOURCC_IART; break; case FOURCC_DISP: idStr = IDS_FOURCC_DISP; break; case FOURCC_ICMS: idStr = IDS_FOURCC_ICMS; break; case FOURCC_ICRP: idStr = IDS_FOURCC_ICRP; break; case FOURCC_IDIM: idStr = IDS_FOURCC_IDIM; break; case FOURCC_IDPI: idStr = IDS_FOURCC_IDPI; break; case FOURCC_IENG: idStr = IDS_FOURCC_IENG; break; case FOURCC_IGNR: idStr = IDS_FOURCC_IGNR; break; case FOURCC_IKEY: idStr = IDS_FOURCC_IKEY; break; case FOURCC_ILGT: idStr = IDS_FOURCC_ILGT; break; case FOURCC_IARL: idStr = IDS_FOURCC_IARL; break; case FOURCC_IMED: idStr = IDS_FOURCC_IMED; break; case FOURCC_IPLT: idStr = IDS_FOURCC_IPLT; break; case FOURCC_IPRD: idStr = IDS_FOURCC_IPRD; break; case FOURCC_ISFT: idStr = IDS_FOURCC_ISFT; break; case FOURCC_ISHP: idStr = IDS_FOURCC_ISHP; break; case FOURCC_ISRC: idStr = IDS_FOURCC_ISRC; break; case FOURCC_ISRF: idStr = IDS_FOURCC_ISRF; break; case FOURCC_ITCH: idStr = IDS_FOURCC_ITCH; break; } if (idStr) LoadString(ghInstance, idStr, pCur->szInfoDesc, sizeof(pCur->szInfoDesc)/sizeof(TCHAR)); return TRUE; }
typedef struct tagWaveDesc { DWORD dSize; WORD wFormatSize; NPWAVEFORMATEX pwavefmt; } WAVEDESC,* PWAVEDESC;
STATIC BOOL PASCAL NEAR ReadWaveHeader(HMMIO hmmio, PWAVEDESC pwd) { MMCKINFO mmckRIFF; MMCKINFO mmck; MMRESULT wError;
mmckRIFF.fccType = mmioWAVE; if (wError = mmioDescend(hmmio, &mmckRIFF, NULL, MMIO_FINDRIFF)) { return FALSE; } mmck.ckid = mmioFMT; if (wError = mmioDescend(hmmio, &mmck, &mmckRIFF, MMIO_FINDCHUNK)) { return FALSE; } if (mmck.cksize < sizeof(WAVEFORMAT)) { return FALSE; } pwd->wFormatSize = (WORD)mmck.cksize; pwd->pwavefmt = (NPWAVEFORMATEX)LocalAlloc(LPTR, pwd->wFormatSize); if (!pwd->pwavefmt) { return FALSE; } if ((DWORD)mmioRead(hmmio, (HPSTR)pwd->pwavefmt, mmck.cksize) != mmck.cksize) { goto RetErr; } if (pwd->pwavefmt->wFormatTag == WAVE_FORMAT_PCM) { if (pwd->wFormatSize < sizeof(PCMWAVEFORMAT)) { goto RetErr; } } else if ((pwd->wFormatSize < sizeof(WAVEFORMATEX)) || (pwd->wFormatSize < sizeof(WAVEFORMATEX) + pwd->pwavefmt->cbSize)) { goto RetErr; } if (wError = mmioAscend(hmmio, &mmck, 0)) { goto RetErr; } mmck.ckid = mmioDATA; if (wError = mmioDescend(hmmio, &mmck, &mmckRIFF, MMIO_FINDCHUNK)) { goto RetErr; } pwd->dSize = mmck.cksize; return TRUE; RetErr: LocalFree((HLOCAL)pwd->pwavefmt); pwd->pwavefmt = NULL; return FALSE; }
STATIC void GetWaveInfo(HMMIO hmmio, PMMPSH pmmpsh) { WAVEDESC wd;
if (!ReadWaveHeader(hmmio, &wd)) return;
pmmpsh->uLen = (UINT)MulDiv(wd.dSize, 1000, wd.pwavefmt->nAvgBytesPerSec); pmmpsh->pAudioFormatInfo = (PVOID)wd.pwavefmt; }
STATIC void GetMCIInfo(LPTSTR pszFile, PMMPSH pmmpsh) { TCHAR szMIDIInfo[MAXSTR]; MCI_OPEN_PARMS mciOpen; /* Structure for MCI_OPEN command */ DWORD dwFlags; DWORD dw; UINT wDevID; MCI_STATUS_PARMS mciStatus; MCI_SET_PARMS mciSet; /* Structure for MCI_SET command */ MCI_INFO_PARMS mciInfo; /* Open a file with an explicitly specified device */
memset(&mciOpen, 0x00, sizeof(mciOpen));
mciOpen.lpstrDeviceType = aszMIDIDev; mciOpen.lpstrElementName = pszFile; dwFlags = MCI_WAIT | MCI_OPEN_ELEMENT | MCI_OPEN_TYPE; dw = mciSendCommand((MCIDEVICEID)0, MCI_OPEN, dwFlags,(DWORD_PTR)(LPVOID)&mciOpen); if (dw) return; wDevID = mciOpen.wDeviceID;
mciSet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
dw = mciSendCommand(wDevID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR) (LPVOID) &mciSet); if (dw) { mciSendCommand(wDevID, MCI_CLOSE, 0L, (DWORD_PTR)0); return; }
mciStatus.dwItem = MCI_STATUS_LENGTH; dw = mciSendCommand(wDevID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR) (LPTSTR) &mciStatus); if (dw) pmmpsh->uLen = 0; else pmmpsh->uLen = (UINT)mciStatus.dwReturn;
mciInfo.dwCallback = 0; mciInfo.lpstrReturn = szMIDIInfo; mciInfo.dwRetSize = sizeof(szMIDIInfo);
szMIDIInfo[0] = TEXT('\0');
dw = mciSendCommand(wDevID, MCI_INFO, MCI_INFO_COPYRIGHT, (DWORD_PTR)(LPVOID)&mciInfo);
if (dw == 0 && lstrlen(szMIDIInfo)) { pmmpsh->MIDICOPYRIGHTSTR = LocalAlloc(LPTR, lstrlen(szMIDIInfo) + 1); if (pmmpsh->MIDICOPYRIGHTSTR) { lstrcpy((LPTSTR)pmmpsh->MIDICOPYRIGHTSTR, szMIDIInfo); } }
mciInfo.lpstrReturn = szMIDIInfo; mciInfo.dwRetSize = sizeof(szMIDIInfo);
szMIDIInfo[0] = TEXT('\0');
dw = mciSendCommand(wDevID, MCI_INFO, MCI_INFO_NAME, (DWORD_PTR)(LPVOID)&mciInfo);
if (dw == 0 && lstrlen(szMIDIInfo)) { pmmpsh->MIDISEQNAMESTR = LocalAlloc(LPTR, lstrlen(szMIDIInfo) + 1); if (pmmpsh->MIDISEQNAMESTR) { lstrcpy((LPTSTR)pmmpsh->MIDISEQNAMESTR, szMIDIInfo); } }
mciSendCommand(wDevID, MCI_CLOSE, 0L, (DWORD)0);
}
STATIC void GetMIDIInfo(LPTSTR pszFile, PMMPSH pmmpsh) { GetMCIInfo(pszFile, pmmpsh); }
STATIC void ReadAviStreams(LPTSTR pszFile, PMMPSH pmmpsh) { HRESULT hr; PAVIFILE pfile; int i; PAVISTREAM pavi; PAVISTREAM apavi[MAXNUMSTREAMS]; // the current streams
AVISTREAMINFO avis; LONG timeStart; // cached start, end, length
LONG timeEnd; int cpavi; TCHAR szDecSep[10]; TCHAR szListSep[10];
hr = (HRESULT)AVIFileOpen(&pfile, pszFile, 0, 0L);
if (FAILED(hr)) { DPF("Unable to open %s", pszFile); return; }
for (i = 0; i <= MAXNUMSTREAMS; i++) { if (AVIFileGetStream(pfile, &pavi, 0L, i) != AVIERR_OK) break; if (i == MAXNUMSTREAMS) { AVIStreamRelease(pavi); DPF("Exceeded maximum number of streams"); break; } apavi[i] = pavi; }
//
// Couldn't get any streams out of this file
//
if (i == 0) { DPF("Unable to open any streams in %s", pszFile); if (pfile) AVIFileRelease(pfile); return; }
cpavi = i;
//
// Start with bogus times
//
timeStart = 0x7FFFFFFF; timeEnd = 0;
//bug 141733, get the local decimal and list separators
GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SDECIMAL, szDecSep, sizeof(szDecSep)/sizeof(TCHAR) ); GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SLIST, szListSep, sizeof(szListSep)/sizeof(TCHAR) );
//
// Walk through and init all streams loaded
//
for (i = 0; i < cpavi; i++) {
AVIStreamInfo(apavi[i], &avis, sizeof(avis));
switch(avis.fccType) { case streamtypeVIDEO: { LONG cbFormat; LPVOID lpFormat; ICINFO icInfo; HIC hic; DWORD dwTimeLen; DWORD dwSize; int iFrameRate; TCHAR szFormat[MAXSTR];
if (pmmpsh->pVideoFormatInfo) break;
AVIStreamFormatSize(apavi[i], 0, &cbFormat); pmmpsh->pVideoFormatInfo = (PVOID)LocalAlloc(LPTR, MAX_PATH); if (!pmmpsh->pVideoFormatInfo) break; dwSize = mmpshGetFileSize(pszFile); dwTimeLen = (DWORD)(AVIStreamEndTime(apavi[i]) - AVIStreamStartTime(apavi[i])); iFrameRate = MulDiv(avis.dwLength, 1000000, dwTimeLen); lpFormat = (LPVOID)LocalAlloc(LPTR, cbFormat); if (!lpFormat) { goto BadFormat; } AVIStreamReadFormat(apavi[i], 0, lpFormat, &cbFormat); hic = (HIC)ICLocate(FOURCC_VIDC, avis.fccHandler, lpFormat, NULL, (WORD)ICMODE_DECOMPRESS); if (hic || ((LPBITMAPINFOHEADER)lpFormat)->biCompression == 0) { TCHAR szName[48];
if (((LPBITMAPINFOHEADER)lpFormat)->biCompression) { ICGetInfo(hic, &icInfo, sizeof(ICINFO)); ICClose(hic); //WideCharToMultiByte(CP_ACP, 0, icInfo.szName, -1, szName, sizeof(szName), NULL, NULL);
wcscpy(szName,icInfo.szName); } else { LoadString(ghInstance, IDS_UNCOMPRESSED, szName, sizeof(szName)/sizeof(TCHAR)); } LoadString(ghInstance, IDS_GOODFORMAT, szFormat, sizeof(szFormat)/sizeof(TCHAR));
wsprintf((LPTSTR)pmmpsh->pVideoFormatInfo, szFormat, (avis.rcFrame.right - avis.rcFrame.left), (avis.rcFrame.bottom - avis.rcFrame.top), szListSep, ((LPBITMAPINFOHEADER)lpFormat)->biBitCount, szListSep, avis.dwLength, szListSep, (UINT)(iFrameRate/1000), szDecSep, (UINT)(iFrameRate%1000), szListSep, MulDiv(dwSize, 1000,dwTimeLen)/1024, szListSep, szName);
goto GoodFormat;
} BadFormat: LoadString(ghInstance, IDS_BADFORMAT, szFormat, sizeof(szFormat)/sizeof(TCHAR)); wsprintf((LPTSTR)pmmpsh->pVideoFormatInfo, szFormat, (avis.rcFrame.right - avis.rcFrame.left), (avis.rcFrame.bottom - avis.rcFrame.top), szListSep, avis.dwLength, szListSep, (UINT)(iFrameRate/1000), szDecSep, (UINT)(iFrameRate%1000), szListSep, MulDiv(dwSize, 1000,dwTimeLen)/1024, szListSep); GoodFormat: LocalFree((HLOCAL)lpFormat); break; } case streamtypeAUDIO: { LONG cbFormat;
AVIStreamFormatSize(apavi[i], 0, &cbFormat); pmmpsh->pAudioFormatInfo = (LPVOID)LocalAlloc(LPTR, cbFormat); if (!pmmpsh->pAudioFormatInfo) break; AVIStreamReadFormat(apavi[i], 0, pmmpsh->pAudioFormatInfo, &cbFormat); break; } default: break; }
//
// We're finding the earliest and latest start and end points for
// our scrollbar.
//
timeStart = (LONG)min(timeStart, AVIStreamStartTime(apavi[i])); timeEnd = (LONG)max(timeEnd, AVIStreamEndTime(apavi[i])); } pmmpsh->uLen = (UINT)(timeEnd - timeStart); DPF("The file length is %d \r\n", pmmpsh->uLen);
for (i = 0; i < cpavi; i++) { AVIStreamRelease(apavi[i]); } AVIFileRelease(pfile); }
STATIC void GetAVIInfo(LPTSTR pszFile, PMMPSH pmmpsh) { if (!LoadAVI()) { DPF("****Load AVI failed**\r\n"); ASSERT(FALSE); return; } if (!LoadVFW()) { DPF("****Load VFW failed**\r\n"); ASSERT(FALSE); FreeAVI(); return; } AVIFileInit(); ReadAviStreams(pszFile, pmmpsh); AVIFileExit(); if (!FreeVFW()) { DPF("****Free VFW failed**\r\n"); ASSERT(FALSE); } if (!FreeAVI()) { DPF("****Free AVI failed**\r\n"); ASSERT(FALSE); } }
STATIC void GetASFInfo(LPTSTR pszFile, PMMPSH pmmpsh) { }
STATIC void GetMediaInfo(HMMIO hmmio, PMMPSH pmmpsh) { switch (pmmpsh->iMediaType) { case MT_WAVE: GetWaveInfo(hmmio, pmmpsh); break; case MT_MIDI: GetMIDIInfo(pmmpsh->pszFileObj, pmmpsh); break; case MT_AVI: GetAVIInfo(pmmpsh->pszFileObj, pmmpsh); break; case MT_ASF: GetASFInfo(pmmpsh->pszFileObj, pmmpsh); break; } }
STATIC HANDLE PASCAL GetRiffAll(PMMPSH pmmpsh) { MMCKINFO ck; MMCKINFO ckINFO; MMCKINFO ckRIFF; HANDLE h = NULL; LONG lSize; DWORD dw; HMMIO hmmio; BOOL fDoneDISP; BOOL fDoneINFO; BOOL fDoneName; LPSTR pInfo;
hmmio = mmioOpen(pmmpsh->pszFileObj, NULL, MMIO_ALLOCBUF | MMIO_READ);
if (!hmmio) goto error;
GetMediaInfo(hmmio, pmmpsh); if (pmmpsh->uLen == 0) goto error; mmioSeek(hmmio, 0, SEEK_SET);
/* descend the input file into the RIFF chunk */ if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0) goto error;
if (ckRIFF.ckid != FOURCC_RIFF) goto error;
fDoneDISP = fDoneINFO = fDoneName = FALSE; while (!(fDoneDISP && fDoneINFO) && !mmioDescend(hmmio, &ck, &ckRIFF, 0)) { if (ck.ckid == FOURCC_DISP) { /* Read dword into dw, break if read unsuccessful */ if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != (LONG)sizeof(dw)) goto error;
/* Find out how much memory to allocate */ lSize = ck.cksize - sizeof(dw); if ((int)dw == CF_DIB && h == NULL) { /* get a handle to memory to hold the description and
lock it down */
if ((h = GlobalAlloc(GHND, lSize+4)) == NULL) goto error;
if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize) goto error;
fDoneDISP = TRUE; } else if ((int)dw == CF_TEXT) { pInfo = (LPSTR)LocalAlloc(LPTR, lSize+1);//+1 not required I think
if (!pInfo) goto error;
if (!mmioRead(hmmio, pInfo, lSize)) goto error;
AddInfoToList(pmmpsh, pInfo, ck.ckid ); fDoneName = TRUE;
}
} else if (ck.ckid == FOURCC_LIST && ck.fccType == FOURCC_INFO && !fDoneINFO) { while (!mmioDescend(hmmio, &ckINFO, &ck, 0)) { switch (ckINFO.ckid) { case FOURCC_ISBJ: case FOURCC_INAM: case FOURCC_ICOP: case FOURCC_ICRD: case FOURCC_IART: case FOURCC_ICMS: case FOURCC_ICMT: case FOURCC_ICRP: case FOURCC_IDIM: case FOURCC_IARL: case FOURCC_IDPI: case FOURCC_IENG: case FOURCC_IGNR: case FOURCC_IKEY: case FOURCC_ILGT: case FOURCC_IMED: case FOURCC_IPLT: case FOURCC_IPRD: case FOURCC_ISFT: case FOURCC_ISHP: case FOURCC_ISRC: case FOURCC_ISRF: case FOURCC_ITCH: pInfo = (LPSTR)LocalAlloc(LPTR, ck.cksize+1);//+1 not required I think
if (!pInfo) goto error;
if (!mmioRead(hmmio, pInfo, ck.cksize)) goto error;
AddInfoToList(pmmpsh, pInfo, ckINFO.ckid); if (ckINFO.ckid == FOURCC_INAM) fDoneName = TRUE; break; }
if (mmioAscend(hmmio, &ckINFO, 0)) break; } }
/* Ascend so that we can descend into next chunk
*/ if (mmioAscend(hmmio, &ck, 0)) break; }
goto exit;
error: if (h) { GlobalUnlock(h); GlobalFree(h); } h = NULL; ReleaseInfoList(pmmpsh);
exit: if (hmmio) mmioClose(hmmio,0); return h; }
STATIC BOOL PASCAL WaveGetFormatDescription ( LPWAVEFORMATEX pwfx, LPTSTR pszDesc ) { UINT_PTR mmr; TCHAR pszFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS]; TCHAR pszFormat[ACMFORMATDETAILS_FORMAT_CHARS]; BOOL bRet = FALSE; TCHAR szListSep[10]; //
// get the name for the format tag of the specified format
//
if (!pwfx) { pszDesc[0] = TEXT('\0'); return TRUE; } if (!LoadACM()) { DPF("****Load ACM failed**\r\n"); ASSERT(FALSE); return FALSE; } if (NULL != pszFormatTag) { PACMFORMATTAGDETAILSW paftd;
//
// initialize all unused members of the ACMFORMATTAGDETAILS
// structure to zero
//
paftd = (PACMFORMATTAGDETAILSW)LocalAlloc(LPTR, sizeof(ACMFORMATTAGDETAILSW)); if (!paftd) goto RetErr; //
// fill in the required members of the ACMFORMATTAGDETAILS
// structure for the ACM_FORMATTAGDETAILSF_FORMATTAG query
//
paftd->cbStruct = sizeof(ACMFORMATTAGDETAILSW); paftd->dwFormatTag = pwfx->wFormatTag;
//
// ask the ACM to find the first available driver that
// supports the specified format tag
//
mmr = acmFormatTagDetails(NULL, paftd, ACM_FORMATTAGDETAILSF_FORMATTAG); if (MMSYSERR_NOERROR == mmr) { //
// copy the format tag name into the caller's buffer
//
lstrcpy(pszFormatTag, paftd->szFormatTag); } else { static const struct _wfm_names { UINT uFormatTag; UINT uIDS; } aWaveFmtNames[] = { WAVE_FORMAT_PCM, IDS_FORMAT_PCM, WAVE_FORMAT_ADPCM, IDS_FORMAT_ADPCM, WAVE_FORMAT_IBM_CVSD, IDS_FORMAT_IBM_CVSD, WAVE_FORMAT_ALAW, IDS_FORMAT_ALAW, WAVE_FORMAT_MULAW, IDS_FORMAT_MULAW, WAVE_FORMAT_OKI_ADPCM, IDS_FORMAT_OKI_ADPCM, WAVE_FORMAT_IMA_ADPCM, IDS_FORMAT_IMA_ADPCM, WAVE_FORMAT_MEDIASPACE_ADPCM, IDS_FORMAT_MEDIASPACE_ADPCM, WAVE_FORMAT_SIERRA_ADPCM, IDS_FORMAT_SIERRA_ADPCM, WAVE_FORMAT_G723_ADPCM, IDS_FORMAT_G723_ADPCM, WAVE_FORMAT_DIGISTD, IDS_FORMAT_DIGISTD, WAVE_FORMAT_DIGIFIX, IDS_FORMAT_DIGIFIX, WAVE_FORMAT_YAMAHA_ADPCM, IDS_FORMAT_YAMAHA_ADPCM, WAVE_FORMAT_SONARC, IDS_FORMAT_SONARC, WAVE_FORMAT_DSPGROUP_TRUESPEECH, IDS_FORMAT_DSPGROUP_TRUESPEECH, WAVE_FORMAT_ECHOSC1, IDS_FORMAT_ECHOSC1, WAVE_FORMAT_AUDIOFILE_AF36, IDS_FORMAT_AUDIOFILE_AF36, WAVE_FORMAT_APTX, IDS_FORMAT_APTX, WAVE_FORMAT_AUDIOFILE_AF10, IDS_FORMAT_AUDIOFILE_AF10, WAVE_FORMAT_DOLBY_AC2, IDS_FORMAT_DOLBY_AC2, WAVE_FORMAT_GSM610, IDS_FORMAT_GSM610, WAVE_FORMAT_G721_ADPCM, IDS_FORMAT_G721_ADPCM, WAVE_FORMAT_CREATIVE_ADPCM, IDS_FORMAT_CREATIVE_ADPCM, 0, IDS_UNKFORMAT, }; UINT ii;
//
// no ACM driver is available that supports the
// specified format tag. look up the tag id
// in our table of tag names (above)
//
for (ii = 0; aWaveFmtNames[ii].uFormatTag; ii++) if (pwfx->wFormatTag == aWaveFmtNames[ii].uFormatTag) break; LoadString(ghInstance, aWaveFmtNames[ii].uIDS, pszFormatTag, ACMFORMATTAGDETAILS_FORMATTAG_CHARS); } LocalFree((HLOCAL)paftd); }
//
// get the description of the attributes for the specified
// format
//
if (NULL != pszFormat) { PACMFORMATDETAILSW pafd;
//
// initialize all unused members of the ACMFORMATDETAILS
// structure to zero
//
pafd = (PACMFORMATDETAILSW)LocalAlloc(LPTR, sizeof(ACMFORMATDETAILSW)); if (!pafd) goto RetErr;
//
// fill in the required members of the ACMFORMATDETAILS
// structure for the ACM_FORMATDETAILSF_FORMAT query
//
pafd->cbStruct = sizeof(ACMFORMATDETAILSW); pafd->dwFormatTag = pwfx->wFormatTag; pafd->pwfx = pwfx;
//
// the cbwfx member must be initialized to the total size
// in bytes needed for the specified format. for a PCM
// format, the cbSize member of the WAVEFORMATEX structure
// is not valid.
//
if (WAVE_FORMAT_PCM == pwfx->wFormatTag) { pafd->cbwfx = sizeof(PCMWAVEFORMAT); } else { pafd->cbwfx = sizeof(WAVEFORMATEX) + pwfx->cbSize; }
//
// ask the ACM to find the first available driver that
// supports the specified format
//
mmr = acmFormatDetails(NULL, pafd, ACM_FORMATDETAILSF_FORMAT); if (MMSYSERR_NOERROR == mmr) { //
// copy the format attributes description into the caller's
// buffer
//
lstrcpy(pszFormat, pafd->szFormat); } else { pszFormat[0] = TEXT('\0'); } LocalFree((HLOCAL)pafd); } //bug 141733, get the local decimal and list separators
GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SLIST, szListSep, sizeof(szListSep)/sizeof(TCHAR) ); wsprintf(pszDesc, TEXT("%s%s %s"), pszFormatTag, szListSep, pszFormat); bRet = TRUE;
RetErr: if (!FreeACM()) { DPF("****Free ACM failed**\r\n"); ASSERT(FALSE); } return bRet; } // AcmAppGetFormatDescription()
STATIC void ShowInfoList(PMMPSH pmmpsh, HWND hDlg) { PMMINFOLIST pCur; TCHAR* szTemp; HWND hwndLB = GetDlgItem(hDlg, IDD_INFO_NAME); TCHAR szNoCopyRight[MAXSTR]; int iIndex;
LoadString(ghInstance, IDS_NOCOPYRIGHT, szNoCopyRight, sizeof(szNoCopyRight)/sizeof(TCHAR)); SetDlgItemText(hDlg, IDD_COPYRIGHT, szNoCopyRight); if (!pmmpsh->pInfoList) { DestroyWindow(GetDlgItem(hDlg, IDC_DETAILSINFO_GRP)); DestroyWindow(GetDlgItem(hDlg, IDC_ITEMSLABEL)); DestroyWindow(GetDlgItem(hDlg, IDC_DESCLABEL)); DestroyWindow(GetDlgItem(hDlg, IDD_INFO_NAME)); DestroyWindow(GetDlgItem(hDlg, IDD_INFO_VALUE)); return; } for (pCur = pmmpsh->pInfoList; pCur; pCur = pCur->pNext) { int nTempSize = (strlen(pCur->pszInfo)*sizeof(TCHAR))+sizeof(TCHAR); szTemp = (LPTSTR)LocalAlloc(LPTR, nTempSize); if (!szTemp) return;
MultiByteToWideChar(GetACP(), 0, pCur->pszInfo, -1, szTemp, nTempSize);
if (pCur->ckid == FOURCC_ICOP) { SetDlgItemText(hDlg, IDD_COPYRIGHT, szTemp); LocalFree(szTemp); continue; } iIndex = ListBox_AddString(hwndLB, pCur->szInfoDesc); if (iIndex != LB_ERR) { //reassigning wide pointer back into "info" so it will get cleaned up later
pCur->pszInfo = (LPSTR)szTemp; ListBox_SetItemData(hwndLB, iIndex, (LPARAM)pCur->pszInfo); } } SetFocus(hwndLB); if (ListBox_SetCurSel(hwndLB, 0) != LB_ERR) FORWARD_WM_COMMAND(hDlg, IDD_INFO_NAME, hwndLB, LBN_SELCHANGE, PostMessage); }
BOOL PASCAL DoDetailsCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify) { switch (id) {
case ID_APPLY: return TRUE;
case IDOK: break;
case IDCANCEL: break;
case ID_INIT: { PMMPSH pmmpsh = (PMMPSH)GetWindowLongPtr(hDlg, DWLP_USER);
if (pmmpsh->hDispBMP) { HWND hwndDisp = GetDlgItem(hDlg,IDD_DISPFRAME); HDC hdc; HPALETTE hpalT; int i;
SendMessage(hwndDisp, (UINT)DF_PM_SETBITMAP, (WPARAM)pmmpsh->hDispBMP, (LPARAM)pmmpsh->hPal);
/*
* If realizing the palette causes the palette to change, * redraw completely. */
hdc = GetDC(hwndDisp); hpalT = SelectPalette (hdc, pmmpsh->hPal, FALSE);
i = RealizePalette(hdc); /* i == entries that changed */
SelectPalette (hdc, hpalT, FALSE); ReleaseDC(hwndDisp, hdc);
/* If any palette entries changed, repaint the window. */
if (i > 0) { InvalidateRect(hwndDisp, NULL, TRUE); } } break; }
case IDD_INFO_NAME: if (codeNotify == LBN_SELCHANGE) { int iIndex = ListBox_GetCurSel(hwndCtl); LPTSTR pszInfo = (LPTSTR)ListBox_GetItemData(hwndCtl, iIndex);
SetDlgItemText(hDlg, IDD_INFO_VALUE, pszInfo); } break; } return FALSE; }
STATIC void ShowMediaLen(PMMPSH pmmpsh, HWND hwnd) { TCHAR szBuf[MAXSTR]; TCHAR szFmt[MAXSTR]; UINT uMin; UINT uSec; UINT umSec; UINT uLen; TCHAR szDecSep[10];
uLen = pmmpsh->uLen;
if ((!uLen && pmmpsh->iMediaType != MT_WAVE) || (!pmmpsh->pAudioFormatInfo && pmmpsh->iMediaType != MT_MIDI && pmmpsh->iMediaType != MT_AVI && pmmpsh->iMediaType != MT_ASF)) { LoadString(ghInstance, IDS_BADFILE, szBuf, sizeof(szBuf)/sizeof(TCHAR)); SetWindowText(hwnd, szBuf); return; } uMin = (UINT)(uLen/60000); uSec = (UINT)((uLen/1000) % 60); umSec = (UINT)(uLen % 1000);
//bug 141733, get the local decimal separator
GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SDECIMAL, szDecSep, sizeof(szDecSep)/sizeof(TCHAR) );
if (uMin) {
LoadString(ghInstance, IDS_MINFMT, szFmt, sizeof(szFmt)/sizeof(TCHAR)); wsprintf(szBuf, szFmt, uMin, uSec, szDecSep, umSec); } else {
LoadString(ghInstance, IDS_SECFMT, szFmt, sizeof(szFmt)/sizeof(TCHAR)); wsprintf(szBuf, szFmt, uSec, szDecSep, umSec); } SetWindowText(hwnd, szBuf); }
STATIC void ShowMediaFormat(PMMPSH pmmpsh, HWND hDlg) { switch (pmmpsh->iMediaType) { case MT_WAVE: { TCHAR szDesc[MAX_PATH];
szDesc[0] = TEXT('\0'); WaveGetFormatDescription((LPWAVEFORMATEX)pmmpsh->pAudioFormatInfo, szDesc); SetDlgItemText(hDlg, IDD_AUDIOFORMAT, szDesc); DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMAT)); DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMATLABEL)); DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL)); DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME)); break; } case MT_MIDI: DestroyWindow(GetDlgItem(hDlg, IDD_AUDIOFORMAT)); DestroyWindow(GetDlgItem(hDlg, IDD_AUDIOFORMATLABEL)); DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMAT)); DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMATLABEL)); if (pmmpsh->MIDICOPYRIGHTSTR) SetDlgItemText(hDlg, IDD_COPYRIGHT, (LPTSTR)pmmpsh->MIDICOPYRIGHTSTR); if (pmmpsh->MIDISEQNAMESTR) SetDlgItemText(hDlg, IDD_MIDISEQUENCENAME, (LPTSTR)pmmpsh->MIDISEQNAMESTR); else { DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL)); DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME)); } break; case MT_AVI: { TCHAR szDesc[MAX_PATH];
DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL)); DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME));
szDesc[0] = TEXT('\0'); if (pmmpsh->pVideoFormatInfo) SetDlgItemText(hDlg, IDD_VIDEOFORMAT, (LPTSTR)pmmpsh->pVideoFormatInfo); else SetDlgItemText(hDlg, IDD_VIDEOFORMAT, (LPTSTR)szDesc); WaveGetFormatDescription((LPWAVEFORMATEX)pmmpsh->pAudioFormatInfo, szDesc); SetDlgItemText(hDlg, IDD_AUDIOFORMAT, szDesc); break; } case MT_ASF: { break; } } }
const static DWORD aFileDetailsIds[] = { // Context Help IDs
IDD_DISPFRAME, NO_HELP, IDD_DISP_ICON, IDH_FPROP_GEN_ICON, IDD_FILENAME, IDH_FPROP_GEN_NAME, IDD_CRLABEL, IDH_FCAB_MM_COPYRIGHT, IDD_COPYRIGHT, IDH_FCAB_MM_COPYRIGHT, IDD_LENLABEL, IDH_FCAB_MM_FILELEN, IDD_FILELEN, IDH_FCAB_MM_FILELEN, IDD_AUDIOFORMATLABEL, IDH_FCAB_MM_AUDIOFORMAT, IDD_AUDIOFORMAT, IDH_FCAB_MM_AUDIOFORMAT, IDD_MIDISEQUENCELABEL, IDH_FCAB_MM_MIDISEQUENCENAME, IDD_MIDISEQUENCENAME, IDH_FCAB_MM_MIDISEQUENCENAME, IDD_VIDEOFORMATLABEL, IDH_FCAB_MM_VIDEOFORMAT, IDD_VIDEOFORMAT, IDH_FCAB_MM_VIDEOFORMAT, IDC_DETAILSINFO_GRP, IDH_FCAB_MM_DETAILSINFO, IDC_ITEMSLABEL, IDH_FCAB_MM_DETAILSINFO, IDC_DESCLABEL, IDH_FCAB_MM_DETAILSINFO, IDD_INFO_NAME, IDH_FCAB_MM_DETAILSINFO, IDD_INFO_VALUE, IDH_FCAB_MM_DETAILSINFO,
0, 0 };
INT_PTR CALLBACK FileDetailsDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { NMHDR FAR *lpnm;
switch (uMsg) { case WM_NOTIFY: lpnm = (NMHDR FAR *)lParam; switch(lpnm->code) { case PSN_KILLACTIVE: FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage); break;
case PSN_APPLY: FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage); break;
case PSN_SETACTIVE: FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage); break;
case PSN_RESET: FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage); break; } break;
case WM_INITDIALOG: { PMMPSH pmmpsh = (PMMPSH)(((LPPROPSHEETPAGE)lParam)->lParam); TCHAR szFile[MAX_PATH]; HANDLE hDib = NULL; HCURSOR hCursor;
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pmmpsh);
if (!pmmpsh->pInfoList) { hDib = GetRiffAll(pmmpsh); }
if (!hDib) break;
pmmpsh->hPal = bmfCreateDIBPalette(hDib); pmmpsh->hDispBMP = bmfBitmapFromDIB(hDib, pmmpsh->hPal); if (hDib) { GlobalUnlock(hDib); hDib = GlobalFree(hDib); } if (!pmmpsh->hDispBMP) { int iIconID;
switch (pmmpsh->iMediaType) { case MT_WAVE: iIconID = IDI_DWAVE; break; case MT_MIDI: iIconID = IDI_DMIDI; break; case MT_AVI: case MT_ASF: iIconID = IDI_DVIDEO; break; } DestroyWindow(GetDlgItem(hDlg,IDD_DISPFRAME)); pmmpsh->hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(iIconID)); Static_SetIcon(GetDlgItem(hDlg, IDD_DISP_ICON), pmmpsh->hIcon); } else { DestroyWindow(GetDlgItem(hDlg,IDD_DISP_ICON)); //SendDlgItemMessage(hDlg, (int)IDD_DISPFRAME, (UINT)DF_PM_SETBITMAP, (WPARAM)pmmpsh->hDispBMP,
// (LPARAM)pmmpsh->hPal);
}
lstrcpy(szFile, pmmpsh->pszFileObj); NiceName(szFile, TRUE); SetDlgItemText(hDlg, IDD_FILENAME, szFile);
ShowMediaLen(pmmpsh, GetDlgItem(hDlg, IDD_FILELEN)); ShowInfoList(pmmpsh, hDlg); ShowMediaFormat(pmmpsh, hDlg); SetCursor(hCursor); break; }
case WM_DESTROY: { PMMPSH pmmpsh = (PMMPSH)GetWindowLongPtr(hDlg, DWLP_USER);
if (pmmpsh->hDispBMP) DeleteObject(pmmpsh->hDispBMP); if (pmmpsh->hIcon) DestroyIcon(pmmpsh->hIcon); if (pmmpsh->hPal) DeleteObject(pmmpsh->hPal); if (pmmpsh->pAudioFormatInfo) LocalFree((HLOCAL)pmmpsh->pAudioFormatInfo); if (pmmpsh->pVideoFormatInfo) LocalFree((HLOCAL)pmmpsh->pVideoFormatInfo); break; }
case WM_CONTEXTMENU: WinHelp((HWND)wParam, gszWindowsHlp, HELP_CONTEXTMENU, (UINT_PTR)(LPTSTR)aFileDetailsIds); return TRUE;
case WM_HELP: WinHelp(((LPHELPINFO)lParam)->hItemHandle, gszWindowsHlp, HELP_WM_HELP , (UINT_PTR)(LPTSTR)aFileDetailsIds); return TRUE;
case WM_COMMAND: HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoDetailsCommand); break; } return FALSE; }
static DWORD aPreviewIds[] = { // Context Help IDs
0, IDH_FCAB_MM_PREVIEW_CONTROL, IDD_DISP_ICON, IDH_FPROP_GEN_ICON, IDD_FILENAME, IDH_FPROP_GEN_NAME,
0, 0 };
INT_PTR CALLBACK PreviewDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static BOOL fLoadedVFW; static HICON hIcon; switch (uMsg) { case WM_NOTIFY: { NMHDR FAR *lpnm;
lpnm = (NMHDR FAR *)lParam; switch(lpnm->code) { case PSN_KILLACTIVE: { HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
DPF("***PSN_KILLACTIVE***\r\n"); if (IsWindow(hwndMCI)) MCIWndStop(hwndMCI); break; }
case PSN_APPLY: DPF("***PSN_APPLY***\r\n"); return TRUE;
} break; }
case WM_INITDIALOG: { PMMPSH pmmpsh = (PMMPSH)(((LPPROPSHEETPAGE)lParam)->lParam); HCURSOR hCursor; HWND hwndMCI; HWND hwndTitle; RECT rcWnd; RECT rcDlg; TCHAR szFile[MAX_PATH]; TCHAR szTitle[MAXSTR]; TCHAR szTmp[MAXSTR]; #ifndef DEBUG_BUILT_LINKED
FN_MCIWNDCREATE fnMCIWndCreate; #endif
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT)); lstrcpy(szFile, pmmpsh->pszFileObj); NiceName(szFile, TRUE); LoadString(ghInstance, IDS_PREVIEWOF, szTmp, sizeof(szTmp)/sizeof(TCHAR)); wsprintf(szTitle, szTmp, szFile); hwndTitle = GetDlgItem(hDlg, IDD_FILENAME); SetWindowText(hwndTitle, szTitle);
fLoadedVFW = FALSE; if (!LoadVFW()) { DPF("****Load VFW failed**\r\n"); ASSERT(FALSE); break; } fLoadedVFW = TRUE; #ifndef DEBUG_BUILT_LINKED
fnMCIWndCreate = (FN_MCIWNDCREATE)MCIWndCreateW; hwndMCI = fnMCIWndCreate(hDlg, ghInstance, (DWORD)MCIWNDF_NOMENU, (LPCTSTR)pmmpsh->pszFileObj); #else
hwndMCI = MCIWndCreateW(hDlg, ghInstance, (DWORD)MCIWNDF_NOMENU, (LPCTSTR)pmmpsh->pszFileObj); #endif
aPreviewIds[0] = GetDlgCtrlID(hwndMCI); GetWindowRect(hwndMCI, &rcWnd); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcWnd, 2); GetWindowRect(hDlg, &rcDlg); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcDlg, 2); hIcon = NULL; switch (pmmpsh->iMediaType) { case MT_WAVE: case MT_MIDI: { int ircWndTop;
ircWndTop = (int)((rcDlg.bottom - rcDlg.top)/2) - 50; rcWnd.top += ircWndTop; rcWnd.bottom += ircWndTop; rcWnd.left = 20; rcWnd.right = rcDlg.right - 20;
MoveWindow(hwndMCI, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left), (rcWnd.bottom - rcWnd.top), FALSE); GetWindowRect(hwndTitle, &rcWnd); MapWindowPoints(NULL, hDlg, (LPPOINT)&rcWnd, 2); OffsetRect(&rcWnd, 52, 36); MoveWindow(hwndTitle, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left), (rcWnd.bottom - rcWnd.top), FALSE); hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_DWAVE+pmmpsh->iMediaType-1)); Static_SetIcon(GetDlgItem(hDlg, IDD_DISP_ICON),hIcon);
break; } case MT_AVI: { int iDlgHt = rcDlg.bottom - rcDlg.top -15; //15 for the title
int iDlgWth = rcDlg.right - rcDlg.left; int iWndHt = rcWnd.bottom - rcWnd.top; int iWndWth = rcWnd.right - rcWnd.left;
DestroyWindow(GetDlgItem(hDlg, IDD_DISP_ICON)); if (iWndWth < iDlgWth && iWndHt < iDlgHt) { int ixOff = (int)((iDlgWth - iWndWth)/2); int iyOff = (int)((iDlgHt - iWndHt)/2) + 15;
OffsetRect(&rcWnd, ixOff, iyOff); MoveWindow(hwndMCI, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left), (rcWnd.bottom - rcWnd.top), FALSE); } else { int ixExcess = iWndWth - iDlgWth; int iyExcess = iWndHt - (iDlgHt - 15); //Take another 15 off
int ixOff; int iyOff; RECT rcSource; RECT rcDest; RECT rcDestWnd;
MCIWndGetDest(hwndMCI, &rcSource); //DPF("The Video Window is too big: SHRINKING\r\nrcSource = %d,%d,%d%d ** rcWnd=%d,%d,%d,%d ** rcDlg=%d,%d,%d,%d\r\n",
// rcSource.left,rcSource.top,rcSource.right,rcSource.bottom,
// rcWnd.left,rcWnd.top,rcWnd.right,rcWnd.bottom,
// rcDlg.left,rcDlg.top,rcDlg.right,rcDlg.bottom);
rcDest.top = rcSource.top; // new boundaries
rcDest.left = rcSource.left; if (ixExcess > iyExcess) { rcDest.right = rcSource.left + (((rcSource.right - rcSource.left)*(iDlgWth - 20))/iWndWth); rcDest.bottom = rcSource.top + (((rcSource.bottom - rcSource.top)*(iDlgWth - 20))/iWndWth); //DPF("rcDest = %d,%d,%d,%d\r\n",rcDest.left,rcDest.top,rcDest.right,rcDest.bottom);
} else { rcDest.right = rcSource.left + (((rcSource.right - rcSource.left)*(iDlgHt - 20))/iWndHt); rcDest.bottom = rcSource.top + (((rcSource.bottom - rcSource.top)*(iDlgHt - 20))/iWndHt); } rcDestWnd.top = rcWnd.top; rcDestWnd.left = rcWnd.left; rcDestWnd.right = rcWnd.left + (rcDest.right - rcDest.left); rcDestWnd.bottom = rcWnd.top + (rcDest.bottom - rcDest.top) + (iWndHt - (rcSource.bottom - rcSource.top)); //DPF("rcDestWnd = %d,%d,%d,%d\r\n",rcDestWnd.left,rcDestWnd.top,rcDestWnd.right,rcDestWnd.bottom);
ixOff = (int)((iDlgWth - (rcDestWnd.right - rcDestWnd.left))/2); iyOff = (int)((iDlgHt - (rcDestWnd.bottom - rcDestWnd.top))/2) + 15; //DPF("ixOff = %, iyOff = %d\r\n", ixOff, iyOff);
OffsetRect(&rcDestWnd, ixOff, iyOff); MCIWndPutDest(hwndMCI, &rcDest); MoveWindow(hwndMCI, rcDestWnd.left, rcDestWnd.top, (rcDestWnd.right - rcDestWnd.left), (rcDestWnd.bottom - rcDestWnd.top), FALSE);
} break;
case MT_ASF: break; } }
SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)hwndMCI); SetCursor(hCursor); break; }
case WM_CLOSE: DPF("***WM_CLOSE***\r\n"); break;
case WM_DESTROY: { HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
DPF("***WM_DESTROY***\r\n"); if (hIcon) { DestroyIcon(hIcon); hIcon = NULL; } if (IsWindow(hwndMCI)) MCIWndDestroy(hwndMCI); SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)NULL);
if (!fLoadedVFW) break; if (!FreeVFW()) { DPF("****Free VFW failed**\r\n"); ASSERT(FALSE); } fLoadedVFW = FALSE; break; }
case WM_CONTEXTMENU: WinHelp((HWND)wParam, gszWindowsHlp, HELP_CONTEXTMENU, (UINT_PTR)(LPTSTR)aPreviewIds); return TRUE;
case WM_HELP: WinHelp(((LPHELPINFO)lParam)->hItemHandle, gszWindowsHlp, HELP_WM_HELP , (UINT_PTR)(LPTSTR)aPreviewIds); return TRUE;
case WM_QUERYNEWPALETTE: case WM_PALETTECHANGED: { HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
SendMessage(hwndMCI, uMsg, wParam, lParam); break; } } return FALSE; }
//---------------------------------------------------------------------------
// mmse IUnknown base member functions
//---------------------------------------------------------------------------
/*----------------------------------------------------------
Purpose: IUnknown::QueryInterface
Returns: standard Cond: -- */ STDMETHODIMP mmpsh_QueryInterface( LPUNKNOWN punk, REFIID riid, LPVOID FAR* ppvOut) { PMMPSH this = IToClass(mmpsh, sei, punk); HRESULT hres = ResultFromScode(E_NOINTERFACE); *ppvOut = NULL;
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IShellExtInit)) { // We use the sei field as our IUnknown as well
*ppvOut = &this->sei; this->cRef++; hres = NOERROR; } else if (IsEqualIID(riid, &IID_IShellPropSheetExt)) { (LPSHELLPROPSHEETEXT)*ppvOut = &this->pse; this->cRef++; hres = NOERROR; } return hres; }
/*----------------------------------------------------------
Purpose: IUnknown::AddRef
Returns: new reference count Cond: -- */ STDMETHODIMP_(UINT) mmpsh_AddRef( LPUNKNOWN punk) { PMMPSH this = IToClass(mmpsh, sei, punk);
return ++this->cRef; }
/*----------------------------------------------------------
Purpose: IUnknown::Release
Returns: new reference count Cond: -- */ STDMETHODIMP_(UINT) mmpsh_Release( LPUNKNOWN punk) { PMMPSH this = IToClass(mmpsh, sei, punk);
if (--this->cRef) { return this->cRef; }
DPF_T("*^*^*^*^*^*^*^*^*^MMPSH nuked , RefCnt = %d *^*^*^*^ \r\n", (g_cRef - 1)); if (this->pdtobj) { this->pdtobj->lpVtbl->Release(this->pdtobj); }
if (this->pszFileObj) { LocalFree((HLOCAL)this->pszFileObj); } ReleaseInfoList(this);
LocalFree((HLOCAL)this); --g_cRef; return 0; }
/*----------------------------------------------------------
Purpose: IShellExtInit::QueryInterface
Returns: standard Cond: -- */ STDMETHODIMP mmpsh_SEI_QueryInterface( LPSHELLEXTINIT psei, REFIID riid, LPVOID FAR* ppvOut) { PMMPSH this = IToClass(mmpsh, sei, psei);
return mmpsh_QueryInterface((LPUNKNOWN)&this->sei, riid, ppvOut); }
/*----------------------------------------------------------
Purpose: IShellExtInit::AddRef
Returns: new reference count Cond: -- */ STDMETHODIMP_(UINT) mmpsh_SEI_AddRef( LPSHELLEXTINIT psei) { PMMPSH this = IToClass(mmpsh, sei, psei);
return mmpsh_AddRef((LPUNKNOWN)&this->sei); }
/*----------------------------------------------------------
Purpose: IShellExtInit::Release
Returns: new reference count Cond: -- */ STDMETHODIMP_(UINT) mmpsh_SEI_Release( LPSHELLEXTINIT psei) { PMMPSH this = IToClass(mmpsh, sei, psei); return mmpsh_Release((LPUNKNOWN)&this->sei); }
/*----------------------------------------------------------
Purpose: MMPSHReleaseStgMedium
Returns: NOERROR Cond: -- */ HRESULT MMPSHReleaseStgMedium(LPSTGMEDIUM pmedium) { //
// Double-check pUnkForRelease in case we're not supposed to
// release the medium.
//
if (NULL == pmedium->pUnkForRelease) { switch(pmedium->tymed) { case TYMED_HGLOBAL: GlobalFree(pmedium->hGlobal); break;
case TYMED_ISTORAGE: pmedium->pstg->lpVtbl->Release(pmedium->pstg); break;
case TYMED_ISTREAM: pmedium->pstm->lpVtbl->Release(pmedium->pstm); break;
default: ASSERT(FALSE); // unknown type
break; } }
return NOERROR; }
/*----------------------------------------------------------
Purpose: IShellExtInit::Initialize
Returns: noerror Cond: -- */ STDMETHODIMP mmpsh_SEI_Initialize( LPSHELLEXTINIT psei, LPCITEMIDLIST pidlObj, LPDATAOBJECT pdtobj, HKEY hkeyProgID) { HRESULT hres = NOERROR; PMMPSH this = IToClass(mmpsh, sei, psei); DPF("mmpsh_SEI_Initialize called\n");
if (pdtobj) { STGMEDIUM medium; FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if (this->pdtobj) { this->pdtobj->lpVtbl->Release(this->pdtobj); } this->pdtobj = pdtobj; pdtobj->lpVtbl->AddRef(pdtobj);
hres = pdtobj->lpVtbl->GetData(pdtobj, &fmte, &medium); if(SUCCEEDED(hres)) { if (DragQueryFile(medium.hGlobal, (UINT)-1, NULL, 0)) { TCHAR szPath[MAX_PATH]; int iIndex; DWORD dwSize = 0;
szPath[0] = '\0';
DragQueryFile(medium.hGlobal, 0, szPath, sizeof(szPath)/sizeof(TCHAR));
dwSize = mmpshGetFileSize(szPath); if (dwSize != 0) { iIndex = lstrlen(szPath) - 4; if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszWavExt)) this->iMediaType = MT_WAVE; else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszMIDIExt)) this->iMediaType = MT_MIDI; else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszRMIExt)) this->iMediaType = MT_MIDI; else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszAVIExt)) this->iMediaType = MT_AVI; else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszASFExt)) this->iMediaType = MT_ASF; else this->iMediaType = MT_ERROR;
if (!this->pszFileObj || lstrcmpi(this->pszFileObj, szPath)) { if (this->pszFileObj) LocalFree((HLOCAL)this->pszFileObj); ReleaseInfoList(this); if (this->iMediaType) { this->pszFileObj = (LPTSTR)LocalAlloc(LPTR, (lstrlen(szPath)*sizeof(TCHAR))+sizeof(TCHAR)); if (this->pszFileObj) lstrcpy(this->pszFileObj , szPath); } else hres = ResultFromScode(E_FAIL); } } else hres = ResultFromScode(E_FAIL); } //
// Release STGMEDIUM if we're responsible for doing that.
//
if (NULL == medium.pUnkForRelease) MMPSHReleaseStgMedium(&medium); } else return hres; } return hres; }
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::QueryInterface
Returns: standard Cond: -- */ STDMETHODIMP mmpsh_PSE_QueryInterface( LPSHELLPROPSHEETEXT ppse, REFIID riid, LPVOID FAR* ppvOut) { PMMPSH this = IToClass(mmpsh, pse, ppse);
return mmpsh_QueryInterface((LPUNKNOWN)&this->sei, riid, ppvOut); }
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::AddRef
Returns: new reference count Cond: -- */ STDMETHODIMP_(UINT) mmpsh_PSE_AddRef( LPSHELLPROPSHEETEXT ppse) { PMMPSH this = IToClass(mmpsh, pse, ppse);
return mmpsh_AddRef((LPUNKNOWN)&this->sei); }
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::Release
Returns: new reference count Cond: -- */ STDMETHODIMP_(UINT) mmpsh_PSE_Release( LPSHELLPROPSHEETEXT ppse) { PMMPSH this = IToClass(mmpsh, pse, ppse); return mmpsh_Release((LPUNKNOWN)&this->sei); }
/*==========================================================================*/ UINT CALLBACK DetailsPageCallback( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp) { if (uMsg == PSPCB_RELEASE) if (((PMMPSH)(ppsp->lParam))->pse.lpVtbl) ((PMMPSH)(ppsp->lParam))->pse.lpVtbl->Release(&(((PMMPSH)(ppsp->lParam))->pse)); else { LocalFree((HLOCAL)((PMMPSH)(ppsp->lParam))->pszFileObj); LocalFree((HLOCAL)ppsp->lParam); } return 1; }
BOOL AddDetailsPage( LPTSTR pszTitle, LPFNADDPROPSHEETPAGE lpfnAddPropSheetPage, LPARAM lDlgParam, LPARAM lParam) { PROPSHEETPAGE psp; HPROPSHEETPAGE hpsp;
psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK; psp.hInstance = ghInstance; psp.pszTemplate = MAKEINTRESOURCE(DLG_FILE_DETAILS); psp.pszIcon = NULL; psp.pszTitle = pszTitle; psp.pfnDlgProc = FileDetailsDlg; psp.lParam = lDlgParam; psp.pfnCallback = DetailsPageCallback; psp.pcRefParent = NULL; if (hpsp = CreatePropertySheetPage(&psp)) { if (lpfnAddPropSheetPage(hpsp, lParam)) return TRUE; DestroyPropertySheetPage(hpsp); } return FALSE; }
UINT CALLBACK PreviewPageCallback( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp) { return 1; }
BOOL AddPreviewPage( LPTSTR pszTitle, LPFNADDPROPSHEETPAGE lpfnAddPropSheetPage, LPARAM lDlgParam, LPARAM lParam) { PROPSHEETPAGE psp; HPROPSHEETPAGE hpsp;
psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK; psp.hInstance = ghInstance; psp.pszTemplate = MAKEINTRESOURCE(PREVIEW_DLG); psp.pszIcon = NULL; psp.pszTitle = pszTitle; psp.pfnDlgProc = PreviewDlg; psp.lParam = lDlgParam; psp.pfnCallback = PreviewPageCallback; psp.pcRefParent = NULL; if (hpsp = CreatePropertySheetPage(&psp)) { if (lpfnAddPropSheetPage(hpsp, lParam)) return TRUE; DestroyPropertySheetPage(hpsp); } return FALSE; }
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::AddPages
Returns: NOERROR Cond: -- */ STDMETHODIMP mmpsh_PSE_AddPages( LPSHELLPROPSHEETEXT ppse, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam) { PMMPSH this = IToClass(mmpsh, pse, ppse); /* BOOL fAddPreview = FALSE;
LoadString(ghInstance, IDS_DETAILS, szDetailsTab, sizeof(szDetailsTab)/sizeof(TCHAR)); RegSndCntrlClass((LPCTSTR)DISPFRAMCLASS); AddDetailsPage(szDetailsTab,lpfnAddPage,(LPARAM)this, lParam); switch (this->iMediaType) { case MT_AVI: fAddPreview = TRUE; break; case MT_WAVE: if (waveOutGetNumDevs() > 0) fAddPreview = TRUE; break; case MT_MIDI: if (midiOutGetNumDevs() > 0) fAddPreview = TRUE; break; } if (fAddPreview) { LoadString(ghInstance, IDS_PREVIEW, szPreviewTab, sizeof(szPreviewTab)/sizeof(TCHAR)); AddPreviewPage(szPreviewTab,lpfnAddPage,(LPARAM)this, lParam); } */ ppse->lpVtbl->AddRef(ppse); return NOERROR; }
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::ReplacePage
Returns: E_NOTIMPL Cond: -- */ STDMETHODIMP mmpsh_PSE_ReplacePage( LPSHELLPROPSHEETEXT ppse, UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam) { return ResultFromScode(E_NOTIMPL); }
IShellExtInitVtbl c_mmpshSEIVtbl = { mmpsh_SEI_QueryInterface, mmpsh_SEI_AddRef, mmpsh_SEI_Release, mmpsh_SEI_Initialize };
IShellPropSheetExtVtbl c_mmpshPSEVtbl = { mmpsh_PSE_QueryInterface, mmpsh_PSE_AddRef, mmpsh_PSE_Release, mmpsh_PSE_AddPages, mmpsh_PSE_ReplacePage } ;
HRESULT CALLBACK mmpsh_CreatePSHInstance( LPUNKNOWN punkOuter, REFIID riid, LPVOID FAR* ppvOut) { HRESULT hres; PMMPSH this;
DPF_T("*^*^*^*^*^*^*^*^mmpsh_CreatePSHInstance*^*^*^*^*^*^*^*^\r\n");
// The handler does not support aggregation.
if (punkOuter) { hres = ResultFromScode(CLASS_E_NOAGGREGATION); goto Leave; }
this = LocalAlloc(LPTR, sizeof(*this)); if (!this) { hres = ResultFromScode(E_OUTOFMEMORY); goto Leave; } this->sei.lpVtbl = &c_mmpshSEIVtbl; this->pse.lpVtbl = &c_mmpshPSEVtbl; this->cRef = 1;
++g_cRef;
// Note that the Release member will free the object, if
// QueryInterface failed.
hres = this->sei.lpVtbl->QueryInterface(&this->sei, riid, ppvOut); this->sei.lpVtbl->Release(&this->sei);
Leave:
return hres; // S_OK or E_NOINTERFACE
}
BOOL mmpsh_ShowFileDetails(LPTSTR pszCaption, HWND hwndParent, LPTSTR pszFile, short iMediaType) { PMMPSH pmmpsh; TCHAR szTabName[64];
pmmpsh = (PMMPSH)LocalAlloc(LPTR, sizeof(*pmmpsh));
if (!pmmpsh) return FALSE;
pmmpsh->pszFileObj = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pszFile)*sizeof(TCHAR))+sizeof(TCHAR));
if (!pmmpsh->pszFileObj) { LocalFree((HLOCAL)pmmpsh); return FALSE; }
lstrcpy(pmmpsh->pszFileObj , pszFile); pmmpsh->iMediaType = iMediaType; LoadString(ghInstance, IDS_DETAILS, szTabName, sizeof(szTabName)/sizeof(TCHAR)); ShowPropSheet(szTabName,FileDetailsDlg,DLG_FILE_DETAILS,hwndParent,pszCaption,(LPARAM)pmmpsh);
return TRUE; }
BOOL ResolveLink(LPTSTR szPath, LPTSTR szResolved, LONG cbSize) { IShellLink *psl = NULL; HRESULT hres;
hres = SHCoCreateInstance(NULL, &CLSID_ShellLink, NULL, &IID_IShellLink, &psl); if (SUCCEEDED(hres)) { WCHAR wszPath[MAX_PATH]; IPersistFile *ppf;
psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf); if (ppf) {
wcscpy(wszPath, szPath); hres = ppf->lpVtbl->Load(ppf, wszPath, 0); ppf->lpVtbl->Release(ppf);
if (FAILED(hres)) { psl->lpVtbl->Release(psl); psl = NULL; } } else { psl = NULL; } } if (psl) { // this reslve could fail.. should we really do NOUI?
psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI); psl->lpVtbl->GetPath(psl, szResolved, cbSize, NULL, SLGP_SHORTPATH); psl->lpVtbl->Release(psl); } if (SUCCEEDED(hres)) return TRUE; return FALSE; }
//---------------------------------------------------------------------------
// EXPORTED API
//---------------------------------------------------------------------------
/*----------------------------------------------------------
Purpose: Standard shell entry-point
Returns: standard Cond: -- */ STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv) {
// We are supposed return the class object for this class. Instead
// of fully implementing it in this DLL, we just call a helper
// function in the shell DLL which creates a default class factory
// object for us. When its CreateInstance member is called, it
// will call back our create instance function.
//
if (IsEqualIID(rclsid, &CLSID_mmsePropSheetHandler)) { return SHCreateDefClassObject( riid, // Interface ID
ppv, // Non-null to aggregate
mmpsh_CreatePSHInstance, // Callback function
&g_cRef, // Reference count of this DLL
&IID_IShellExtInit); // Init interface
} return ResultFromScode(REGDB_E_CLASSNOTREG); }
//****************************************************************************
// STDAPI DllCanUnLoadNow()
//
// This function is called by shell
//
//****************************************************************************
STDAPI DllCanUnloadNow(void) { HRESULT hr;
if (0 == g_cRef) { DPF("DllCanUnloadNow says OK (Ref=%d)", g_cRef);
hr = ResultFromScode(S_OK); } else { DPF("DllCanUnloadNow says FALSE (Ref=%d)", g_cRef);
hr = ResultFromScode(S_FALSE); } return hr; }
|