windows-nt/Source/XPSP1/NT/shell/osshell/control/mmsys/sndfile.c
2020-09-26 16:20:57 +08:00

552 lines
16 KiB
C

/*
***************************************************************
* sndfile.c
*
* This file contains the code to fill up the list and combo boxes,
* show the RIFF Dibs and the current sound mappings
*
* Copyright 1993, Microsoft Corporation
*
* History:
*
* 07/94 - VijR (Created)
*
***************************************************************
*/
#include <windows.h>
#include <mmsystem.h>
#include <string.h>
#include <ole2.h>
#include <prsht.h>
#include <cpl.h>
#include "mmcpl.h"
#include "draw.h"
#include "sound.h"
/*
***************************************************************
* Globals
***************************************************************
*/
HSOUND ghse;
/*
***************************************************************
* extern
***************************************************************
*/
extern TCHAR gszMediaDir[];
extern TCHAR gszCurDir[];
extern BOOL gfWaveExists; // indicates wave device in system.
extern BOOL gfChanged; // Is set TRUE if any changes are made
extern BOOL gfNewScheme;
//Globals used in painting disp chunk display.
extern HTREEITEM ghOldItem;
/*
***************************************************************
* Defines
***************************************************************
*/
#define DF_PM_SETBITMAP (WM_USER+1)
#define FOURCC_INFO mmioFOURCC('I','N','F','O')
#define FOURCC_DISP mmioFOURCC('D','I','S','P')
#define FOURCC_INAM mmioFOURCC('I','N','A','M')
#define FOURCC_ISBJ mmioFOURCC('I','S','B','J')
#define MAXDESCLEN 220
/*
***************************************************************
* Prototypes
***************************************************************
*/
HANDLE PASCAL GetRiffDisp (HMMIO);
BOOL PASCAL ShowSoundMapping (HWND, PEVENT);
BOOL PASCAL ChangeSoundMapping (HWND, LPTSTR, PEVENT);
BOOL PASCAL PlaySoundFile (HWND, LPTSTR);
BOOL PASCAL ChangeSetting (LPTSTR*, LPTSTR);
LPTSTR PASCAL NiceName(LPTSTR sz, BOOL fNukePath);
// Stuff in dib.c
//
HPALETTE WINAPI bmfCreateDIBPalette(HANDLE);
HBITMAP WINAPI bmfBitmapFromDIB(HANDLE, HPALETTE);
// Stuff in drivers.c
//
LPTSTR lstrchr (LPTSTR, TCHAR);
int lstrnicmp (LPTSTR, LPTSTR, size_t);
// Stuff in scheme.c
//
void PASCAL AddMediaPath (LPTSTR, LPTSTR);
/*
***************************************************************
***************************************************************
*/
STATIC void NEAR PASCAL ChopPath(LPTSTR lpszFile)
{
TCHAR szTmp[MAX_PATH];
size_t cchTest = lstrlen (gszCurDir);
szTmp[0] = TEXT('\0');
ExpandEnvironmentStrings(lpszFile, (LPTSTR)szTmp, MAXSTR);
lstrcpy(lpszFile,szTmp);
if (gszCurDir[ cchTest-1 ] == TEXT('\\'))
--cchTest;
lstrcpy((LPTSTR)szTmp, lpszFile);
if (!lstrnicmp((LPTSTR)szTmp, (LPTSTR)gszCurDir, cchTest))
{
if (szTmp[ cchTest ] == TEXT('\\'))
{
lstrcpy(lpszFile, (LPTSTR)(szTmp+cchTest+1));
}
}
}
/*
***************************************************************
* QualifyFileName
*
* Description:
* Verifies the existence and readability of a file.
*
* Parameters:
* LPTSTR lpszFile - name of file to check.
* LPTSTR lpszPath - returning full pathname of file.
* int csSize - Size of return buffer
*
* Returns: BOOL
* True if absolute path exists
*
***************************************************************
*/
BOOL PASCAL QualifyFileName(LPTSTR lpszFile, LPTSTR lpszPath, int cbSize, BOOL fTryCurDir)
{
BOOL fErrMode;
BOOL f = FALSE;
BOOL fHadEnvStrings;
TCHAR szTmpFile[MAXSTR];
int len;
BOOL fTriedCurDir;
TCHAR* pszFilePart;
HFILE hFile;
if (!lpszFile)
return FALSE;
fHadEnvStrings = (lstrchr (lpszFile, TEXT('%')) != NULL) ? TRUE : FALSE;
ExpandEnvironmentStrings (lpszFile, (LPTSTR)szTmpFile, MAXSTR);
len = lstrlen((LPTSTR)szTmpFile)+1;
fErrMode = SetErrorMode(TRUE); // we will handle errors
AddExt (szTmpFile, cszWavExt);
fTriedCurDir = FALSE;
TryOpen:
hFile = (HFILE)HandleToUlong(CreateFile(szTmpFile,GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
if (-1 != hFile)
{
if (fHadEnvStrings)
lstrcpyn(lpszPath, lpszFile, cbSize);
else
GetFullPathName(szTmpFile,cbSize/sizeof(TCHAR),lpszPath,&pszFilePart);
f = TRUE;
CloseHandle(LongToHandle(hFile));
}
else
/*
** If the test above failed, we try converting the name to OEM
** character set and try again.
*/
{
/*
** First, is it in MediaPath?
**
*/
if (lstrchr (lpszFile, TEXT('\\')) == NULL)
{
TCHAR szCurDirFile[MAXSTR];
AddMediaPath (szCurDirFile, lpszFile);
if (-1 != (HFILE)HandleToUlong(CreateFile(szCurDirFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
{
GetFullPathName(szCurDirFile,cbSize/sizeof(TCHAR),lpszPath,&pszFilePart);
f = TRUE;
goto DidOpen;
}
}
//AnsiToOem((LPTSTR)szTmpFile, (LPTSTR)szTmpFile);
if (-1 != (HFILE)HandleToUlong(CreateFile(szTmpFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
{
if (fHadEnvStrings)
lstrcpyn(lpszPath, lpszFile, cbSize);
else
GetFullPathName(szTmpFile,cbSize/sizeof(TCHAR),lpszPath,&pszFilePart);
f = TRUE;
}
else if (fTryCurDir && !fTriedCurDir)
{
TCHAR szCurDirFile[MAXSTR];
//OemToAnsi((LPTSTR)szTmpFile, (LPTSTR)szTmpFile);
lstrcpy (szCurDirFile, gszCurDir);
lstrcat (szCurDirFile, cszSlash);
lstrcat (szCurDirFile, szTmpFile);
lstrcpy((LPTSTR)szTmpFile, (LPTSTR)szCurDirFile);
fTriedCurDir = TRUE;
goto TryOpen;
}
}
DidOpen:
SetErrorMode(fErrMode);
return f;
}
/*
***************************************************************
* ChangeSoundMapping
*
* Description:
* Change the sound file associated with a sound
*
* Parameters:
* HWND hDlg - handle to dialog window.
* LPTSTR lpszFile - New filename for current event
* LPTSTR lpszDir - New foldername for current event
* LPTSTR lpszPath - New absolute path for file
*
* Returns: BOOL
*
***************************************************************
*/
BOOL PASCAL ChangeSoundMapping(HWND hDlg, LPTSTR lpszPath, PEVENT pEvent)
{
TCHAR szValue[MAXSTR];
if (!pEvent)
{
if(!ghse)
EnableWindow(GetDlgItem(hDlg, ID_PLAY), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_SOUND_FILES), FALSE);
ShowSoundMapping(hDlg,NULL);
return TRUE;
}
szValue[0] = TEXT('\0');
if (!ChangeSetting((LPTSTR *)&(pEvent->pszPath), lpszPath))
return FALSE;
if(!ghse)
EnableWindow(GetDlgItem(hDlg, ID_PLAY), TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_SOUND_FILES), TRUE);
ShowSoundMapping(hDlg,pEvent);
gfChanged = TRUE;
gfNewScheme = TRUE;
PropSheet_Changed(GetParent(hDlg),hDlg);
return TRUE;
}
STATIC void SetTreeStateIcon(HWND hDlg, int iImage)
{
TV_ITEM tvi;
HWND hwndTree = GetDlgItem(hDlg, IDC_EVENT_TREE);
HTREEITEM hti;
if (ghOldItem)
hti = ghOldItem;
else
hti = TreeView_GetSelection(hwndTree);
if (hti)
{
tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.hItem = hti;
tvi.iImage = tvi.iSelectedImage = iImage;
TreeView_SetItem(hwndTree, &tvi);
RedrawWindow(hwndTree, NULL, NULL, RDW_ERASE|RDW_ERASENOW|RDW_INTERNALPAINT|RDW_INVALIDATE | RDW_UPDATENOW);
}
}
/*
***************************************************************
* ShowSoundMapping
*
* Description:
* Highlights the label and calls ShowSoundDib to display the Dib
* associated with the current event.
*
* Parameters:
* HWND hDlg - handle to dialog window.
*
* Returns: BOOL
*
***************************************************************
*/
BOOL PASCAL ShowSoundMapping(HWND hDlg, PEVENT pEvent)
{
TCHAR szOut[MAXSTR];
if (!pEvent)
{
EnableWindow(GetDlgItem(hDlg, IDC_SOUND_FILES), FALSE);
EnableWindow(GetDlgItem(hDlg, ID_BROWSE), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_NAME), FALSE);
// wsprintf((LPTSTR)szCurSound, (LPTSTR)gszSoundGrpStr, (LPTSTR)gszNull);
}
else
{
EnableWindow(GetDlgItem(hDlg, IDC_SOUND_FILES), TRUE);
EnableWindow(GetDlgItem(hDlg, ID_BROWSE), TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_NAME), TRUE);
// wsprintf((LPTSTR)szCurSound, (LPTSTR)gszSoundGrpStr, (LPTSTR)pEvent->pszEventLabel);
}
//SetWindowText(GetDlgItem(hDlg, IDC_SOUNDGRP), (LPTSTR)szCurSound);
//RedrawWindow(GetDlgItem(hDlg, IDC_EVENT_TREE), NULL, NULL, RDW_ERASE|RDW_ERASENOW|RDW_INTERNALPAINT|RDW_INVALIDATE | RDW_UPDATENOW);
if (!pEvent || !QualifyFileName(pEvent->pszPath, szOut, sizeof(szOut), FALSE))
{
int iLen;
if(!ghse)
EnableWindow(GetDlgItem(hDlg, ID_PLAY), FALSE);
if(pEvent)
iLen = lstrlen(pEvent->pszPath);
if (pEvent && iLen > 0)
{
if (iLen < 5)
{
lstrcpy(pEvent->pszPath, gszNull);
gfChanged = TRUE;
gfNewScheme = TRUE;
PropSheet_Changed(GetParent(hDlg),hDlg);
}
else
{
TCHAR szMsg[MAXSTR];
TCHAR szTitle[MAXSTR];
LoadString(ghInstance, IDS_NOSNDFILE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
wsprintf(szMsg, szTitle, pEvent->pszPath);
LoadString(ghInstance, IDS_NOSNDFILETITLE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
if (MessageBox(hDlg, szMsg, szTitle, MB_YESNO) == IDNO)
{
lstrcpy(pEvent->pszPath, gszNull);
ComboBox_SetText(GetDlgItem(hDlg, IDC_SOUND_FILES), gszNone);
gfChanged = TRUE;
gfNewScheme = TRUE;
PropSheet_Changed(GetParent(hDlg),hDlg);
if (pEvent && pEvent->fHasSound)
{
SetTreeStateIcon(hDlg, 2);
pEvent->fHasSound = FALSE;
}
}
else
{
lstrcpy(szOut ,pEvent->pszPath);
ChopPath((LPTSTR)szOut);
NiceName((LPTSTR)szOut, FALSE);
ComboBox_SetText(GetDlgItem(hDlg, IDC_SOUND_FILES), szOut);
if (!pEvent->fHasSound)
{
SetTreeStateIcon(hDlg, 1);
pEvent->fHasSound = TRUE;
}
}
}
}
else
{
ComboBox_SetText(GetDlgItem(hDlg, IDC_SOUND_FILES), gszNone);
if (pEvent && pEvent->fHasSound)
{
SetTreeStateIcon(hDlg, 2);
pEvent->fHasSound = FALSE;
}
}
}
else
{
if(!ghse)
EnableWindow(GetDlgItem(hDlg, ID_PLAY),gfWaveExists);
ChopPath((LPTSTR)szOut);
NiceName((LPTSTR)szOut, FALSE);
ComboBox_SetText(GetDlgItem(hDlg, IDC_SOUND_FILES), szOut);
if (!pEvent->fHasSound)
{
SetTreeStateIcon(hDlg, 1);
pEvent->fHasSound = TRUE;
}
}
return TRUE;
}
/*
***************************************************************
* PlaySoundFile
*
* Description:
* Plays the given sound file.
*
* Parameters:
* HWND hDlg - Window handle
* LPTSTR lpszFile - absolute path of File to play.
*
* Returns: BOOL
*
***************************************************************
*/
BOOL PASCAL PlaySoundFile(HWND hDlg, LPTSTR lpszFile)
{
TCHAR szOut[MAXSTR];
TCHAR szTemp[MAXSTR];
BOOL rb = TRUE;
if (!QualifyFileName(lpszFile, szTemp, sizeof(szTemp), FALSE))
{
ErrorBox(hDlg, IDS_ERRORPLAY, lpszFile);
rb = FALSE;
}
else{
MMRESULT err = MMSYSERR_NOERROR;
ExpandEnvironmentStrings (szTemp, szOut, MAXSTR);
if((soundOpen(szOut, hDlg, &ghse) != MMSYSERR_NOERROR) || ((err = soundPlay(ghse)) != MMSYSERR_NOERROR))
{
if (err >= (MMRESULT)MMSYSERR_LASTERROR)
ErrorBox(hDlg, IDS_ERRORUNKNOWNPLAY, lpszFile);
else if (err == (MMRESULT)MMSYSERR_ALLOCATED)
ErrorBox(hDlg, IDS_ERRORDEVBUSY, lpszFile);
else
ErrorBox(hDlg, IDS_ERRORFILEPLAY, lpszFile);
ghse = NULL;
rb = FALSE;
}
}
return rb;
}
/*
***************************************************************
* ChangeSetting
*
* Description:
* Displays the labels of all the links present in the lpszDir folder
* in the LB_SOUNDS listbox
*
* Parameters:
* HWND hDlg - Window handle
* LPTSTR lpszDir - Name of sound folder whose files must be displayed.
*
* Returns: BOOL
*
***************************************************************
*/
BOOL PASCAL ChangeSetting(LPTSTR *npOldString, LPTSTR lpszNew)
{
int len = (lstrlen(lpszNew)*sizeof(TCHAR))+sizeof(TCHAR);
if (*npOldString)
{
*npOldString = (LPTSTR)LocalReAlloc((HLOCAL)*npOldString,
len, LMEM_MOVEABLE);
}
else
{
DPF("Current file Does not exist\n");
*npOldString = (LPTSTR)LocalAlloc(LPTR, len);
}
if (*npOldString == NULL)
{
DPF("ReAlloc Failed\n");
return FALSE;
}
lstrcpy(*npOldString, lpszNew);
DPF("New file is %s\n", (LPTSTR)*npOldString);
return TRUE;
}
STATIC HANDLE PASCAL GetRiffDisp(HMMIO hmmio)
{
MMCKINFO ck;
MMCKINFO ckRIFF;
HANDLE h = NULL;
LONG lSize;
DWORD dw;
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;
while (!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;
}
}
//
// if we have both a picture and a title, then exit.
//
if (h != NULL)
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;
exit:
return h;
}