NxPlayer: Fix some error handling, update comments, more debug output

This commit is contained in:
Gregory Nutt 2014-07-31 14:59:51 -06:00
parent 6671be97cc
commit cd546421d1

View File

@ -1,9 +1,16 @@
/**************************************************************************** /****************************************************************************
* apps/system/nxplayer/nxplayer.c * apps/system/nxplayer/nxplayer.c
* *
* Developed by:
*
* Copyright (C) 2013 Ken Pettit. All rights reserved. * Copyright (C) 2013 Ken Pettit. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com> * Author: Ken Pettit <pettitkd@gmail.com>
* *
* With ongoing support:
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Greory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
@ -487,11 +494,18 @@ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer,
struct audio_buf_desc_s bufdesc; struct audio_buf_desc_s bufdesc;
int ret; int ret;
/* Validate the file is still open */ /* Validate the file is still open. It will be closed automatically when
* we encounter the end of file (or, perhaps, a read error that we cannot
* handle.
*/
if (pPlayer->fileFd == NULL) if (pPlayer->fileFd == NULL)
{ {
return OK; /* Return -ENODATA to indicate that there is nothing more to read from
* the file.
*/
return -ENODATA;
} }
/* Read data into the buffer. */ /* Read data into the buffer. */
@ -508,6 +522,9 @@ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer,
* event. * event.
*/ */
audvdbg("Closing audio file, nbytes=%d readerr=%d\n",
pBuf->nbytes, readerror);
fclose(pPlayer->fileFd); fclose(pPlayer->fileFd);
pPlayer->fileFd = NULL; pPlayer->fileFd = NULL;
@ -518,7 +535,7 @@ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer,
DEBUGASSERT(errcode > 0); DEBUGASSERT(errcode > 0);
auddbg("ERROR: fread failed: %d\n", errcode); auddbg("ERROR: fread failed: %d\n", errcode);
return errcode; return -errcode;
} }
} }
@ -547,11 +564,19 @@ static int nxplayer_enqueuebuffer(FAR struct nxplayer_s *pPlayer,
DEBUGASSERT(errcode > 0); DEBUGASSERT(errcode > 0);
auddbg("ERROR: AUDIOIOC_ENQUEUEBUFFER ioctl failed: %d\n", errcode); auddbg("ERROR: AUDIOIOC_ENQUEUEBUFFER ioctl failed: %d\n", errcode);
return errcode; return -errcode;
}
} }
/* Return OK to indicate that we successfully read data from the file
* (and we are not yet at the end of file)
*/
return OK; return OK;
}
/* Return -ENODATA if we are at the end of file */
return -ENODATA;
} }
/**************************************************************************** /****************************************************************************
@ -569,7 +594,7 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
struct audio_buf_desc_s buf_desc; struct audio_buf_desc_s buf_desc;
ssize_t size; ssize_t size;
uint8_t running = true; uint8_t running = true;
uint8_t playing = true; uint8_t streaming = true;
#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS #ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
struct ap_buffer_info_s buf_info; struct ap_buffer_info_s buf_info;
FAR struct ap_buffer_s** pBuffers; FAR struct ap_buffer_s** pBuffers;
@ -580,7 +605,7 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
int x; int x;
int ret; int ret;
auddbg("Entry\n"); audvdbg("Entry\n");
/* Query the audio device for it's preferred buffer size / qty */ /* Query the audio device for it's preferred buffer size / qty */
@ -589,6 +614,7 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
(unsigned long) &buf_info)) != OK) (unsigned long) &buf_info)) != OK)
{ {
/* Driver doesn't report it's buffer size. Use our default. */ /* Driver doesn't report it's buffer size. Use our default. */
buf_info.buffer_size = CONFIG_AUDIO_BUFFER_NUMBYTES; buf_info.buffer_size = CONFIG_AUDIO_BUFFER_NUMBYTES;
buf_info.nbuffers = CONFIG_AUDIO_NUM_BUFFERS; buf_info.nbuffers = CONFIG_AUDIO_NUM_BUFFERS;
} }
@ -634,13 +660,14 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
buf_desc.numbytes = CONFIG_AUDIO_BUFFER_NUMBYTES; buf_desc.numbytes = CONFIG_AUDIO_BUFFER_NUMBYTES;
#endif #endif
buf_desc.u.ppBuffer = &pBuffers[x]; buf_desc.u.ppBuffer = &pBuffers[x];
ret = ioctl(pPlayer->devFd, AUDIOIOC_ALLOCBUFFER, ret = ioctl(pPlayer->devFd, AUDIOIOC_ALLOCBUFFER,
(unsigned long) &buf_desc); (unsigned long) &buf_desc);
if (ret != sizeof(buf_desc)) if (ret != sizeof(buf_desc))
{ {
/* Buffer alloc Operation not supported or error allocating! */ /* Buffer alloc Operation not supported or error allocating! */
auddbg("nxplayer_playthread: can't alloc buffer %d\n", x); auddbg("ERROR: Could not allocate buffer %d\n", x);
running = false; running = false;
goto err_out; goto err_out;
} }
@ -667,13 +694,18 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
} }
else else
{ {
playing = false; /* We are no longer streaming data from the file */
streaming = false;
} }
break; break;
} }
} }
audvdbg("%d buffers queued, running=%d streaming=%d\n",
x, running, streaming);
/* Start the audio device */ /* Start the audio device */
#ifdef CONFIG_AUDIO_MULTI_SESSION #ifdef CONFIG_AUDIO_MULTI_SESSION
@ -682,6 +714,7 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
#else #else
ret = ioctl(pPlayer->devFd, AUDIOIOC_START, 0); ret = ioctl(pPlayer->devFd, AUDIOIOC_START, 0);
#endif #endif
if (ret < 0) if (ret < 0)
{ {
/* Error starting the audio stream! */ /* Error starting the audio stream! */
@ -693,21 +726,31 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
pPlayer->state = NXPLAYER_STATE_PLAYING; pPlayer->state = NXPLAYER_STATE_PLAYING;
/* Set parameters such as volume, bass, etc. */ /* Set initial parameters such as volume, bass, etc.
* REVISIT: Shouldn't this actually be done BEFORE we start playing?
*/
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME #ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
(void)nxplayer_setvolume(pPlayer, pPlayer->volume); (void)nxplayer_setvolume(pPlayer, pPlayer->volume);
#endif #endif
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE #ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
nxplayer_setbalance(pPlayer, pPlayer->balance); nxplayer_setbalance(pPlayer, pPlayer->balance);
#endif #endif
#ifndef CONFIG_AUDIO_EXCLUDE_TONE #ifndef CONFIG_AUDIO_EXCLUDE_TONE
nxplayer_setbass(pPlayer, pPlayer->bass); nxplayer_setbass(pPlayer, pPlayer->bass);
nxplayer_settreble(pPlayer, pPlayer->treble); nxplayer_settreble(pPlayer, pPlayer->treble);
#endif #endif
/* Loop until we specifically break */ /* Loop until we specifically break. running == true means that we are
* still looping waiting for the playback to complete. All of the file
* data may have been sent (if streaming == false), but the playback is
* not complete until we get the AUDIO_MSG_COMPLETE (or AUDIO_MSG_STOP)
* message
*/
audvdbg("%s\n", running ? "Playing..." : "Not runnning");
while (running) while (running)
{ {
/* Wait for a signal either from the Audio driver that it needs /* Wait for a signal either from the Audio driver that it needs
@ -723,6 +766,7 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
{ {
/* Interrupted by a signal? What to do? */ /* Interrupted by a signal? What to do? */
continue;
} }
/* Perform operation based on message id */ /* Perform operation based on message id */
@ -732,21 +776,22 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
/* An audio buffer is being dequeued by the driver */ /* An audio buffer is being dequeued by the driver */
case AUDIO_MSG_DEQUEUE: case AUDIO_MSG_DEQUEUE:
/* Read data from the file directly into this buffer /* Read data from the file directly into this buffer and
* and re-enqueue it. * re-enqueue it. streaming == true means that we have
* not yet hit the end-of-file.
*/ */
if (playing) if (streaming)
{ {
ret = nxplayer_enqueuebuffer(pPlayer, msg.u.pPtr); ret = nxplayer_enqueuebuffer(pPlayer, msg.u.pPtr);
if (ret != OK) if (ret != OK)
{ {
/* Out of data. Stay in the loop until the /* Out of data. Stay in the loop until the device sends
* device sends us a COMPLETE message, but stop * us a COMPLETE message, but stop trying to play more
* trying to play more data. * data.
*/ */
playing = false; streaming = false;
} }
} }
break; break;
@ -756,19 +801,22 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
case AUDIO_MSG_STOP: case AUDIO_MSG_STOP:
/* Send a stop message to the device */ /* Send a stop message to the device */
audvdbg("Stopping!\n");
#ifdef CONFIG_AUDIO_MULTI_SESSION #ifdef CONFIG_AUDIO_MULTI_SESSION
ioctl(pPlayer->devFd, AUDIOIOC_STOP, ioctl(pPlayer->devFd, AUDIOIOC_STOP,
(unsigned long) pPlayer->session); (unsigned long) pPlayer->session);
#else #else
ioctl(pPlayer->devFd, AUDIOIOC_STOP, 0); ioctl(pPlayer->devFd, AUDIOIOC_STOP, 0);
#endif #endif
playing = false; streaming = false;
running = false; running = false;
break; break;
/* Message indicating the playback is complete */ /* Message indicating the playback is complete */
case AUDIO_MSG_COMPLETE: case AUDIO_MSG_COMPLETE:
audvdbg("Play complete\n");
running = false; running = false;
break; break;
@ -782,6 +830,8 @@ static void *nxplayer_playthread(pthread_addr_t pvarg)
/* Release our audio buffers and unregister / release the device */ /* Release our audio buffers and unregister / release the device */
err_out: err_out:
audvdbg("Clean-up and exit\n");
/* Unregister the message queue and release the session */ /* Unregister the message queue and release the session */
ioctl(pPlayer->devFd, AUDIOIOC_UNREGISTERMQ, (unsigned long) pPlayer->mq); ioctl(pPlayer->devFd, AUDIOIOC_UNREGISTERMQ, (unsigned long) pPlayer->mq);
@ -799,7 +849,7 @@ err_out:
#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS #ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
if (pBuffers != NULL) if (pBuffers != NULL)
{ {
auddbg("Freeing buffers\n"); audvdbg("Freeing buffers\n");
for (x = 0; x < buf_info.nbuffers; x++) for (x = 0; x < buf_info.nbuffers; x++)
{ {
/* Fill in the buffer descriptor struct to issue a free request */ /* Fill in the buffer descriptor struct to issue a free request */
@ -816,7 +866,7 @@ err_out:
free(pBuffers); free(pBuffers);
} }
#else #else
auddbg("Freeing buffers\n"); audvdbg("Freeing buffers\n");
for (x = 0; x < CONFIG_AUDIO_NUM_BUFFERS; x++) for (x = 0; x < CONFIG_AUDIO_NUM_BUFFERS; x++)
{ {
/* Fill in the buffer descriptor struct to issue a free request */ /* Fill in the buffer descriptor struct to issue a free request */
@ -851,7 +901,7 @@ err_out:
nxplayer_release(pPlayer); nxplayer_release(pPlayer);
auddbg("Exit\n"); audvdbg("Exit\n");
return NULL; return NULL;
} }
@ -1459,9 +1509,9 @@ int nxplayer_playfile(FAR struct nxplayer_s *pPlayer,
return -EBUSY; return -EBUSY;
} }
auddbg("==============================\n"); audvdbg("==============================\n");
auddbg("Playing file %s\n", pFilename); audvdbg("Playing file %s\n", pFilename);
auddbg("==============================\n"); audvdbg("==============================\n");
/* Test that the specified file exists */ /* Test that the specified file exists */
@ -1519,7 +1569,7 @@ int nxplayer_playfile(FAR struct nxplayer_s *pPlayer,
{ {
/* Hmmm, it's some unknown / unsupported type */ /* Hmmm, it's some unknown / unsupported type */
auddbg("BERROR: Unsupported format: %d \n", filefmt); auddbg("ERROR: Unsupported format: %d \n", filefmt);
ret = -ENOSYS; ret = -ENOSYS;
goto err_out_nodev; goto err_out_nodev;
} }
@ -1609,7 +1659,7 @@ int nxplayer_playfile(FAR struct nxplayer_s *pPlayer,
(pthread_addr_t) pPlayer); (pthread_addr_t) pPlayer);
if (ret != OK) if (ret != OK)
{ {
auddbg("Error %d creating playthread\n", ret); auddbg("ERROR: Failed to create playthread: %d\n", ret);
goto err_out; goto err_out;
} }
@ -1735,9 +1785,12 @@ void nxplayer_release(FAR struct nxplayer_s* pPlayer)
while ((ret = sem_wait(&pPlayer->sem)) != OK) while ((ret = sem_wait(&pPlayer->sem)) != OK)
{ {
if (ret != -EINTR) int errcode = errno;
DEBUGASSERT(errcode > 0);
if (errcode != EINTR)
{ {
auddbg("Error getting semaphore\n"); auddbg("ERROR: sem_wait failed: %d\n", errcode);
return; return;
} }
} }
@ -1749,11 +1802,15 @@ void nxplayer_release(FAR struct nxplayer_s* pPlayer)
sem_post(&pPlayer->sem); sem_post(&pPlayer->sem);
pthread_join(pPlayer->playId, &value); pthread_join(pPlayer->playId, &value);
pPlayer->playId = 0; pPlayer->playId = 0;
while ((ret = sem_wait(&pPlayer->sem)) != OK) while ((ret = sem_wait(&pPlayer->sem)) != OK)
{ {
if (ret != -EINTR) int errcode = errno;
DEBUGASSERT(errcode > 0);
if (errcode != -EINTR)
{ {
auddbg("Error getting semaphore\n"); auddbg("ERROR: sem_wait failed: %d\n", errcode);
return; return;
} }
} }
@ -1790,9 +1847,12 @@ void nxplayer_reference(FAR struct nxplayer_s* pPlayer)
while ((ret = sem_wait(&pPlayer->sem)) != OK) while ((ret = sem_wait(&pPlayer->sem)) != OK)
{ {
if (ret != -EINTR) int errcode = errno;
DEBUGASSERT(errcode > 0);
if (errcode != -EINTR)
{ {
auddbg("Error getting semaphore\n"); auddbg("ERROR: sem_wait failed: %d\n", errcode);
return; return;
} }
} }
@ -1826,9 +1886,12 @@ void nxplayer_detach(FAR struct nxplayer_s* pPlayer)
while ((ret = sem_wait(&pPlayer->sem)) != OK) while ((ret = sem_wait(&pPlayer->sem)) != OK)
{ {
if (ret != -EINTR) int errcode = errno;
DEBUGASSERT(errcode > 0);
if (errcode != -EINTR)
{ {
auddbg("Error getting semaphore\n"); auddbg("ERROR: sem_wait failed: %d\n", errcode);
return; return;
} }
} }