Lots of changes to integrate with Ken's NxPlayer

This commit is contained in:
Gregory Nutt 2014-07-24 15:01:05 -06:00
parent e5ff9a4798
commit 4c6723f96e
3 changed files with 276 additions and 61 deletions

View File

@ -1154,7 +1154,7 @@ config NXWM_MEDIAPLAYER_MEDIAPATH
containing all of the media files accessible by the media player.
config NXWM_MEDIAPLAYER_NOFILTER
bool "Disable filtering by file name extension
bool "Disable filtering by file name extension"
default y
config NXWM_MEDIAPLAYER_FILTER

View File

@ -143,10 +143,11 @@ namespace NxWM
enum EMediaPlayerState m_state; /**< Media player current state */
enum EMediaPlayerState m_prevState; /**< Media player previous state */
enum EPendingRelease m_pending; /**< Pending image release event */
NXWidgets::CNxString m_filePath; /**< The full path to the selected file */
bool m_fileReady; /**< True: Ready to play */
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
int m_level; /**< Current volume level */
uint8_t m_level; /**< Current volume level, range 0-100 */
#endif
int m_fileIndex; /**< Index to selected file in the list box */
/**
* Media player geometry.
@ -187,18 +188,26 @@ namespace NxWM
NXWidgets::CRlePaletteBitmap *m_volumeBitmap; /**< Volume control grip bitmap */
/**
* Open a media file for playing. Called after a file has been selected
* from the list box.
* Get the full media file path and make ready for playing. Called
* after a file has been selected from the list box.
*/
inline bool openMediaFile(const NXWidgets::CListBoxDataItem *item);
bool getMediaFile(const NXWidgets::CListBoxDataItem *item);
/**
* Close media file. Called when a new media file is selected, when a
* media file is de-selected, or when destroying the media player instance.
* Get the full media file path and make ready for playing. Called
* after a file has been selected from the list box.
*/
inline void closeMediaFile(void);
bool openMediaFile(const NXWidgets::CListBoxDataItem *item);
/**
* Stop playing the current file. Called when a new media file is selected,
* when a media file is de-selected, or when destroying the media player
* instance.
*/
void stopPlaying(void);
/**
* Select the geometry of the media player given the current window size.

View File

@ -40,6 +40,8 @@
#include <nuttx/config.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstring>
#include <cerrno>
@ -47,6 +49,7 @@
#include <debug.h>
#include <apps/nxplayer.h>
#include <nuttx/audio/audio.h>
#include "cwidgetcontrol.hxx"
@ -132,7 +135,7 @@ CMediaPlayer::CMediaPlayer(CTaskbar *taskbar, CApplicationWindow *window)
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
m_level = 0;
#endif
m_fileIndex = -1;
m_fileReady = false;
// Add our personalized window label
@ -391,23 +394,96 @@ bool CMediaPlayer::isFullScreen(void) const
}
/**
* Open a media file for playing. Called after a file has been selected
* from the list box.
* Get the full media file path and make ready for playing. Called
* after a file has been selected from the list box.
*/
bool CMediaPlayer::openMediaFile(const NXWidgets::CListBoxDataItem *item)
bool CMediaPlayer::getMediaFile(const NXWidgets::CListBoxDataItem *item)
{
#warning Missing logic
// Get the full path to the file
NXWidgets::CNxString newFilePath(CONFIG_NXWM_MEDIAPLAYER_MEDIAPATH "/");
newFilePath.append(item->getText());
// Make sure that this is a different name than the one we already have
if (!m_fileReady || m_filePath.compareTo(newFilePath) != 0)
{
// It is a new file name
// Get the path to the file as a regular C-style string
NXWidgets::nxwidget_char_t *filePath =
new NXWidgets::nxwidget_char_t[m_filePath.getAllocSize() + 1];
if (!filePath)
{
dbg("ERROR: Failed to allocate file path\n");
return false;
}
m_filePath.copyToCharArray(filePath);
// Verify that the file of this name exists and that it is a not
// something weird (like a directory or a block device).
// REVISIT: Should check if read-able as well.
struct stat buf;
int ret = stat((FAR const char *)filePath, &buf);
delete filePath;
if (ret < 0)
{
int errcode = errno;
dbg("ERROR: Could not stat file: %d\n", errcode);
// Make sure there is no previous file information
m_fileReady = false;
m_filePath.remove(0);
return false;
}
if (S_ISDIR(buf.st_mode) || S_ISBLK(buf.st_mode))
{
dbg("ERROR: Not a regular file\n");
// Make sure there is no previous file information
m_fileReady = false;
m_filePath.remove(0);
return false;
}
}
// Save the new file path and mark ready to play
m_filePath = newFilePath;
m_fileReady = true;
return true;
}
/**
* Close media file. Called when a new media file is selected, when a media file is de-selected, or when destroying the media player instance.
*/
* Stop playing the current file. Called when a new media file is selected,
* when a media file is de-selected, or when destroying the media player
* instance.
*/
void CMediaPlayer::closeMediaFile(void)
void CMediaPlayer::stopPlaying(void)
{
#warning Missing logic
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
// Stop playing the file
int ret = nxplayer_stop(m_player);
if (ret < 0)
{
auddbg("ERROR: nxplayer_stop failed: %d\n", ret);
}
#endif
// Clear information about the selected file
m_fileReady = false;
m_filePath.remove(0);
}
/**
@ -1036,7 +1112,7 @@ void CMediaPlayer::setMediaPlayerState(enum EMediaPlayerState state)
// Play image is visible, but enabled and ready to start playing only
// if a file is selected
if (m_fileIndex < 0)
if (m_fileReady)
{
m_play->disable();
}
@ -1082,7 +1158,9 @@ void CMediaPlayer::setMediaPlayerState(enum EMediaPlayerState state)
// Pause image enabled and ready to pause playing
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
m_pause->enable();
#endif
m_pause->show();
#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
@ -1148,7 +1226,9 @@ void CMediaPlayer::setMediaPlayerState(enum EMediaPlayerState state)
// Pause image enabled and ready to stop fast forwarding
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
m_pause->enable();
#endif
m_pause->show();
}
else
@ -1193,7 +1273,9 @@ void CMediaPlayer::setMediaPlayerState(enum EMediaPlayerState state)
// Pause image enabled and ready to stop rewinding
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
m_pause->enable();
#endif
m_pause->show();
}
else
@ -1241,14 +1323,28 @@ void CMediaPlayer::setVolumeLevel(void)
// range 0-100
int newLevel = m_volume->getValue();
if (newLevel < 0 || newLevel > 100)
{
dbg("ERROR: volume is out of range: %d\n", newLevel);
}
// Has the volume level changed?
if (m_level != newLevel)
else if ((int)m_level != newLevel)
{
// Yes.. provide the new volume setting to the NX Player
#warning Missing logic
m_level = newLevel;
int ret = nxplayer_setvolume(m_player, (uint16_t)newLevel);
if (ret < OK)
{
dbg("ERROR: nxplayer_setvolume failed: %d\n", ret);
}
else
{
// New volume set successfully.. save the new setting
m_level = (uint8_t)newLevel;
}
}
}
#endif
@ -1269,64 +1365,59 @@ void CMediaPlayer::checkFileSelection(void)
{
// No file is selected
m_fileIndex = -1;
m_fileReady = false;
// Nothing is selected.. If we are not stopped, then stop now
if (m_state != MPLAYER_STOPPED)
{
closeMediaFile();
stopPlaying();
setMediaPlayerState(MPLAYER_STOPPED);
}
}
// A media file is selected. Were stopped before?
// A media file is selected. Were we stopped before?
else if (m_state == MPLAYER_STOPPED)
{
// Yes.. open the new media file and go to the PAUSE state
// Yes.. Get the new media file path and go to the PAUSE state
if (!openMediaFile(m_listbox->getSelectedOption()))
if (!getMediaFile(m_listbox->getSelectedOption()))
{
// Remain in the stopped state if we fail to open the file
m_fileIndex = -1;
dbg("ERROR: openMediaFile failed\n");
dbg("ERROR: getMediaFile failed\n");
}
else
{
// And go to the PAUSED state (enabling the PLAY button)
m_fileIndex = newFileIndex;
setMediaPlayerState(MPLAYER_PAUSED);
}
}
// We already have a media file loaded. Is it the same file?
// Make sure that we are not already playing,
else if (m_fileIndex != newFileIndex)
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()))
{
// No.. It is a new file. Close that media file, load the newly
// selected file, and make sure that we are in the paused state
// (that should already be the case)
// Go to the STOPPED state on a failure to open the media file
// The play button will be disabled because m_fileReady is false.
closeMediaFile();
if (!openMediaFile(m_listbox->getSelectedOption()))
{
// Go to the STOPPED state on a failure to open the media file
// The play button will be disabled because m_fileIndex == -1.
dbg("ERROR: getMediaFile failed\n");
setMediaPlayerState(MPLAYER_STOPPED);
}
else
{
// And go to the PAUSED state (enabling the PLAY button)
dbg("ERROR: openMediaFile failed\n");
m_fileIndex = -1;
setMediaPlayerState(MPLAYER_STOPPED);
}
else
{
// And go to the PAUSED state (enabling the PLAY button)
m_fileIndex = newFileIndex;
setMediaPlayerState(MPLAYER_PAUSED);
}
setMediaPlayerState(MPLAYER_PAUSED);
}
}
@ -1377,7 +1468,15 @@ void CMediaPlayer::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
// Yes.. then revert to the previous play/pause state
// REVISIT: Or just increase rewind speed?
setMediaPlayerState(m_prevState);
int ret = nxplayer_cancel_motion(m_player, m_prevState == MPLAYER_PAUSED);
if (ret < 0)
{
dbg("ERROR: nxplayer_cancel_motion failed: %d\n", ret);
}
else
{
setMediaPlayerState(m_prevState);
}
}
// We should not be stopped here, but let's check anyway
@ -1386,7 +1485,15 @@ void CMediaPlayer::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
{
// Start rewinding
setMediaPlayerState(MPLAYER_FREWIND);
int ret = nxplayer_rewind(m_player, SUBSAMPLE_4X);
if (ret < 0)
{
dbg("ERROR: nxplayer_rewind failed: %d\n", ret);
}
else
{
setMediaPlayerState(MPLAYER_FREWIND);
}
}
}
#endif
@ -1403,7 +1510,16 @@ void CMediaPlayer::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
// Yes.. then revert to the previous play/pause state
// REVISIT: Or just increase fast forward speed?
setMediaPlayerState(m_prevState);
int ret = nxplayer_cancel_motion(m_player, m_prevState == MPLAYER_PAUSED);
if (ret < 0)
{
dbg("ERROR: nxplayer_cancel_motion failed: %d\n", ret);
}
else
{
setMediaPlayerState(m_prevState);
}
}
// We should not be stopped here, but let's check anyway
@ -1412,7 +1528,15 @@ void CMediaPlayer::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
{
// Start fast forwarding
setMediaPlayerState(MPLAYER_FFORWARD);
int ret = nxplayer_fforward(m_player, SUBSAMPLE_4X);
if (ret < 0)
{
dbg("ERROR: nxplayer_fforward failed: %d\n", ret);
}
else
{
setMediaPlayerState(MPLAYER_FFORWARD);
}
}
}
#endif
@ -1430,16 +1554,67 @@ void CMediaPlayer::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e)
if (m_pending == PENDING_PLAY_RELEASE && !m_play->isClicked())
{
// Yes.. Now perform the delayed state change
// Yes.. Now perform the delayed state change.
//
// If we were previously STOPPED or PAUSED, then enter the PLAYING
// state.
// If there is no selected file, then the play button does nothing
if (m_state == MPLAYER_STOPPED || m_state == MPLAYER_PAUSED)
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
if (m_state == MPLAYER_PAUSED)
{
setMediaPlayerState(MPLAYER_PLAYING);
// Resume playing
int ret = nxplayer_resume(m_player);
if (ret < 0)
{
dbg("ERROR: nxplayer_resume() failed: %d\n", ret);
}
else
{
setMediaPlayerState(MPLAYER_PLAYING);
}
}
else if (m_state == MPLAYER_STOPPED)
#else
if (m_state == MPLAYER_STOPPED || m_state == MPLAYER_PAUSED)
#endif
{
// Has a file been selected? If not the ignore the event
if (m_fileReady)
{
// Get the path to the file as a regular C-style string
NXWidgets::nxwidget_char_t *filePath =
new NXWidgets::nxwidget_char_t[m_filePath.getAllocSize() + 1];
if (!filePath)
{
dbg("ERROR: Failed to allocate file path\n");
return;
}
m_filePath.copyToCharArray(filePath);
// And start playing
int ret = nxplayer_playfile(m_player, (FAR const char *)filePath,
AUDIO_FMT_UNDEF, AUDIO_FMT_UNDEF);
if (ret < 0)
{
dbg("ERROR: nxplayer_playfile failed: %d\n", ret);
}
else
{
setMediaPlayerState(MPLAYER_PLAYING);
}
delete filePath;
}
}
#if !defined(CONFIG_AUDIO_EXCLUDE_FFORWARD) || !defined(CONFIG_AUDIO_EXCLUDE_REWIND)
// Ignore the event if we are already in the PLAYING state
else if (m_state != MPLAYER_PLAYING)
@ -1447,14 +1622,24 @@ void CMediaPlayer::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e)
// Otherwise, we must be fast forwarding or rewinding. In these
// cases, stop the action and return to the previous state
setMediaPlayerState(m_prevState);
int ret = nxplayer_cancel_motion(m_player, m_prevState == MPLAYER_PAUSED);
if (ret < 0)
{
dbg("ERROR: nxplayer_cancel_motion failed: %d\n", ret);
}
else
{
setMediaPlayerState(m_prevState);
}
}
#endif
// No longer any action pending the PLAY image release
m_pending = PENDING_NONE;
}
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
// Check if the Pause image was released
else if (m_pending == PENDING_PAUSE_RELEASE && !m_pause->isClicked())
@ -1465,9 +1650,20 @@ void CMediaPlayer::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e)
if (m_state == MPLAYER_PLAYING)
{
setMediaPlayerState(MPLAYER_PAUSED);
// Pause playing
int ret = nxplayer_pause(m_player);
if (ret < 0)
{
dbg("ERROR: nxplayer_pause() failed: %d\n", ret);
}
else
{
setMediaPlayerState(MPLAYER_PAUSED);
}
}
#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)
@ -1475,13 +1671,23 @@ void CMediaPlayer::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e)
// Otherwise, we must be fast forwarding or rewinding. In these
// cases, stop the action and return to the previous state
setMediaPlayerState(m_prevState);
int ret = nxplayer_cancel_motion(m_player, m_prevState == MPLAYER_PAUSED);
if (ret < 0)
{
dbg("ERROR: nxplayer_cancel_motion failed: %d\n", ret);
}
else
{
setMediaPlayerState(m_prevState);
}
}
#endif
// No longer any action pending the PAUSE image release
m_pending = PENDING_NONE;
}
#endif
}
/**