|
|
/* (C) Copyright Microsoft Corporation 1991-1994. All Rights Reserved */ /* SoundRec.c
* * SoundRec main loop etc. * Revision History. * 4/2/91 LaurieGr (AKA LKG) Ported to WIN32 / WIN16 common code * 21/2/94 LaurieGr Merged Daytona and Motown versions * LaurieGr Merged common button and trackbar code from StephenE */
#undef NOWH // Allow SetWindowsHook and WH_*
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <htmlhelp.h>
#ifdef USE_MMCNTRLS
#include "mmcntrls.h"
#else
#include <commctrl.h>
#include "buttons.h"
#endif
#include <mmreg.h>
#define INCLUDE_OLESTUBS
#include "soundrec.h"
#include "srecids.h"
#include "fixreg.h"
#include "reg.h"
#include "convert.h"
#include "helpids.h"
#include <stdarg.h>
#include <stdio.h>
/* globals */
BOOL gfUserClose; // user-driven shutdown
HWND ghwndApp; // main application window
HINSTANCE ghInst; // program instance handle
TCHAR gachFileName[_MAX_PATH];// current file name (or UNTITLED)
BOOL gfDirty; // file was modified and not saved?
BOOL gfClipboard; // we have data in clipboard
int gfErrorBox; // TRUE if we have a message box active
HICON ghiconApp; // app's icon
HWND ghwndWaveDisplay; // waveform display window handle
HWND ghwndScroll; // scroll bar control window handle
HWND ghwndPlay; // Play button window handle
HWND ghwndStop; // Stop button window handle
HWND ghwndRecord; // Record button window handle
#ifdef THRESHOLD
HWND ghwndSkipStart; // Needed to enable/disable...
HWND ghwndSkipEnd; // ...the skip butons
#endif //THRESHOLD
HWND ghwndForward; // [>>] button
HWND ghwndRewind; // [<<] button
BOOL gfWasPlaying; // was playing before scroll, fwd, etc.
BOOL gfWasRecording; // was recording before scroll etc.
BOOL gfPaused; // are we paused now?
BOOL gfPausing; // are we stopping into a paused state?
HWAVE ghPausedWave; // holder for the paused wave handle
int gidDefaultButton; // which button should have input focus
BOOL gfEmbeddedObject; // Are we editing an embedded object?
BOOL gfRunWithEmbeddingFlag; // TRUE if we are run with "-Embedding"
BOOL gfHideAfterPlaying; BOOL gfShowWhilePlaying; BOOL gfInUserDestroy = FALSE; TCHAR chDecimal = TEXT('.'); BOOL gfLZero = 1; // do we use leading zeros?
BOOL gfIsRTL = 0; // no compile BIDI
UINT guiACMHlpMsg = 0; // help message from ACM, none == 0
//Data used for supporting context menu help
BOOL bF1InMenu=FALSE; //If true F1 was pressed on a menu item.
UINT currMenuItem=0; //The current selected menu item if any.
BITMAPBTN tbPlaybar[] = { { ID_REWINDBTN - ID_BTN_BASE, ID_REWINDBTN, 0 }, /* index 0 */ { ID_FORWARDBTN - ID_BTN_BASE, ID_FORWARDBTN,0 }, /* index 1 */ { ID_PLAYBTN - ID_BTN_BASE, ID_PLAYBTN, 0 }, /* index 2 */ { ID_STOPBTN - ID_BTN_BASE, ID_STOPBTN, 0 }, /* index 3 */ { ID_RECORDBTN - ID_BTN_BASE, ID_RECORDBTN, 0 } /* index 4 */ };
#include <msacmdlg.h>
#ifdef CHICAGO
/* these id's are part of the main windows help file */ #define IDH_AUDIO_CUST_ATTRIB 2403
#define IDH_AUDIO_CUST_FORMAT 2404
#define IDH_AUDIO_CUST_NAME 2405
#define IDH_AUDIO_CUST_REMOVE 2406
#define IDH_AUDIO_CUST_SAVEAS 2407
const DWORD aChooserHelpIds[] = { IDD_ACMFORMATCHOOSE_CMB_FORMAT, IDH_AUDIO_CUST_ATTRIB, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, IDH_AUDIO_CUST_FORMAT, IDD_ACMFORMATCHOOSE_CMB_CUSTOM, IDH_AUDIO_CUST_NAME, IDD_ACMFORMATCHOOSE_BTN_DELNAME, IDH_AUDIO_CUST_REMOVE, IDD_ACMFORMATCHOOSE_BTN_SETNAME, IDH_AUDIO_CUST_SAVEAS, 0, 0 };
UINT guChooserContextMenu = 0; UINT guChooserContextHelp = 0; #endif
/*
* constants */ SZCODE aszNULL[] = TEXT(""); SZCODE aszClassKey[] = TEXT(".wav"); SZCODE aszIntl[] = TEXT("Intl");
/*
* statics */ static HHOOK hMsgHook;
/*
* functions */ BOOL SoundRec_OnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos); BOOL SoundRec_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT *lpdis); void SoundRec_ControlPanel(HINSTANCE hinst, HWND hwnd); BOOL NEAR PASCAL FreeWaveHeaders(void);
/*
* HelpMsgFilter - filter for F1 key in dialogs */ LRESULT CALLBACK HelpMsgFilter( int nCode, WPARAM wParam, LPARAM lParam) { LPMSG msg; if (nCode >= 0){ msg = (LPMSG)lParam; if ((msg->message == WM_KEYDOWN) && (LOWORD(msg->wParam) == VK_F1)) { // testing for <0 tests MSB whether int is 16 or 32 bits
// MSB set means key is down
if (( GetAsyncKeyState(VK_SHIFT) | GetAsyncKeyState(VK_CONTROL) | GetAsyncKeyState(VK_MENU)) < 0 ) //
// do nothing
//
; else { if(nCode == MSGF_MENU) { bF1InMenu = TRUE; SendMessage(ghwndApp, WM_COMMAND, IDM_HELPTOPICS, 0L); } } } } return CallNextHookEx(hMsgHook, nCode, wParam, lParam); }
/* WinMain(hInst, hPrev, lpszCmdLine, cmdShow)
* * The main procedure for the App. After initializing, it just goes * into a message-processing loop until it gets a WM_QUIT message * (meaning the app was closed). */ int WINAPI // returns exit code specified in WM_QUIT
WinMain( HINSTANCE hInst, // instance handle of current instance
HINSTANCE hPrev, // instance handle of previous instance
LPSTR lpszCmdLine, // null-terminated command line
int iCmdShow) // how window should be initially displayed
{ HWND hDlg; MSG rMsg;
//
// save instance handle for dialog boxes
//
ghInst = hInst;
DPF(TEXT("AppInit ...\n")); //
// call initialization procedure
//
if (!AppInit(hInst, hPrev)) { DPF(TEXT("AppInit failed\n")); return FALSE; }
//
// setup the message filter to handle grabbing F1 for this task
//
hMsgHook = SetWindowsHookEx(WH_MSGFILTER, HelpMsgFilter, ghInst, GetCurrentThreadId());
//
// display "SoundRec" dialog box
//
hDlg = CreateDialogParam( ghInst , MAKEINTRESOURCE(IDD_SOUNDRECBOX) , NULL , SoundRecDlgProc , iCmdShow ); if (hDlg) { //
// Polling messages from event queue
//
while (GetMessage(&rMsg, NULL, 0, 0)) { if (ghwndApp) { if (TranslateAccelerator(ghwndApp, ghAccel, &rMsg)) continue;
if (IsDialogMessage(ghwndApp,&rMsg)) continue; }
TranslateMessage(&rMsg); DispatchMessage(&rMsg); } }
//
// free the current document
//
DestroyWave();
//
// if the message hook was installed, remove it and free
// up our proc instance for it.
//
if (hMsgHook) { UnhookWindowsHookEx(hMsgHook); }
//
// random cleanup
//
DeleteObject(ghbrPanel);
if(gfOleInitialized) { FlushOleClipboard(); OleUninitialize(); gfOleInitialized = FALSE; }
return TRUE; }
/*
* Process file drop/drag options. */ void SoundRec_OnDropFiles( HWND hwnd, HDROP hdrop) { TCHAR szPath[_MAX_PATH];
if (DragQueryFile(hdrop, (UINT)(-1), NULL, 0) > 0) { //
// If user dragged/dropped a file regardless of keys pressed
// at the time, open the first selected file from file
// manager.
//
DragQueryFile(hdrop,0,szPath,SIZEOF(szPath)); SetActiveWindow(hwnd);
ResolveIfLink(szPath);
if (FileOpen(szPath)) { gfHideAfterPlaying = FALSE; //
// This is a bit hacked. The Ole caption should just never change.
//
if (gfEmbeddedObject && !gfLinked) { LPTSTR lpszObj, lpszApp; extern void SetOleCaption(LPTSTR lpsz);
DoOleSave(); AdviseSaved();
OleObjGetHostNames(&lpszApp,&lpszObj); lpszObj = (LPTSTR)FileName((LPCTSTR)lpszObj); SetOleCaption(lpszObj); } PostMessage(ghwndApp, WM_COMMAND, ID_PLAYBTN, 0L); } } DragFinish(hdrop); // Delete structure alocated
}
/* Pause(BOOL fBeginPause)
* * If <fBeginPause>, then if user is playing or recording do a StopWave(). * The next call to Pause() should have <fBeginPause> be FALSE -- this will * cause the playing or recording to be resumed (possibly at a new position * if <glWavePosition> changed. */ void Pause(BOOL fBeginPause) { if (fBeginPause) { if (ghWaveOut != NULL) { #ifdef NEWPAUSE
gfPausing = TRUE; gfPaused = FALSE; ghPausedWave = (HWAVE)ghWaveOut; #endif
gfWasPlaying = TRUE;
// User intentionally stopped us. Don't go away.
if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp)) gfCloseAtEndOfPlay = FALSE;
StopWave(); } else if (ghWaveIn != NULL) { #ifdef NEWPAUSE
gfPausing = TRUE; gfPaused = FALSE; ghPausedWave = (HWAVE)ghWaveIn; #endif
gfWasRecording = TRUE;
// User intentionally stopped us. Don't go away.
if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp)) gfCloseAtEndOfPlay = FALSE;
StopWave(); } } else { if (gfWasPlaying) { gfWasPlaying = FALSE; PlayWave(); #ifdef NEWPAUSE
gfPausing = FALSE; gfPaused = FALSE; #endif
} else if (gfWasRecording) { gfWasRecording = FALSE; RecordWave(); #ifdef NEWPAUSE
gfPausing = FALSE; gfPaused = FALSE; #endif
} } }
void DoHtmlHelp() { //note, using ANSI version of function because UNICODE is foobar in NT5 builds
char chDst[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, gachHtmlHelpFile, -1, chDst, MAX_PATH, NULL, NULL); HtmlHelpA(GetDesktopWindow(), chDst, HH_DISPLAY_TOPIC, 0L); }
void ProcessHelp(HWND hwnd) { static TCHAR HelpFile[] = TEXT("SOUNDREC.HLP"); //Handle context menu help
if(bF1InMenu) { switch(currMenuItem) { case IDM_NEW: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_NEW); break; case IDM_OPEN: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_OPEN); break; case IDM_SAVE: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_SAVE); break; case IDM_SAVEAS: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_SAVE_AS); break; case IDM_REVERT: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_REVERT); break; case IDM_PROPERTIES: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_PROPERTIES); break; case IDM_EXIT: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_FILE_EXIT); break; case IDM_COPY: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_COPY); break; case IDM_PASTE_INSERT: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_PASTE_INSERT); break; case IDM_PASTE_MIX: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_PASTE_MIX); break; case IDM_INSERTFILE: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_INSERT_FILE); break; case IDM_MIXWITHFILE: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_MIX_WITH_FILE); break; case IDM_DELETEBEFORE: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_DELETE_BEFORE_CURRENT_POSITION); break; case IDM_DELETEAFTER: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_DELETE_AFTER_CURRENT_POSITION); break; case IDM_VOLUME: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EDIT_AUDIO_PROPERTIES); break; case IDM_INCREASEVOLUME: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_INCREASE_VOLUME); break; case IDM_DECREASEVOLUME: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_DECREASE_VOLUME); break; case IDM_MAKEFASTER: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_INCREASE_SPEED); break; case IDM_MAKESLOWER: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_DECREASE_SPEED); break; case IDM_ADDECHO: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_ADD_ECHO); break; case IDM_REVERSE: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_EFFECTS_REVERSE); break; case IDM_HELPTOPICS: case IDM_INDEX: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_HELP_HELP_TOPICS); break; case IDM_ABOUT: WinHelp(hwnd, HelpFile, HELP_CONTEXTPOPUP, IDH_SOUNDREC_SNDRC_CS_HELP_ABOUT); break; default://In the default case just display the HTML Help.
DoHtmlHelp(); } bF1InMenu = FALSE; //This flag will be set again if F1 is pressed in a menu.
} else DoHtmlHelp(); }
/*
* SoundRec_OnCommand */ BOOL SoundRec_OnCommand( HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {
if (gfHideAfterPlaying && id != ID_PLAYBTN) { DPF(TEXT("Resetting HideAfterPlaying\n")); gfHideAfterPlaying = FALSE; }
switch (id) { case IDM_NEW:
if (PromptToSave(FALSE, FALSE) == enumCancel) return FALSE; #ifdef CHICAGO
if (FileNew(FMT_DEFAULT,TRUE,FALSE)) #else
if (FileNew(FMT_DEFAULT,TRUE,TRUE)) #endif
{ /* return to being a standalone */ gfHideAfterPlaying = FALSE; }
break;
case IDM_OPEN:
if (FileOpen(NULL)) { /* return to being a standalone */ gfHideAfterPlaying = FALSE; }
if (IsWindowEnabled(ghwndPlay)) { SetDlgFocus(ghwndPlay); } break;
case IDM_SAVE: // also OLE UPDATE
if (!gfEmbeddedObject || gfLinked) { if (!FileSave(FALSE)) break; } else { DoOleSave(); gfDirty = FALSE; } break;
case IDM_SAVEAS: if (FileSave(TRUE)) { /* return to being a standalone */ gfHideAfterPlaying = FALSE; } break;
case IDM_REVERT: UpdateWindow(hwnd);
// User intentionally stopped us. Don't go away.
if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp)) gfCloseAtEndOfPlay = FALSE;
StopWave(); SnapBack();
if (FileRevert()) { /* return to being a standalone */ gfHideAfterPlaying = FALSE; } break;
case IDM_EXIT: PostMessage(hwnd, WM_CLOSE, 0, 0L); return TRUE;
case IDCANCEL:
// User intentionally stopped us. Don't go away.
if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp)) gfCloseAtEndOfPlay = FALSE;
StopWave(); SnapBack(); break;
case IDM_COPY: if (!gfOleInitialized) { InitializeOle(ghInst); if (gfStandalone && gfOleInitialized) CreateStandaloneObject(); } TransferToClipboard(); gfClipboard = TRUE; break;
case IDM_PASTE_INSERT: case IDM_INSERTFILE: UpdateWindow(hwnd);
// User intentionally stopped us. Don't go away.
if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp)) gfCloseAtEndOfPlay = FALSE;
StopWave(); SnapBack(); InsertFile(id == IDM_PASTE_INSERT); break;
case IDM_PASTE_MIX: case IDM_MIXWITHFILE: UpdateWindow(hwnd);
// User intentionally stopped us. Don't go away.
if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp)) gfCloseAtEndOfPlay = FALSE;
StopWave(); SnapBack(); MixWithFile(id == IDM_PASTE_MIX); break;
case IDM_DELETEBEFORE: UpdateWindow(hwnd); Pause(TRUE); DeleteBefore(); Pause(FALSE); break;
case IDM_DELETE: if (glWaveSamplesValid == 0L) return 0L;
glWavePosition = 0L;
// fall through to delete after.
case IDM_DELETEAFTER: UpdateWindow(hwnd); Pause(TRUE); DeleteAfter(); Pause(FALSE); break;
#ifdef THRESHOLD
// Threshold was an experiment to allow facilities to skip to the start
// of the sound or to the end of the sound. The trouble was that it
// required the ability to detect silence and different sound cards in
// different machines with different background noises gave quite different
// ideas of what counted as silence. Manual control over the threshold level
// did sort-of work but was just too complicated. It really wanted to be
// intuitive or intelligent (or both).
case IDM_SKIPTOSTART: case ID_SKIPSTARTBTN: UpdateWindow(hwnd); Pause(TRUE); SkipToStart(); Pause(FALSE); break;
case ID_SKIPENDBTN: case IDM_SKIPTOEND: UpdateWindow(hwnd); Pause(TRUE); SkipToEnd(); Pause(FALSE); break;
case IDM_INCREASETHRESH: IncreaseThresh(); break;
case IDM_DECREASETHRESH: DecreaseThresh(); break; #endif //THRESHOLD
case IDM_INCREASEVOLUME: UpdateWindow(hwnd); Pause(TRUE); ChangeVolume(TRUE); Pause(FALSE); break;
case IDM_DECREASEVOLUME: UpdateWindow(hwnd); Pause(TRUE); ChangeVolume(FALSE); Pause(FALSE); break;
case IDM_MAKEFASTER: UpdateWindow(hwnd); Pause(TRUE); MakeFaster(); Pause(FALSE); break;
case IDM_MAKESLOWER: UpdateWindow(hwnd); Pause(TRUE); MakeSlower(); Pause(FALSE); break;
case IDM_ADDECHO: UpdateWindow(hwnd); Pause(TRUE); AddEcho(); Pause(FALSE); break;
#if defined(REVERB)
case IDM_ADDREVERB: UpdateWindow(hwnd); Pause(TRUE); AddReverb(); Pause(FALSE); break; #endif //REVERB
case IDM_REVERSE: UpdateWindow(hwnd); Pause(TRUE); Reverse(); Pause(FALSE); break;
case IDM_VOLUME: SoundRec_ControlPanel(ghInst, hwnd); break;
case IDM_PROPERTIES: { WAVEDOC wd; SGLOBALS sg; DWORD dw;
wd.pwfx = gpWaveFormat; wd.pbdata = gpWaveSamples; wd.cbdata = wfSamplesToBytes(gpWaveFormat, glWaveSamplesValid); wd.fChanged = FALSE; wd.pszFileName = (LPTSTR)FileName(gachFileName); //
// Need to extract these from the file
//
wd.hIcon = NULL; wd.pszCopyright = gpszInfo; wd.lpv = &sg;
//
// modify globals w/o returning from prop dialog
//
sg.ppwfx = &gpWaveFormat; sg.pcbwfx = &gcbWaveFormat; sg.pcbdata = &dw; sg.ppbdata = &gpWaveSamples; sg.plSamplesValid = &glWaveSamplesValid; sg.plSamples = &glWaveSamples; sg.plWavePosition = &dw;
SoundRec_Properties(hwnd, ghInst, &wd); break; }
#ifndef CHICAGO
case IDM_INDEX: WinHelp(hwnd, gachHelpFile, HELP_INDEX, 0L); break;
case IDM_SEARCH: WinHelp(hwnd, gachHelpFile, HELP_PARTIALKEY, (DWORD)(LPTSTR)aszNULL); break; #else
case IDM_HELPTOPICS: ProcessHelp(hwnd); break; #endif
case IDM_USINGHELP: WinHelp(hwnd, (LPTSTR)NULL, HELP_HELPONHELP, 0L); break;
case IDM_ABOUT: { LPTSTR lpAbout = NULL; lpAbout = SoundRec_GetFormatName(gpWaveFormat); ShellAbout(hwnd, gachAppTitle, lpAbout, (HICON)SendMessage(hwnd, WM_QUERYDRAGICON, 0, 0L)); // , ghiconApp
if (lpAbout) GlobalFreePtr(lpAbout); break; }
case ID_REWINDBTN: #if 1
//Related to BombayBug 1609
Pause(TRUE); glWavePosition = 0L; Pause(FALSE); UpdateDisplay(FALSE); #else
//Behave as if the user pressed the 'Home' key
//Call the handler directly
SoundRec_OnHScroll(hwnd,ghwndScroll,SB_TOP,0); #endif
break;
case ID_PLAYBTN: // checks for empty file moved to PlayWave in wave.c
// if at end of file, go back to beginning.
if (glWavePosition == glWaveSamplesValid) glWavePosition = 0;
PlayWave(); break;
case ID_STOPBTN: // User intentionally stopped us. Don't go away.
if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp)) gfCloseAtEndOfPlay = FALSE;
StopWave();
// I added this update because StopWave doesn't call it and
// if you hit stop too quickly, the buttons aren't updated
// Should StopWave() be calling UpdateDisplay()?
UpdateDisplay(TRUE); SnapBack(); break;
case ID_RECORDBTN: /* Never let us be forced to quit after recording. */ gfHideAfterPlaying = FALSE; RecordWave(); break;
case ID_FORWARDBTN: #if 1
//Bombay bug 1610
//Behave as if the user pressed the 'End' key
Pause(TRUE); glWavePosition = glWaveSamplesValid; Pause(FALSE); UpdateDisplay(FALSE); #else
//Call the handler directly
SoundRec_OnHScroll(hwnd,ghwndScroll,SB_BOTTOM,0); #endif
break;
default: return FALSE; } return TRUE; } /* SoundRec_OnCommand */
/*
* handle WM_INIT from SoundRecDlgProc */ void SoundRec_OnInitMenu(HWND hwnd, HMENU hMenu) { BOOL fUntitled; // file is untitled?
UINT mf;
//
// see if we can insert/mix into this file.
//
mf = (glWaveSamplesValid == 0 || IsWaveFormatPCM(gpWaveFormat)) ? MF_ENABLED : MF_GRAYED;
EnableMenuItem(hMenu, IDM_INSERTFILE , mf); EnableMenuItem(hMenu, IDM_MIXWITHFILE , mf);
//
// see if any CF_WAVE data is in the clipboard
//
mf = ( (mf == MF_ENABLED) && IsClipboardFormatAvailable(CF_WAVE) //DOWECARE (|| IsClipboardNative())
) ? MF_ENABLED : MF_GRAYED;
EnableMenuItem(hMenu, IDM_PASTE_INSERT, mf); EnableMenuItem(hMenu, IDM_PASTE_MIX , mf);
//
// see if we can delete before or after the current position.
//
EnableMenuItem(hMenu, IDM_DELETEBEFORE, glWavePosition > 0 ? MF_ENABLED : MF_GRAYED); EnableMenuItem(hMenu, IDM_DELETEAFTER, (glWaveSamplesValid-glWavePosition) > 0 ? MF_ENABLED : MF_GRAYED);
//
// see if we can do editing operations on the file.
//
mf = IsWaveFormatPCM(gpWaveFormat) ? MF_ENABLED : MF_GRAYED;
EnableMenuItem(hMenu, IDM_INCREASEVOLUME , mf); EnableMenuItem(hMenu, IDM_DECREASEVOLUME , mf); EnableMenuItem(hMenu, IDM_MAKEFASTER , mf); EnableMenuItem(hMenu, IDM_MAKESLOWER , mf); EnableMenuItem(hMenu, IDM_ADDECHO , mf); EnableMenuItem(hMenu, IDM_REVERSE , mf);
/* enable "Revert..." if the file was opened or saved
* (not created using "New") and is currently dirty * and we're not using an embedded object */ fUntitled = (lstrcmp(gachFileName, aszUntitled) == 0); EnableMenuItem( hMenu, IDM_REVERT, (!fUntitled && gfDirty && !gfEmbeddedObject) ? MF_ENABLED : MF_GRAYED);
if (gfHideAfterPlaying) { DPF(TEXT("Resetting HideAfterPlaying")); gfHideAfterPlaying = FALSE; }
} /* SoundRec_OnInitMenu() */
/*
* Handle WM_HSCROLL from SoundRecDlgProc * */ BOOL SoundRec_OnHScroll( HWND hwnd, HWND hwndCtl, UINT code, int pos) { BOOL fFineControl; long lNewPosition; // new position in wave buffer
LONG l;
LONG lBlockInc; LONG lInc;
fFineControl = (0 > GetKeyState(VK_SHIFT));
if (gfHideAfterPlaying) { DPF(TEXT("Resetting HideAfterPlaying")); gfHideAfterPlaying = FALSE; }
lBlockInc = wfBytesToSamples(gpWaveFormat,gpWaveFormat->nBlockAlign);
switch (code) { case SB_LINEUP: // left-arrow
// This is a mess. NT implemented SHIFT and Motown implemented CTRL
// To do about the same thing!!
if (fFineControl) lNewPosition = glWavePosition - 1; else { l = (GetKeyState(VK_CONTROL) < 0) ? (SCROLL_LINE_MSEC/10) : SCROLL_LINE_MSEC;
lNewPosition = glWavePosition - MulDiv(l, (long) gpWaveFormat->nSamplesPerSec, 1000L); } break;
case SB_PAGEUP: // left-page
// NEEDS SOMETHING SENSIBLE !!! ???
if (fFineControl) lNewPosition = glWavePosition - 10; else lNewPosition = glWavePosition - MulDiv((long) SCROLL_PAGE_MSEC, (long) gpWaveFormat->nSamplesPerSec, 1000L); break;
case SB_LINEDOWN: // right-arrow
if (fFineControl) lNewPosition = glWavePosition + 1; else { l = (GetKeyState(VK_CONTROL) & 0x8000) ? (SCROLL_LINE_MSEC/10) : SCROLL_LINE_MSEC; lInc = MulDiv(l, (long) gpWaveFormat->nSamplesPerSec, 1000L); lInc = (lInc < lBlockInc)?lBlockInc:lInc; lNewPosition = glWavePosition + lInc; } break;
case SB_PAGEDOWN: // right-page
if (fFineControl) lNewPosition = glWavePosition + 10; else { lInc = MulDiv((long) SCROLL_PAGE_MSEC, (long) gpWaveFormat->nSamplesPerSec, 1000L); lInc = (lInc < lBlockInc)?lBlockInc:lInc; lNewPosition = glWavePosition + lInc; } break;
case SB_THUMBTRACK: // thumb has been positioned
case SB_THUMBPOSITION: // thumb has been positioned
lNewPosition = MulDiv(glWaveSamplesValid, pos, SCROLL_RANGE); break;
case SB_TOP: // Home
lNewPosition = 0L; break;
case SB_BOTTOM: // End
lNewPosition = glWaveSamplesValid; break;
case SB_ENDSCROLL: // user released mouse button
/* resume playing, if necessary */ Pause(FALSE); return TRUE;
default: return TRUE;
}
//
// snap position to nBlockAlign
//
if (lNewPosition != glWaveSamplesValid) lNewPosition = wfSamplesToSamples(gpWaveFormat,lNewPosition);
if (lNewPosition < 0) lNewPosition = 0; if (lNewPosition > glWaveSamplesValid) lNewPosition = glWaveSamplesValid;
/* if user is playing or recording, pause until scrolling
* is complete */ Pause(TRUE);
glWavePosition = lNewPosition; UpdateDisplay(FALSE); return TRUE; } /* SoundRec_OnHScroll() */
/*
* WM_SYSCOLORCHANGE needs to be send to all child windows (esp. trackbars) */ void SoundRec_PropagateMessage( HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam) { HWND hwndChild;
for (hwndChild = GetWindow(hwnd, GW_CHILD); hwndChild != NULL; hwndChild = GetWindow(hwndChild, GW_HWNDNEXT)) { SendMessage(hwndChild, uMessage, wParam, lParam); } }
/* SoundRecDlgProc(hwnd, wMsg, wParam, lParam)
* * This function handles messages belonging to the main window dialog box. */ INT_PTR CALLBACK SoundRecDlgProc( HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {
switch (wMsg) {
case WM_BADREG: //
// Bad registry entries detected. Clean it up.
//
FixReg(hwnd); return TRUE;
case WM_COMMAND: return HANDLE_WM_COMMAND( hwnd, wParam, lParam , SoundRec_OnCommand );
case WM_INITDIALOG: //
// Start async registry check.
//
if (!IgnoreRegCheck()) BackgroundRegCheck(hwnd); //
// restore window position
//
SoundRec_GetSetRegistryRect(hwnd, SGSRR_GET); return SoundDialogInit(hwnd, (int)lParam);
case WM_SIZE: return FALSE; // let dialog manager do whatever else it wants
case WM_WININICHANGE: if (!lParam || !lstrcmpi((LPTSTR)lParam, aszIntl)) if (GetIntlSpecs()) UpdateDisplay(TRUE);
return (TRUE);
case WM_INITMENU: HANDLE_WM_INITMENU(hwnd, wParam, lParam, SoundRec_OnInitMenu); return (TRUE);
case WM_PASTE: UpdateWindow(hwnd);
// User intentionally stopped us. Don't go away.
if (gfCloseAtEndOfPlay && IsWindowVisible(ghwndApp)) gfCloseAtEndOfPlay = FALSE;
StopWave(); SnapBack(); InsertFile(TRUE); break;
case WM_DRAWITEM: return HANDLE_WM_DRAWITEM( hwnd, wParam, lParam, SoundRec_OnDrawItem );
case WM_NOTIFY: { LPNMHDR pnmhdr; pnmhdr = (LPNMHDR)lParam;
//
// tooltips notifications
//
switch (pnmhdr->code) { case TTN_NEEDTEXT: { LPTOOLTIPTEXT lpTt; lpTt = (LPTOOLTIPTEXT)lParam;
LoadString( ghInst, (UINT)lpTt->hdr.idFrom, lpTt->szText , SIZEOF(lpTt->szText) ); break; } default: break; } break; }
case WM_HSCROLL: HANDLE_WM_HSCROLL(hwnd, wParam, lParam, SoundRec_OnHScroll); return (TRUE);
case WM_SYSCOMMAND: if (gfHideAfterPlaying) { DPF(TEXT("Resetting HideAfterPlaying")); gfHideAfterPlaying = FALSE; }
switch (wParam & 0xFFF0) { case SC_CLOSE: PostMessage(hwnd, WM_CLOSE, 0, 0L); return TRUE; } break;
case WM_QUERYENDSESSION: if (PromptToSave(FALSE, TRUE) == enumCancel) return TRUE;
SoundRec_GetSetRegistryRect(hwnd, SGSRR_SET); #if 0 // this is bogus if someone else cancels the shutdown!
ShowWindow(hwnd, SW_HIDE); #endif
return FALSE;
case WM_SYSCOLORCHANGE: if (ghbrPanel) DeleteObject(ghbrPanel);
ghbrPanel = CreateSolidBrush(RGB_PANEL); SoundRec_PropagateMessage(hwnd, wMsg, wParam, lParam); break;
case WM_ERASEBKGND: { RECT rcClient; // client rectangle
GetClientRect(hwnd, &rcClient); FillRect((HDC)wParam, &rcClient, ghbrPanel); return TRUE; }
case MM_WOM_DONE: WaveOutDone((HWAVEOUT)wParam, (LPWAVEHDR) lParam); return TRUE;
case MM_WIM_DATA: WaveInData((HWAVEIN)wParam, (LPWAVEHDR) lParam); return TRUE;
case WM_TIMER: //
// timer message is only used for SYNCRONOUS drivers
//
UpdateDisplay(FALSE); return TRUE;
case WM_MENUSELECT: //Keep track of which menu bar item is currently popped up.
//This will be used for displaying the appropriate help from the mplayer.hlp file
//when the user presses the F1 key.
currMenuItem = (UINT)LOWORD(wParam); return TRUE;
case MM_WIM_CLOSE: return TRUE;
case WM_CTLCOLORBTN: case WM_CTLCOLORSTATIC: { POINT pt; pt.x = pt.y = 0; ClientToScreen((HWND)lParam, &pt); ScreenToClient(hwnd, &pt); SetBrushOrgEx((HDC) wParam, -pt.x, -pt.y, NULL); return (INT_PTR)ghbrPanel; }
case WM_CLOSE: if (gfInUserDestroy) { DestroyWindow(hwnd); return TRUE; }
DPF(TEXT("WM_CLOSE received\n")); gfUserClose = TRUE; if (gfHideAfterPlaying) { DPF(TEXT("Resetting HideAfterPlaying\n")); gfHideAfterPlaying = FALSE; } if (gfErrorBox) { // DPF("we have a error box up, ignoring WM_CLOSE.\n");
return TRUE; } if (PromptToSave(TRUE, FALSE) == enumCancel) return TRUE;
//
// Don't free our data before terminating. When the clipboard
// is flushed, we need to commit the data.
//
TerminateServer(); FileNew(FMT_DEFAULT, FALSE, FALSE); FreeACM(); FreeWaveHeaders();
//
// NOTE: TerminateServer() will destroy the window!
//
SoundRec_GetSetRegistryRect(hwnd, SGSRR_SET); return TRUE; //!!!
case WM_USER_DESTROY: DPF(TEXT("WM_USER_DESTROY\n"));
if (ghWaveOut || ghWaveIn) { DPF(TEXT("Ignoring, we have a device open.\n")); //
// Close later, when the play finishes.
//
return TRUE; } gfInUserDestroy = TRUE; PostMessage(hwnd, WM_CLOSE, 0, 0); return TRUE;
case WM_DESTROY: DPF(TEXT("WM_DESTROY\n"));
WinHelp(hwnd, gachHelpFile, HELP_QUIT, 0L); ghwndApp = NULL;
//
// Tell my app to die
//
PostQuitMessage(0); return TRUE;
case WM_DROPFILES: HANDLE_WM_DROPFILES(hwnd, wParam, lParam, SoundRec_OnDropFiles); break;
default: #ifdef CHICAGO
//
// if we have an ACM help message registered see if this
// message is it.
//
if (guiACMHlpMsg && wMsg == guiACMHlpMsg) { //
// message was sent from ACM because the user
// clicked on the HELP button on the chooser dialog.
// report help for that dialog.
//
WinHelp(hwnd, gachHelpFile, HELP_CONTEXT, IDM_NEW); return TRUE; }
//
// Handle context-sensitive help messages from acm dialog
//
if( wMsg == guChooserContextMenu ) { WinHelp( (HWND)wParam, NULL, HELP_CONTEXTMENU, (UINT_PTR)(LPSTR)aChooserHelpIds ); } else if( wMsg == guChooserContextHelp ) { WinHelp( ((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (UINT_PTR)(LPSTR)aChooserHelpIds ); } #endif
break; } return FALSE;
} /* SoundRecDlgProc */
/*
* Bitmap Buttons * */ BOOL SoundRec_OnDrawItem ( HWND hwnd, const DRAWITEMSTRUCT *lpdis ) { int i;
i = lpdis->CtlID - ID_BTN_BASE;
if (lpdis->CtlType == ODT_BUTTON ) {
/*
** Now draw the button according to the buttons state information. */
tbPlaybar[i].fsState = LOBYTE(lpdis->itemState);
if (lpdis->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)) {
BtnDrawButton( hwnd, lpdis->hDC, (int)lpdis->rcItem.right, (int)lpdis->rcItem.bottom, &tbPlaybar[i] ); return(TRUE); } else if (lpdis->itemAction & ODA_FOCUS) {
BtnDrawFocusRect(lpdis->hDC, &lpdis->rcItem, lpdis->itemState); return(TRUE); } } return(FALSE); }
/*
* void SoundRec_ControlPanel * * Launch "Audio" control panel/property sheet upon request. * * */ void SoundRec_ControlPanel( HINSTANCE hInst, HWND hParent) { const TCHAR gszOpen[] = TEXT("open"); const TCHAR gszRunDLL[] = TEXT("RUNDLL32.EXE"); const TCHAR gszMMSYSCPL[] = TEXT("MMSYS.CPL,ShowAudioPropertySheet"); ShellExecute (NULL, gszOpen, gszRunDLL, gszMMSYSCPL, NULL, SW_SHOWNORMAL); }
/* ResolveLink
* * This routine is called when the user drags and drops a shortcut * onto Media Player. If it succeeds, it returns the full path * of the actual file in szResolved. */ BOOL ResolveLink(LPTSTR szPath, LPTSTR szResolved, LONG cbSize) { IShellLink *psl = NULL; HRESULT hres;
if (!gfOleInitialized) { if (!InitializeOle(ghInst)) return FALSE; }
hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC, &IID_IShellLink, &psl);
if (SUCCEEDED(hres) && (psl != NULL)) { IPersistFile *ppf;
psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
if (ppf) { WCHAR wszPath[MAX_PATH]; #ifdef UNICODE
lstrcpy (wszPath, szPath); #else
AnsiToUnicodeString(szPath, wszPath, UNKNOWN_LENGTH); #endif
hres = ppf->lpVtbl->Load(ppf, wszPath, 0); ppf->lpVtbl->Release(ppf);
if (FAILED(hres)) { psl->lpVtbl->Release(psl); psl = NULL; } } else { psl->lpVtbl->Release(psl); psl = NULL; } }
if (psl) { psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI); psl->lpVtbl->GetPath(psl, szResolved, cbSize, NULL, 0); psl->lpVtbl->Release(psl); }
return SUCCEEDED(hres); }
/* ResolveIfLink
* * Called to check whether a given file name is a shortcut * on Windows 95. * * Copies the resolved file name into the buffer provided, * overwriting the original name. * * Returns TRUE if the function succeeded, whether or not the * file name was changed. FALSE indicates that an error occurred. * * Andrew Bell, 16 February 1995 */ BOOL ResolveIfLink(PTCHAR szFileName) { SHFILEINFO sfi; BOOL rc = TRUE;
if ((SHGetFileInfo(szFileName, 0, &sfi, sizeof sfi, SHGFI_ATTRIBUTES) == 1) && ((sfi.dwAttributes & SFGAO_LINK) == SFGAO_LINK)) { TCHAR szResolvedLink[MAX_PATH];
if (ResolveLink(szFileName, szResolvedLink, SIZEOF(szResolvedLink))) lstrcpy(szFileName, szResolvedLink); else rc = FALSE; }
return rc; }
#if DBG
void FAR cdecl dprintfA(LPSTR szFormat, ...) { char ach[128]; int s,d; va_list va;
va_start(va, szFormat); s = vsprintf (ach,szFormat, va); va_end(va);
for (d=sizeof(ach)-1; s>=0; s--) { if ((ach[d--] = ach[s]) == '\n') ach[d--] = '\r'; }
OutputDebugStringA("SNDREC32: "); OutputDebugStringA(ach+d+1); } #ifdef UNICODE
void FAR cdecl dprintfW(LPWSTR szFormat, ...) { WCHAR ach[128]; int s,d; va_list va;
va_start(va, szFormat); s = vswprintf (ach,szFormat, va); va_end(va);
for (d=(sizeof(ach)/sizeof(WCHAR))-1; s>=0; s--) { if ((ach[d--] = ach[s]) == TEXT('\n')) ach[d--] = TEXT('\r'); }
OutputDebugStringW(TEXT("SNDREC32: ")); OutputDebugStringW(ach+d+1); } #endif
#endif
|