Add apps/system/nxplayer media player from Ken Pettit

This commit is contained in:
Gregory Nutt 2013-10-27 07:23:01 -06:00
parent 0b14e81b56
commit 96a778cf46
11 changed files with 2816 additions and 3 deletions

View file

@ -700,4 +700,6 @@
* apps/examples/adc: Add support so that a ADC driven by
software triggering can be tested (2013-10-25).
* apps/examples/cc3000: Updates from David Sidrane (2013-10-25).
* apps/system/nxplayer: Implements a command line media
player. From Ken Pettit (2013-10-27).

356
include/nxplayer.h Normal file
View file

@ -0,0 +1,356 @@
/****************************************************************************
* apps/system/nxplayer/nxplayer.h
*
* Copyright (C) 2013 Ken Pettit. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __APPS_SYSTEM_NXPLAYER_NXPLAYER_H
#define __APPS_SYSTEM_NXPLAYER_NXPLAYER_H 1
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Type Declarations
****************************************************************************/
struct nxplayer_s
{
int state; /* Current player state */
int devFd; /* File descriptor of active device */
mqd_t mq; /* Message queue for the playthread */
char mqname[16]; /* Name of our message queue */
pthread_t playId; /* Thread ID of the playthread */
int crefs; /* Number of references to the player */
sem_t sem; /* Thread sync semaphore */
FILE* fileFd; /* File descriptor of open file */
#ifdef CONFIG_NXPLAYER_INCLUDE_PREFERRED_DEVICE
char prefdevice[CONFIG_NAME_MAX]; /* Preferred audio device */
int prefformat; /* Formats supported by preferred device */
int preftype; /* Types supported by preferred device */
#endif
#ifdef CONFIG_NXPLAYER_INCLUDE_MEDIADIR
char mediadir[CONFIG_NAME_MAX]; /* Root media directory where media is located */
#endif
#ifdef CONFIG_AUDIO_MULTI_SESSION
FAR void* session; /* Session assigment from device */
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
uint16_t volume; /* Volume as a whole percentage (0-100) */
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
uint16_t balance; /* Balance as a whole % (0=left off, 100=right off) */
#endif
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
uint16_t treble; /* Treble as a whole % */
uint16_t bass; /* Bass as a whole % */
#endif
};
typedef int (*nxplayer_func)(FAR struct nxplayer_s* pPlayer, char* pargs);
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: nxplayer_create
*
* Allocates and Initializes a NxPlayer context that is passed to all
* nxplayer routines. The player MUST be destroyed using the
* nxplayer_destroy() routine since the context is reference counted.
* The context can be used in a mode where the caller creates the
* context, starts a file playing, and then forgets about the context
* and it will self free. This is because the nxplayer_playfile
* will also create a reference to the context, so the client calling
* nxplayer_destroy() won't actually de-allocate anything. The freeing
* will occur after the playthread has completed.
*
* Alternately, the caller can create the objec and hold on to it, then
* the context will persist until the original creator destroys it.
*
* Input Parameters: None
*
* Returned values:
* Pointer to created NxPlayer context or NULL if error.
*
**************************************************************************/
FAR struct nxplayer_s *nxplayer_create(void);
/****************************************************************************
* Name: nxplayer_release
*
* Reduces the reference count to the player and if it reaches zero,
* frees all memory used by the context.
*
* Input Parameters:
* pPlayer Pointer to the NxPlayer context
*
* Returned values: None
*
**************************************************************************/
void nxplayer_release(FAR struct nxplayer_s *pPlayer);
/****************************************************************************
* Name: nxplayer_reference
*
* Increments the reference count to the player.
*
* Input Parameters:
* pPlayer Pointer to the NxPlayer context
*
* Returned values: None
*
**************************************************************************/
void nxplayer_reference(FAR struct nxplayer_s *pPlayer);
/****************************************************************************
* Name: nxplayer_setdevice
*
* Sets the preferred Audio device to use with the instance of the
* nxplayer. Without a preferred device set, the nxplayer will search
* the audio subsystem to find a suitable device depending on the
* type of audio operation requested (i.e. an MP3 decoder device when
* playing an MP3 file, a WAV decoder device for a WAV file, etc.).
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
* device - Pointer to pathname of the preferred device
*
* Returned values:
* OK if context initialized successfully, error code otherwise.
*
**************************************************************************/
int nxplayer_setdevice(FAR struct nxplayer_s *pPlayer, char* device);
/****************************************************************************
* Name: nxplayer_playfile
*
* Plays the specified media file (from the filesystem) using the
* Audio system. If a preferred device has been set, that device
* will be used for the playback, otherwise the first suitable device
* found in the /dev/audio directory will be used.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
* filename - Pointer to pathname of the file to play
* filefmt - Format of audio in filename if known, AUDIO_FMT_UNDEF
* to let nxplayer_playfile() determine automatically.
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
int nxplayer_playfile(FAR struct nxplayer_s *pPlayer, char* filename,
int filefmt);
/****************************************************************************
* Name: nxplayer_stop
*
* Stops current playback.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
int nxplayer_stop(FAR struct nxplayer_s *pPlayer);
#endif
/****************************************************************************
* Name: nxplayer_pause
*
* Pauses current playback.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
int nxplayer_pause(FAR struct nxplayer_s *pPlayer);
#endif
/****************************************************************************
* Name: nxplayer_resume
*
* Resuems current playback.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
int nxplayer_resume(FAR struct nxplayer_s *pPlayer);
#endif
/****************************************************************************
* Name: nxplayer_setvolume
*
* Sets the playback volume. The volume is represented in 1/10th of a
* percent increments, so the range is 0-1000. A value of 10 would mean
* 1%.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
* volume - Volume level to set in 1/10th percent increments
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
int nxplayer_setvolume(FAR struct nxplayer_s *pPlayer, uint16_t volume);
#endif
/****************************************************************************
* Name: nxplayer_setbalance
*
* Sets the playback balance. The balance is represented in 1/10th of a
* percent increments, so the range is 0-1000. A value of 10 would mean
* 1%.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
* balance - Balance level to set in 1/10th percent increments
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
int nxplayer_setbalance(FAR struct nxplayer_s *pPlayer, uint16_t balance);
#endif
#endif
/****************************************************************************
* Name: nxplayer_setmediadir
*
* Sets the root media directory for non-path qualified file searches.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
* mediadir - Pointer to pathname of the media directory
*
*
**************************************************************************/
inline void nxplayer_setmediadir(FAR struct nxplayer_s *pPlayer, char* mediadir);
/****************************************************************************
* Name: nxplayer_setbass
*
* Sets the playback bass level. The bass is represented in one percent
* increments, so the range is 0-100.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
* bass - Bass level to set in one percent increments
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
int nxplayer_setbass(FAR struct nxplayer_s *pPlayer, uint8_t bass);
#endif
/****************************************************************************
* Name: nxplayer_settreble
*
* Sets the playback treble level. The bass is represented in one percent
* increments, so the range is 0-100.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
* treble - Treble level to set in one percent increments
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
int nxplayer_settreble(FAR struct nxplayer_s *pPlayer, uint8_t treble);
#endif
/****************************************************************************
* Name: nxplayer_systemreset
*
* Performs an audio system reset, including a hardware reset on all
* registered audio devices.
*
* Input Parameters:
* pPlayer - Pointer to the context to initialize
*
* Returned values:
* OK if file found, device found, and playback started.
*
**************************************************************************/
#ifdef CONFIG_NXPLAYER_INCLUDE_SYSTEM_RESET
int nxplayer_systemreset(FAR struct nxplayer_s *pPlayer);
#endif
#endif /* __APPS_SYSTEM_NXPLAYER_NXPLAYER_H */

