windows-nt/Source/XPSP1/NT/multimedia/media/deluxe2/cdplay/commands.cpp
2020-09-26 16:20:57 +08:00

519 lines
13 KiB
C++

/******************************Module*Header*******************************\
* Module Name: commands.c
*
* Executes the users commands.
*
*
* Created: 18-11-93
* Author: Stephen Estrop [StephenE]
*
* Copyright (c) 1993 Microsoft Corporation
\**************************************************************************/
#pragma warning( once : 4201 4214 )
#define NOOLE
#include <windows.h> /* required for all Windows applications */
#include <windowsx.h>
#include <string.h>
#include <malloc.h>
#include <stdarg.h>
#include <stdio.h>
#include "playres.h"
#include "cdplayer.h"
#include "ledwnd.h"
#include "cdapi.h"
#include "scan.h"
#include "trklst.h"
#include "database.h"
#include "commands.h"
#define PREVTRAK_TIMELIMIT 3 //seconds
extern IMMFWNotifySink* g_pSink;
/******************************Public*Routine******************************\
* CdPlayerEjectCmd
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CdPlayerEjectCmd(
void
)
{
if (g_State & CD_PAUSED) {
g_State &= (~(CD_PAUSED_AND_MOVED | CD_PAUSED));
}
if (g_State & CD_PLAYING) {
g_State &= ~CD_PLAYING;
g_State |= CD_STOPPED;
}
if (EjectTheCdromDisc(g_CurrCdrom))
{
g_State = (CD_NO_CD | CD_STOPPED);
SetPlayButtonsEnableState();
TimeAdjustInitialize( g_CurrCdrom );
g_pSink->OnEvent(MMEVENT_ONMEDIAUNLOADED,NULL);
}
}
/******************************Public*Routine******************************\
* CdPlayerPlayCmd
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CdPlayerPlayCmd(
void
)
{
/*
** If we can't lock all the cdrom devices
** don't do anything. The user will have press
** the play button again.
*/
if ( LockALLTableOfContents() ) {
if (g_State & CD_LOADED ) {
if ((g_State & CD_STOPPED) && PlayCurrTrack( g_CurrCdrom )) {
g_State &= ~CD_STOPPED;
g_State |= CD_PLAYING;
}
else if ( g_State & CD_PAUSED ) {
if ( g_State & CD_PAUSED_AND_MOVED ) {
g_State &= ~CD_PAUSED_AND_MOVED;
g_State |= CD_PLAYING;
if ( SeekToCurrSecond( g_CurrCdrom ) ) {
g_State &= ~CD_PAUSED;
g_State |= CD_PLAYING;
}
else {
g_State &= ~CD_PLAYING;
}
}
else if ( ResumeTheCdromDrive( g_CurrCdrom ) ) {
g_State &= ~CD_PAUSED;
g_State |= CD_PLAYING;
}
UpdateDisplay( DISPLAY_UPD_LED );
}
if (g_State & CD_PLAYING)
{
g_pSink->OnEvent(MMEVENT_ONPLAY,NULL);
}
}
else {
#if DBG
dprintf( TEXT("Failing play because NO disc loaded") );
#endif
}
SetPlayButtonsEnableState();
}
}
/******************************Public*Routine******************************\
* CdPlayerPauseCmd
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CdPlayerPauseCmd(
void
)
{
/*
** If we can't lock all the cdrom devices
** don't do anything. The user will have press
** the pause button again.
*/
if ( LockALLTableOfContents() ) {
if ( g_State & CD_PLAYING )
{
if ( PauseTheCdromDrive( g_CurrCdrom ) )
{
g_State &= ~CD_PLAYING;
g_State |= CD_PAUSED;
g_pSink->OnEvent(MMEVENT_ONPAUSE,NULL);
}
}
else if ( g_State & CD_PAUSED )
{
if ( g_State & CD_PAUSED_AND_MOVED ) {
g_State &= ~CD_PAUSED_AND_MOVED;
g_State |= CD_PLAYING;
if ( SeekToCurrSecond( g_CurrCdrom ) ) {
g_State &= ~CD_PAUSED;
g_State |= CD_PLAYING;
}
else {
g_State &= ~CD_PLAYING;
}
}
else if ( ResumeTheCdromDrive( g_CurrCdrom ) ) {
g_State &= ~CD_PAUSED;
g_State |= CD_PLAYING;
}
UpdateDisplay( DISPLAY_UPD_LED );
if (g_State & CD_PLAYING)
{
g_pSink->OnEvent(MMEVENT_ONPLAY,NULL);
}
}
SetPlayButtonsEnableState();
}
}
/******************************Public*Routine******************************\
* CdPlayerStopCmd
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CdPlayerStopCmd(
void
)
{
/*
** If we can't lock all the cdrom devices
** don't do anything. The user will have press
** the stop button again.
*/
if ( LockALLTableOfContents() ) {
BOOL bPlaying, bPaused;
bPlaying = g_State & CD_PLAYING;
bPaused = g_State & CD_PAUSED;
if ( (bPlaying || bPaused) && StopTheCdromDrive(g_CurrCdrom) ) {
g_State &= ~(bPlaying ? CD_PLAYING : CD_PAUSED);
g_State |= CD_STOPPED;
/*
** Stop the current play operation and seek to the first
** playable track.
*/
CURRTRACK(g_CurrCdrom) = FindFirstTrack( g_CurrCdrom );
TimeAdjustSkipToTrack( g_CurrCdrom, CURRTRACK(g_CurrCdrom) );
UpdateDisplay( DISPLAY_UPD_LED | DISPLAY_UPD_TRACK_TIME |
DISPLAY_UPD_TRACK_NAME );
SetPlayButtonsEnableState();
// Stop it again!!!
// This is to prevent a strange bug with NEC 4x,6x players
// Where a SEEK command in TimeAdjustSkipToTrack causes
// The ejection mechanism to get locked.
if (StopTheCdromDrive (g_CurrCdrom))
{
g_pSink->OnEvent(MMEVENT_ONSTOP,NULL);
}
}
}
}
/******************************Public*Routine******************************\
* CdPlayerPrevTrackCmd
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CdPlayerPrevTrackCmd(
void
)
{
/*
** If we can't lock all the cdrom devices
** don't do anything. The user will have press
** the previous track button again.
*/
if ( LockALLTableOfContents() ) {
DWORD dwOldState;
int i, j;
PTRACK_PLAY tr;
if ( (CDTIME(g_CurrCdrom).TrackCurSec <= PREVTRAK_TIMELIMIT)
&& (CDTIME(g_CurrCdrom).TrackCurMin == 0) ) {
dwOldState = g_State;
i = g_CurrCdrom;
tr = FindPrevTrack( g_CurrCdrom, g_fContinuous );
if ( tr == NULL ) {
/*
** If we were Paused or Playing fake a press on the
** "stop" button
*/
if ( g_State & (CD_PLAYING | CD_PAUSED) ) {
SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_STOP)],
WM_LBUTTONDOWN, 0, 0L );
SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_STOP)],
WM_LBUTTONUP, 0, 0L );
}
}
else {
TimeAdjustSkipToTrack( g_CurrCdrom, tr );
if ( (i != g_CurrCdrom) && (dwOldState & CD_PLAYING) )
{
j = g_CurrCdrom;
g_CurrCdrom = i;
//don't allow the ledwnd to paint
LockWindowUpdate(g_hwndControls[INDEX(IDC_LED)]);
SwitchToCdrom( j, FALSE );
LockWindowUpdate(NULL);
//switchtocdrom command stopped drive, setting us back to track 1...
//reset to correct track
TimeAdjustSkipToTrack( g_CurrCdrom, tr );
SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_PLAY)],
WM_LBUTTONDOWN, 0, 0L );
SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_PLAY)],
WM_LBUTTONUP, 0, 0L );
}
}
}
else {
TimeAdjustSkipToTrack( g_CurrCdrom, CURRTRACK( g_CurrCdrom ) );
}
}
}
/******************************Public*Routine******************************\
* CdPlayerNextTrackCmd
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CdPlayerNextTrackCmd(
void
)
{
/*
** If we can't lock all the cdrom devices
** don't do anything. The user will have press
** the next track button again.
*/
if ( LockALLTableOfContents() ) {
DWORD dwOldState;
PTRACK_PLAY tr;
dwOldState = g_State;
tr = FindNextTrack( g_fContinuous );
if ( tr == NULL ) {
/*
** If the CD is playing fake a press on the "stop" button
** otherwise call the stop function directly.
*/
if ( g_State & (CD_PLAYING | CD_PAUSED) ) {
SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_STOP)],
WM_LBUTTONDOWN, 0, 0L );
SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_STOP)],
WM_LBUTTONUP, 0, 0L );
}
else {
/*
** Seek to the first playable track.
*/
CURRTRACK(g_CurrCdrom) = FindFirstTrack( g_CurrCdrom );
if (CURRTRACK(g_CurrCdrom) != NULL ) {
TimeAdjustSkipToTrack( g_CurrCdrom,
CURRTRACK(g_CurrCdrom) );
UpdateDisplay( DISPLAY_UPD_LED | DISPLAY_UPD_TRACK_TIME |
DISPLAY_UPD_TRACK_NAME );
SetPlayButtonsEnableState();
}
}
}
else {
if ( g_LastCdrom != g_CurrCdrom) {
SwitchToCdrom( g_CurrCdrom,FALSE);
TimeAdjustSkipToTrack( g_CurrCdrom, tr );
if ( dwOldState & CD_PLAYING ) {
SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_PLAY)],
WM_LBUTTONDOWN, 0, 0L );
SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_PLAY)],
WM_LBUTTONUP, 0, 0L );
}
}
else {
TimeAdjustSkipToTrack( g_CurrCdrom, tr );
}
}
}
}
/******************************Public*Routine******************************\
* CdPlayerSeekCmd
*
* How Seek works.
*
* When the user presses a seek button (forwards or backwards) this function
* gets called. The cdplayer can be in three possible states:
*
* 1. Playing
* 2. Paused
* 3. Stopped
*
* In state 1 (playing) we pause the device and alter its global state flags
* to show that it was playing (CD_WAS_PLAYING). This is so that we can
* return to the playing state when the user stops seeking.
*
* We then start a timer. We always call the timer function, this means
* that we will allways skip one second no matter how quickly the user
* clicks the seek button. The timer just increments (or decrements) the
* current play position according to the currrent play list. When the users
* releases the seek button we stop the timer and resume playing if the
* CD_WAS_PLAYING flag was set.
*
* The interesting case is when we try to seek beyond the end of the current
* play list. We detect this by testing the state of CURRTRACK(g_CurrCdrom).
* If NULL we have come to the end of the play list. If we were paused or
* previously playing we fake a stop command by sending a WM_LBUTTONDOWN,
* WM_LBUTTONUP message pair to the stop button. This causes the focus
* to be moved from the currently pressed seek button, which means that
* this function will get called BEFORE the CdPlayerStopCmd function. So
* by the time CdPlayerStopCmd gets called the correct playing state of
* the cdrom device would have been restored by the code below.
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CdPlayerSeekCmd(
HWND hwnd,
BOOL fStart,
UINT uDirection
)
{
UINT_PTR rc;
BOOL frc;
if ( fStart ) {
if (g_State & CD_PLAYING) {
g_State &= ~CD_PLAYING;
g_State |= CD_WAS_PLAYING;
PauseTheCdromDrive( g_CurrCdrom );
}
g_State |= CD_SEEKING;
rc = SetTimer( hwnd, uDirection, SKIPBEAT_TIMER_RATE,
(TIMERPROC)SkipBeatTimerProc );
ASSERT(rc != 0);
SkipBeatTimerProc( hwnd, WM_TIMER, uDirection, 0L );
}
else {
g_State &= ~CD_SEEKING;
if (g_State & CD_WAS_PLAYING) {
g_State &= ~CD_WAS_PLAYING;
g_State |= CD_PLAYING;
}
if ( g_State & CD_PAUSED ) {
g_State |= CD_PAUSED_AND_MOVED;
}
else {
SeekToCurrSecond( g_CurrCdrom );
}
frc = KillTimer( hwnd, uDirection );
ASSERT(frc != FALSE);
}
}