NxWM::CMediaPlayer: Revise state logic. We need an additional state for the case where a file is selected, but playing has not yet start. Several other state-related fixes

This commit is contained in:
Gregory Nutt 2014-07-25 10:11:30 -06:00
parent 04152576fa
commit 7b43b0543b
2 changed files with 101 additions and 61 deletions

View File

@ -89,9 +89,10 @@ namespace NxWM
* | FILE | FILE | | | FAST | |
* STATE | SELECTED |DESELECTED| PLAY | PAUSE | FORWARD | REWIND |
* ---------+----------+----------+----------+----------+----------+----------+
* STOPPED | PAUSED | X | X | X | X | X |
* PAUSED | PAUSED | STOPPED | PLAYING | X |FFORWARD1 | REWIND1 |
* STOPPED | STAGED | X | X | X | X | X |
* STAGED | STAGED | STOPPED | PLAYING | X | X | X |
* PLAYING | X | X | X | PAUSED |FFORWARD2 | REWIND2 |
* PAUSED | STAGED | STOPPED | PLAYING | X |FFORWARD1 | REWIND1 |
* FFORWARD1| X | X | PAUSED | X | PAUSED | REWIND1 |
* REWIND1 | X | X | PAUSED | X |FFORWARD1 | PAUSED |
* FFORWARD2| X | X | X | PLAYING | PLAYING | REWIND1 |
@ -112,12 +113,19 @@ namespace NxWM
enum EMediaPlayerState
{
MPLAYER_STOPPED = 0, /**< No media file has been selected */
MPLAYER_STAGED, /**< Media file selected, not playing */
MPLAYER_PLAYING, /**< Playing a media file */
MPLAYER_PAUSED, /**< Playing a media file but paused */
MPLAYER_FFORWARD, /**< Fast forwarding through a media file */
MPLAYER_FREWIND, /**< Rewinding a media file */
};
/**
* Describes the state of an image touch. Some image touch cannot be
* processed until the image contact is lost. This enumeration arms and
* manages those cases.
*/
enum EPendingRelease
{
PENDING_NONE = 0, /**< Nothing is pending */

View File

@ -2,6 +2,7 @@
* NxWidgets/nxwm/src/cmediaplayer.cxx
*
* Copyright (C) 2013 Ken Pettit. All rights reserved.
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
* Gregory Nutt <gnutt@nuttx.org>
*
@ -1057,8 +1058,12 @@ void CMediaPlayer::redrawWidgets(void)
m_listbox->redraw();
// Only one of the Play and Pause images should have drawing enabled.
// Play should be visible if we are in any STOPPED state of if we
// are fast forward or rewind state that came from the PAUSED state
if (m_state != MPLAYER_STOPPED && m_prevState == MPLAYER_PLAYING)
if (m_state != MPLAYER_STOPPED && // Stopped states
m_state != MPLAYER_STAGED &&
m_prevState == MPLAYER_PLAYING) // Previously playing
{
// Playing... show the pause button
// REVISIT: Really only available if there is a selected file in the list box
@ -1104,24 +1109,16 @@ void CMediaPlayer::setMediaPlayerState(enum EMediaPlayerState state)
{
case MPLAYER_STOPPED: // Initial state. Also the state after playing completes
m_state = MPLAYER_STOPPED;
m_prevState = MPLAYER_PLAYING;
m_prevState = MPLAYER_STOPPED;
// List box is enabled and ready for file selection
m_listbox->enable();
// Play image is visible, but enabled and ready to start playing only
// if a file is selected
if (m_fileReady)
{
m_play->disable();
}
else
{
m_play->enable();
}
// Play image is visible, but disabled. It will not enabled until
// we enter the MPLAYER_STAGED state after a file is selected
m_play->disable();
m_play->show();
// Pause image is disabled and hidden
@ -1139,6 +1136,43 @@ void CMediaPlayer::setMediaPlayerState(enum EMediaPlayerState state)
m_rewind->disable();
m_rewind->setStuckSelection(false);
// Volume slider is available
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
m_volume->enable();
#endif
break;
case MPLAYER_STAGED: // Media file selected, not playing
m_state = MPLAYER_STAGED;
m_prevState = MPLAYER_STOPPED;
// List box is still enabled a ready for file selection
m_listbox->enable();
// Play image enabled and ready to start playing
m_play->enable();
m_play->show();
// Pause image is disabled and hidden
m_pause->disable();
m_pause->hide();
// Fast forward image is disabled
m_fforward->disable();
m_fforward->setStuckSelection(false);
// Rewind image is disabled
m_rewind->disable();
m_rewind->setStuckSelection(false);
// Volume slider is available
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
m_volume->enable();
#endif
@ -1372,54 +1406,48 @@ void CMediaPlayer::checkFileSelection(void)
if (m_state != MPLAYER_STOPPED)
{
// Stop playing. Should be okay if m_state == MPLAYER_STAGED.
// We are not really playing yet, but NxPlayer should be able
// to handle that.
stopPlaying();
// Then go to the STOPPED state
setMediaPlayerState(MPLAYER_STOPPED);
}
}
// A media file is selected. Were we stopped before?
else if (m_state == MPLAYER_STOPPED)
else
{
// Yes.. Get the new media file path and go to the PAUSE state
// A media file is selected. Were we in a STOPPED state before?
// Make sure that we are not already playing. Should be okay if
// are in a STOPPED or STAGED state. We are not really playing
// yet those cases, but NxPlayer should be able to handle any
// spurious stops.
stopPlaying();
// Get the path to the newly selected file
if (!getMediaFile(m_listbox->getSelectedOption()))
{
// Remain in the stopped state if we fail to open the file
// Go to the STOPPED state on a failure to open the media file
// The play button will be disabled because m_fileReady is false.
// No harm done if we were already STOPPED.
dbg("ERROR: getMediaFile failed\n");
setMediaPlayerState(MPLAYER_STOPPED);
}
else
{
// And go to the PAUSED state (enabling the PLAY button)
// We have the file. Go to the STAGED state (enabling the PLAY
// button). NOTE that if for some reason this is the same file
// that we were already and playing, then playing will be
// restarted.
setMediaPlayerState(MPLAYER_PAUSED);
setMediaPlayerState(MPLAYER_STAGED);
}
}
// Make sure that we are not already playing,
stopPlaying();
// Get the path to the newly selected file, and make sure that we are
// in the paused state (that should already be the case). NOTE that if
// for some reason this is the same file that we were already playing,
// then playing will be restarted.
if (!getMediaFile(m_listbox->getSelectedOption()))
{
// Go to the STOPPED state on a failure to open the media file
// The play button will be disabled because m_fileReady is false.
dbg("ERROR: getMediaFile failed\n");
setMediaPlayerState(MPLAYER_STOPPED);
}
else
{
// And go to the PAUSED state (enabling the PLAY button)
setMediaPlayerState(MPLAYER_PAUSED);
}
}
/**
@ -1444,7 +1472,7 @@ void CMediaPlayer::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
// These only make sense in non-STOPPED states
if (m_state != MPLAYER_STOPPED)
if (m_state != MPLAYER_STOPPED && m_state != MPLAYER_STAGED)
{
// Check if the Pause image was clicked
@ -1480,9 +1508,9 @@ void CMediaPlayer::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
}
}
// We should not be stopped here, but let's check anyway
// We should not be in a STOPPED state here, but let's check anyway
else if (m_state != MPLAYER_STOPPED)
else if (m_state != MPLAYER_STOPPED && m_state != MPLAYER_STAGED)
{
// Start rewinding
@ -1511,7 +1539,6 @@ void CMediaPlayer::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
// Yes.. then revert to the previous play/pause state
// REVISIT: Or just increase fast forward speed?
int ret = nxplayer_cancel_motion(m_player, m_prevState == MPLAYER_PAUSED);
if (ret < 0)
{
@ -1523,9 +1550,9 @@ void CMediaPlayer::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
}
}
// We should not be stopped here, but let's check anyway
// We should not be in a STOPPED state here, but let's check anyway
else if (m_state != MPLAYER_STOPPED)
else if (m_state != MPLAYER_STOPPED && m_state != MPLAYER_STAGED)
{
// Start fast forwarding
@ -1576,9 +1603,9 @@ void CMediaPlayer::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e)
setMediaPlayerState(MPLAYER_PLAYING);
}
}
else if (m_state == MPLAYER_STOPPED)
else if (m_state == MPLAYER_STAGED)
#else
if (m_state == MPLAYER_STOPPED || m_state == MPLAYER_PAUSED)
if (m_state == MPLAYER_STAGED || m_state == MPLAYER_PAUSED)
#endif
{
// Has a file been selected? If not the ignore the event
@ -1615,13 +1642,16 @@ void CMediaPlayer::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e)
}
}
#if !defined(CONFIG_AUDIO_EXCLUDE_FFORWARD) || !defined(CONFIG_AUDIO_EXCLUDE_REWIND)
// Ignore the event if we are already in the PLAYING state
// Ignore the event if (1) we are already in the PLAYING state, or (2)
// we are still in the STOPPED state (with no file selected).
else if (m_state != MPLAYER_PLAYING)
#if !defined(CONFIG_AUDIO_EXCLUDE_FFORWARD) || !defined(CONFIG_AUDIO_EXCLUDE_REWIND)
// The remaining cases include only the FFORWARD and REWIND states
else if (m_state == MPLAYER_FFORWARD || m_state == MPLAYER_FREWIND)
{
// Otherwise, we must be fast forwarding or rewinding. In these
// cases, stop the action and return to the previous state
// In these states, stop the fast motion action and return to the
// previous state
int ret = nxplayer_cancel_motion(m_player, m_prevState == MPLAYER_PAUSED);
if (ret < 0)
@ -1667,7 +1697,9 @@ void CMediaPlayer::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e)
#if !defined(CONFIG_AUDIO_EXCLUDE_FFORWARD) || !defined(CONFIG_AUDIO_EXCLUDE_REWIND)
// Ignore the event if we are already in the PAUSED or STOPPED states
else if (m_state != MPLAYER_STOPPED && m_state != MPLAYER_PAUSED)
else if (m_state != MPLAYER_STOPPED &&
m_state != MPLAYER_STAGED &&
m_state != MPLAYER_PAUSED)
{
// Otherwise, we must be fast forwarding or rewinding. In these
// cases, stop the action and return to the previous state