View file

@ -27,6 +27,10 @@ menu "FLASH Erase-all Command"
source "$APPSDIR/system/flash_eraseall/Kconfig"
endmenu
menu "NxPlayer media player library / command Line"
source "$APPSDIR/system/nxplayer/Kconfig"
endmenu
menu "RAM test"
source "$APPSDIR/system/ramtest/Kconfig"
endmenu

View file

@ -58,6 +58,10 @@ ifeq ($(CONFIG_SYSTEM_FLASH_ERASEALL),y)
CONFIGURED_APPS += system/flash_eraseall
endif
ifeq ($(CONFIG_SYSTEM_NXPLAYER),y)
CONFIGURED_APPS += system/nxplayer
endif
ifeq ($(CONFIG_SYSTEM_RAMTEST),y)
CONFIGURED_APPS += system/ramtest
endif

View file

@ -37,9 +37,9 @@
# Sub-directories containing system task
SUBDIRS = cdcacm composite flash_eraseall free i2c install poweroff
SUBDIRS += ramtest ramtron readline sdcard stackmonitor sysinfo usbmonitor
SUBDIRS += usbmsc zmodem
SUBDIRS = cdcacm composite flash_eraseall free i2c install nxplayer
SUBDIRS += poweroff ramtest ramtron readline sdcard stackmonitor sysinfo
SUBDIRS += usbmonitor usbmsc zmodem
# Create the list of installed runtime modules (INSTALLED_DIRS)

11
system/nxplayer/.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
/Make.dep
/.depend
/.built
/*.asm
/*.rel
/*.lst
/*.sym
/*.adb
/*.lib
/*.src
/*.obj

109
system/nxplayer/Kconfig Normal file
View file

@ -0,0 +1,109 @@
#
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
config SYSTEM_NXPLAYER
bool "NxPlayer library / command line support"
default n
---help---
Enable support for the command line media player
if SYSTEM_NXPLAYER
config NXPLAYER_COMMAND_LINE
bool "Include nxplayer command line application"
default y
---help---
Compiles in code for the nxplayer command line control.
This is a text-based command line interface that uses
the nxplayer library to play media files, control the
volume, balance, bass, etc.
if NXPLAYER_COMMAND_LINE
config NXPLAYER_INCLUDE_HELP
bool "Include HELP command and text"
default y
---help---
Compiles in the NxPlayer help text to provide online help
for available commands with syntax.
endif
config NXPLAYER_INCLUDE_DEVICE_SEARCH
bool "Include audio device search code"
default y
---help---
Compiles in extra code to search the audio device directory
for a suitable audio device to play the specified file.
Disabling this feature saves some code space, but it will
mean the calling application must specify the path of the
audio device to use before performing any other operations.
config NXPLAYER_INCLUDE_PREFERRED_DEVICE
bool "Include preferred audio device specification code"
default y
---help---
Adds support for identifying a specific audio device to use
for audio operations. If this feature is not enabled, then
an audio device search will be performed.
config NXPLAYER_FMT_FROM_EXT
bool "Include code to determine Audio format from extension"
default y
---help---
Compiles in extra code to determine audio format based
on the filename extension for known file types.
This feature is used if the format is not manually
specified, and will take priority over the more lengthy
file content detection approach.
config NXPLAYER_FMT_FROM_HEADER
bool "Include code to find Audio format from file content"
default n
---help---
Compiles in extra code to determine audio format based
on the header content of a file for known file types.
This feature is used when the format type cannot be
determined from the filename extension.
config NXPLAYER_INCLUDE_MEDIADIR
bool "Include support for specifying a media directory"
default y
---help---
Compiles in extra code to set a media directory which
will be searched when a request is made to play a file
which is not fully qualified.
if NXPLAYER_INCLUDE_MEDIADIR
config NXPLAYER_DEFAULT_MEDIADIR
string "Default root directory to search for media files"
default "/music"
---help---
Specifies a root directory to search for media files
when an absolute path is not provided. This can be
changed at the nxplayer command line, but will default
to this value each time nxplayer is launched.
config NXPLAYER_RECURSIVE_MEDIA_SEARCH
bool "Perform recursive directory search for media files"
default n
---help---
When enabled, this feature will add code to perform
a complete recursive directory search within the
MEDIADIR for any media files that do not have a
qualified path (i.e. contain no '/' characters).
endif
config NXPLAYER_INCLUDE_SYSTEM_RESET
bool "Include support for system / hardware reset"
default n
---help---
When enabled, this feature will add code to enable issuing
a HW reset via program call. The system reset will perform
a reset on all registered audio devices.
endif

131
system/nxplayer/Makefile Normal file
View file

@ -0,0 +1,131 @@
############################################################################
# apps/system/nxplayer/Makefile
#
# Copyright (C) 2013 Ken Pettit. All rights reserved.
# Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
# Author: Ken Pettit <pettitkd@gmail.com>
# Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
# TODO, this makefile should run make under the app dirs, instead of
# sourcing the Make.defs!
-include $(TOPDIR)/.config
-include $(TOPDIR)/Make.defs
include $(APPDIR)/Make.defs
ifeq ($(WINTOOL),y)
INCDIROPT = -w
endif
# NxPlayer Library
ASRCS =
CSRCS = nxplayer.c
# NxPlayer Application
APPNAME = nxplayer
PRIORITY = SCHED_PRIORITY_DEFAULT
STACKSIZE = 3100
ifeq ($(CONFIG_NXPLAYER_COMMAND_LINE),y)
CSRCS += nxplayer_main.c
endif
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
OBJS = $(AOBJS) $(COBJS)
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
BIN = ..\..\libapps$(LIBEXT)
else
ifeq ($(WINTOOL),y)
BIN = ..\\..\\libapps$(LIBEXT)
else
BIN = ../../libapps$(LIBEXT)
endif
endif
ROOTDEPPATH = --dep-path .
# Common build
VPATH =
all: .built
.PHONY: context depend clean distclean
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
$(COBJS): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)
.built: $(OBJS)
$(call ARCHIVE, $(BIN), $(OBJS))
$(Q) touch .built
# Register application
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
ifeq ($(CONFIG_NXPLAYER_COMMAND_LINE),y)
$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
else
context:
endif
else
context:
endif
# Create dependencies
.depend: Makefile $(SRCS)
$(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
$(Q) touch $@
depend: .depend
clean:
$(call DELFILE, .built)
$(call CLEAN)
rm -rf ..$(DELIM)..$(DELIM)builtin$(DELIM)registry$(DELIM)$(APPNAME)_main.*
distclean: clean
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
-include Make.dep

View file

@ -0,0 +1,17 @@
NXPlayer
========
Source: NuttX
Author: Ken Pettit
Date: 11 Sept 2013
This application implements a command-line media player
which uses the NuttX Audio system to play files (mp3,
wav, etc.) from the file system.
Usage:
nxplayer
The application presents an command line for specifying
player commands, such as "play filename", "pause",
"volume 50%", etc.

1513
system/nxplayer/nxplayer.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,666 @@
/****************************************************************************
* apps/system/nxplayer/nxplayer_main.c
*
* Copyright (C) 2013 Ken Pettit. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/audio/audio.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <apps/readline.h>
#include <apps/nxplayer.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define NXPLAYER_VER "1.04"
#ifdef CONFIG_NXPLAYER_INCLUDE_HELP
# define NXPLAYER_HELP_TEXT(x) #x
#else
# define NXPLAYER_HELP_TEXT(x)
#endif
/****************************************************************************
* Private Type Declarations
****************************************************************************/
struct mp_cmd_s {
const char *cmd; /* The command text */
const char *arghelp; /* Text describing the args */
nxplayer_func pFunc; /* Pointer to command handler */
const char *help; /* The help text */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int nxplayer_cmd_quit(FAR struct nxplayer_s *pPlayer, char* parg);
static int nxplayer_cmd_play(FAR struct nxplayer_s *pPlayer, char* parg);
#ifdef CONFIG_NXPLAYER_INCLUDE_SYSTEM_RESET
static int nxplayer_cmd_reset(FAR struct nxplayer_s *pPlayer, char* parg);
#endif
#ifdef CONFIG_NXPLAYER_INCLUDE_PREFERRED_DEVICE
static int nxplayer_cmd_device(FAR struct nxplayer_s *pPlayer, char* parg);
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
static int nxplayer_cmd_pause(FAR struct nxplayer_s *pPlayer, char* parg);
static int nxplayer_cmd_resume(FAR struct nxplayer_s *pPlayer, char* parg);
#endif
#ifdef CONFIG_NXPLAYER_INCLUDE_MEDIADIR
static int nxplayer_cmd_mediadir(FAR struct nxplayer_s *pPlayer, char* parg);
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
static int nxplayer_cmd_stop(FAR struct nxplayer_s *pPlayer, char* parg);
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
static int nxplayer_cmd_volume(FAR struct nxplayer_s *pPlayer, char* parg);
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
static int nxplayer_cmd_balance(FAR struct nxplayer_s *pPlayer, char* parg);
#endif
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
static int nxplayer_cmd_bass(FAR struct nxplayer_s *pPlayer, char* parg);
static int nxplayer_cmd_treble(FAR struct nxplayer_s *pPlayer, char* parg);
#endif
#ifdef CONFIG_NXPLAYER_INCLUDE_HELP
static int nxplayer_cmd_help(FAR struct nxplayer_s *pPlayer, char* parg);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
static struct mp_cmd_s g_nxplayer_cmds[] =
{
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
{ "balance", "d%", nxplayer_cmd_balance, NXPLAYER_HELP_TEXT(Set balance percentage (< 50% means more left)) },
#endif
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
{ "bass", "d%", nxplayer_cmd_bass, NXPLAYER_HELP_TEXT(Set bass level percentage) },
#endif
#ifdef CONFIG_NXPLAYER_INCLUDE_PREFERRED_DEVICE
{ "device", "devfile", nxplayer_cmd_device, NXPLAYER_HELP_TEXT(Specify a preferred audio device) },
#endif
#ifdef CONFIG_NXPLAYER_INCLUDE_HELP
{ "h", "", nxplayer_cmd_help, NXPLAYER_HELP_TEXT(Display help for commands) },
{ "help", "", nxplayer_cmd_help, NXPLAYER_HELP_TEXT(Display help for commands) },
#endif
#ifdef CONFIG_NXPLAYER_INCLUDE_MEDIADIR
{ "mediadir", "path", nxplayer_cmd_mediadir, NXPLAYER_HELP_TEXT(Change the media directory) },
#endif
{ "play", "filename", nxplayer_cmd_play, NXPLAYER_HELP_TEXT(Play a media file) },
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
{ "pause", "", nxplayer_cmd_pause, NXPLAYER_HELP_TEXT(Pause playback) },
#endif
#ifdef CONFIG_NXPLAYER_INCLUDE_SYSTEM_RESET
{ "reset", "", nxplayer_cmd_reset, NXPLAYER_HELP_TEXT(Perform a HW reset) },
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
{ "resume", "", nxplayer_cmd_resume, NXPLAYER_HELP_TEXT(Resume playback) },
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
{ "stop", "", nxplayer_cmd_stop, NXPLAYER_HELP_TEXT(Stop playback) },
#endif
{ "tone", "freq secs",NULL, NXPLAYER_HELP_TEXT(Produce a pure tone) },
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
{ "treble", "d%", nxplayer_cmd_treble, NXPLAYER_HELP_TEXT(Set treble level percentage) },
#endif
{ "q", "", nxplayer_cmd_quit, NXPLAYER_HELP_TEXT(Exit NxPlayer) },
{ "quit", "", nxplayer_cmd_quit, NXPLAYER_HELP_TEXT(Exit NxPlayer) },
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
{ "volume", "d%", nxplayer_cmd_volume, NXPLAYER_HELP_TEXT(Set volume to level specified) }
#endif
};
static const int g_nxplayer_cmd_count = sizeof(g_nxplayer_cmds) / sizeof(struct mp_cmd_s);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: nxplayer_cmd_play
*
* nxplayer_cmd_play() plays the specified media file using the nxplayer
* context.
*
****************************************************************************/
static int nxplayer_cmd_play(FAR struct nxplayer_s *pPlayer, char* parg)
{
int ret;
/* Try to play the file specified */
ret = nxplayer_playfile(pPlayer, parg, AUDIO_FMT_UNDEF);
/* Test if the device file exists */
if (ret == -ENODEV)
{
printf("No suitable Audio Device found\n");
}
else if (ret == -EBUSY)
{
printf("Audio device busy\n");
}
else if (ret == -ENOENT)
{
printf("File %s not found\n", parg);
}
else if (ret == -ENOSYS)
{
printf("Unknown audio format\n");
}
if (ret < 0)
{
return ret;
}
/* File playing successfully */
return OK;
}
/****************************************************************************
* Name: nxplayer_cmd_volume
*
* nxplayer_cmd_volume() sets the volume level.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
static int nxplayer_cmd_volume(FAR struct nxplayer_s *pPlayer, char* parg)
{
uint16_t percent;
/* If no arg given, then print current volume */
if (parg == NULL || *parg == '\0')
{
printf("volume: %d%\n", pPlayer->volume / 10);
}
else
{
/* Get the percentage value from the argument */
percent = (uint16_t) (atof(parg) * 10.0);
nxplayer_setvolume(pPlayer, percent);
}
return OK;
}
#endif
/****************************************************************************
* Name: nxplayer_cmd_bass
*
* nxplayer_cmd_bass() sets the bass level and range.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
static int nxplayer_cmd_bass(FAR struct nxplayer_s *pPlayer, char* parg)
{
uint8_t level_percent;
/* If no arg given, then print current bass */
if (parg == NULL || *parg == '\0')
{
printf("bass: %d\n", pPlayer->bass);
}
else
{
/* Get the level and range percentage value from the argument */
level_percent = (uint8_t) atoi(parg);
nxplayer_setbass(pPlayer, level_percent);
}
return OK;
}
#endif
/****************************************************************************
* Name: nxplayer_cmd_treble
*
* nxplayer_cmd_treble() sets the treble level and range.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
static int nxplayer_cmd_treble(FAR struct nxplayer_s *pPlayer, char* parg)
{
uint8_t level_percent;
/* If no arg given, then print current bass */
if (parg == NULL || *parg == '\0')
{
printf("treble: %d\n", pPlayer->treble);
}
else
{
/* Get the level and range percentage value from the argument */
level_percent = (uint8_t) atoi(parg);
nxplayer_settreble(pPlayer, level_percent);
}
return OK;
}
#endif
/****************************************************************************
* Name: nxplayer_cmd_balance
*
* nxplayer_cmd_balance() sets the balance level.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
static int nxplayer_cmd_balance(FAR struct nxplayer_s *pPlayer, char* parg)
{
uint16_t percent;
/* If no arg given, then print current volume */
if (parg == NULL || *parg == '\0')
{
printf("balance: %d%\n", pPlayer->volume / 10);
}
else
{
/* Get the percentage value from the argument */
percent = (uint16_t) (atof(parg) * 10.0);
nxplayer_setbalance(pPlayer, percent);
}
return OK;
}
#endif
#endif
/****************************************************************************
* Name: nxplayer_cmd_reset
*
* nxplayer_cmd_reset() performs a HW reset of all the audio devices.
*
****************************************************************************/
#ifdef CONFIG_NXPLAYER_INCLUDE_SYSTEM_RESET
static int nxplayer_cmd_reset(FAR struct nxplayer_s *pPlayer, char* parg)
{
nxplayer_systemreset(pPlayer);
return OK;
}
#endif
/****************************************************************************
* Name: nxplayer_cmd_mediadir
*
* nxplayer_cmd_mediadir() displays or changes the media directory
* context.
*
****************************************************************************/
#ifdef CONFIG_NXPLAYER_INCLUDE_MEDIADIR
static int nxplayer_cmd_mediadir(FAR struct nxplayer_s *pPlayer, char* parg)
{
/* If no arg given, then print current media dir */
if (parg == NULL || *parg == '\0')
printf("%s\n", pPlayer->mediadir);
else
nxplayer_setmediadir(pPlayer, parg);
return OK;
}
#endif
/****************************************************************************
* Name: nxplayer_cmd_stop
*
* nxplayer_cmd_stop() stops playback of currently playing file
* context.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
static int nxplayer_cmd_stop(FAR struct nxplayer_s *pPlayer, char* parg)
{
/* Stop the playback */
nxplayer_stop(pPlayer);
return OK;
}
#endif
/****************************************************************************
* Name: nxplayer_cmd_pause
*
* nxplayer_cmd_pause() pauses playback of currently playing file
* context.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
static int nxplayer_cmd_pause(FAR struct nxplayer_s *pPlayer, char* parg)
{
/* Pause the playback */
nxplayer_pause(pPlayer);
return OK;
}
#endif
/****************************************************************************
* Name: nxplayer_cmd_resume
*
* nxplayer_cmd_resume() resumes playback of currently playing file
* context.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
static int nxplayer_cmd_resume(FAR struct nxplayer_s *pPlayer, char* parg)
{
/* Resume the playback */
nxplayer_resume(pPlayer);
return OK;
}
#endif
/****************************************************************************
* Name: nxplayer_cmd_device
*
* nxplayer_cmd_device() sets the preferred audio device for playback
*
****************************************************************************/
#ifdef CONFIG_NXPLAYER_INCLUDE_PREFERRED_DEVICE
static int nxplayer_cmd_device(FAR struct nxplayer_s *pPlayer, char* parg)
{
int ret;
char path[32];
/* First try to open the file directly */
ret = nxplayer_setdevice(pPlayer, parg);
if (ret == -ENOENT)
{
/* Append the /dev/audio path and try again */
#ifdef CONFIG_AUDIO_CUSTOM_DEV_PATH
#ifdef CONFIG_AUDIO_DEV_ROOT
snprintf(path, sizeof(path), "/dev/%s", parg);
#else
snprintf(path, sizeof(path), CONFIG_AUDIO_DEV_PATH "/%s", parg);
#endif
#else
snprintf(path, sizeof(path), "/dev/audio/%s", parg);
#endif
ret = nxplayer_setdevice(pPlayer, path);
}
/* Test if the device file exists */
if (ret == -ENOENT)
{
/* Device doesn't exit. Report error */
printf("Device %s not found\n", parg);
return ret;
}
/* Test if is is an audio device */
if (ret == -ENODEV)
{
printf("Device %s is not an audio device\n", parg);
return ret;
}
if (ret < 0)
{
return ret;
}
/* Device set successfully */
return OK;
}
#endif /* CONFIG_NXPLAYER_INCLUDE_PREFERRED_DEVICE */
/****************************************************************************
* Name: nxplayer_cmd_quit
*
* nxplayer_cmd_quit() terminates the application
****************************************************************************/
static int nxplayer_cmd_quit(FAR struct nxplayer_s *pPlayer, char* parg)
{
/* Nothing to do */
return OK;
}
/****************************************************************************
* Name: nxplayer_cmd_help
*
* nxplayer_cmd_help() displays the application's help information on
* supported commands and command syntax.
****************************************************************************/
#ifdef CONFIG_NXPLAYER_INCLUDE_HELP
static int nxplayer_cmd_help(FAR struct nxplayer_s *pPlayer, char* parg)
{
int x, len, maxlen = 0;
int c;
/* Calculate length of longest cmd + arghelp */
for (x = 0; x < g_nxplayer_cmd_count; x++)
{
len = strlen(g_nxplayer_cmds[x].cmd) + strlen(g_nxplayer_cmds[x].arghelp);
if (len > maxlen)
maxlen = len;
}
printf("NxPlayer commands\n================\n");
for (x = 0; x < g_nxplayer_cmd_count; x++)
{
/* Print the command and it's arguments */
printf(" %s %s", g_nxplayer_cmds[x].cmd, g_nxplayer_cmds[x].arghelp);
/* Calculate number of spaces to print before the help text */
len = maxlen - (strlen(g_nxplayer_cmds[x].cmd) + strlen(g_nxplayer_cmds[x].arghelp));
for (c = 0; c < len; c++)
printf(" ");
printf(" : %s\n", g_nxplayer_cmds[x].help);
}
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nxplayer
*
* nxplayer() reads in commands from the console using the readline
* system add-in and implemets a command-line based media player that
* uses the NuttX audio system to play media files read in from the
* file system. Commands are provided for setting volume, base and
* other audio features, as well as for pausing and stoping the
* playback.
*
* Input Parameters:
* buf - The user allocated buffer to be filled.
* buflen - the size of the buffer.
* instream - The stream to read characters from
* outstream - The stream to each characters to.
*
* Returned values:
* On success, the (positive) number of bytes transferred is returned.
* EOF is returned to indicate either an end of file condition or a
* failure.
*
**************************************************************************/
int nxplayer_main(int argc, char *argv[])
{
char buffer[64];
int len, x, running;
char *cmd, *arg;
FAR struct nxplayer_s *pPlayer;
printf("NxPlayer version " NXPLAYER_VER "\n");
printf("h for commands, q to exit\n");
printf("\n");
/* Initialize our NxPlayer context */
pPlayer = nxplayer_create();
if (pPlayer == NULL)
{
printf("Error: Out of RAM\n");
return -ENOMEM;
}
/* Loop until the user exits */
running = TRUE;
while (running)
{
/* Print a prompt */
printf("nxplayer> ");
fflush(stdout);
/* Read a line from the terminal */
len = readline(buffer, sizeof(buffer), stdin, stdout);
buffer[len] = '\0';
if (len > 0)
{
if (buffer[len-1] == '\n')
buffer[len-1] = '\0';
/* Parse the command from the argument */
cmd = strtok_r(buffer, " \n", &arg);
if (cmd == NULL)
continue;
/* Remove leading spaces from arg */
while (*arg == ' ')
arg++;
/* Find the command in our cmd array */
for (x = 0; x < g_nxplayer_cmd_count; x++)
{
if (strcmp(cmd, g_nxplayer_cmds[x].cmd) == 0)
{
/* Command found. Call it's handler if not NULL */
if (g_nxplayer_cmds[x].pFunc != NULL)
g_nxplayer_cmds[x].pFunc(pPlayer, arg);
/* Test if it is a quit command */
if (g_nxplayer_cmds[x].pFunc == nxplayer_cmd_quit)
running = FALSE;
break;
}
}
/* Test for Unknown command */
if (x == g_nxplayer_cmd_count)
printf("%s: unknown nxplayer command\n", buffer);
}
}
/* Release the NxPlayer context */
// nxplayer_detach(pPlayer);
nxplayer_release(pPlayer);
return OK;
}