summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2020-10-21 08:53:12 -0400
committerSolomon Peachy <pizza@shaftnet.org>2020-10-21 13:24:47 +0000
commit884d8922e37586c1916ee124e78721e6dd946606 (patch)
treee4dea4bec5286dbda51bf62e034833c593c5da7a
parent6b13437aff3a2720763f3918aaa5cd3ce1624625 (diff)
downloadrockbox-884d8922e37586c1916ee124e78721e6dd946606.tar.gz
rockbox-884d8922e37586c1916ee124e78721e6dd946606.zip
hosted: Allow ALSA driver to switch output device at runtime
* Allow output device name to be specified * Set hw/swparams prior to actual playback start, not at init * If told to open a new device, cleanly close down old one. Change-Id: Ib97310ec23588136c031466ee9c22312ab0f9f5a
-rw-r--r--firmware/target/hosted/pcm-alsa.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c
index db86a790d2..baa841ebe9 100644
--- a/firmware/target/hosted/pcm-alsa.c
+++ b/firmware/target/hosted/pcm-alsa.c
@@ -38,7 +38,6 @@
38 * supposedly safer, it appears to use more CPU (however I didn't measure it 38 * supposedly safer, it appears to use more CPU (however I didn't measure it
39 * accurately, only looked at htop). At least, in this mode the "default" 39 * accurately, only looked at htop). At least, in this mode the "default"
40 * device works which doesnt break with other apps running. 40 * device works which doesnt break with other apps running.
41 * device works which doesnt break with other apps running.
42 */ 41 */
43 42
44#include "autoconf.h" 43#include "autoconf.h"
@@ -66,11 +65,13 @@
66#include <pthread.h> 65#include <pthread.h>
67#include <signal.h> 66#include <signal.h>
68 67
69#define USE_ASYNC_CALLBACK
70/* plughw:0,0 works with both, however "default" is recommended. 68/* plughw:0,0 works with both, however "default" is recommended.
71 * default doesnt seem to work with async callback but doesn't break 69 * default doesnt seem to work with async callback but doesn't break
72 * with multple applications running */ 70 * with multple applications running */
73static char device[] = "plughw:0,0"; /* playback device */ 71#define DEFAULT_PLAYBACK_DEVICE "plughw:0,0"
72
73#define USE_ASYNC_CALLBACK
74
74static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */ 75static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */
75#if defined(SONY_NWZ_LINUX) || defined(HAVE_FIIO_LINUX_CODEC) 76#if defined(SONY_NWZ_LINUX) || defined(HAVE_FIIO_LINUX_CODEC)
76/* Sony NWZ must use 32-bit per sample */ 77/* Sony NWZ must use 32-bit per sample */
@@ -81,8 +82,8 @@ static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format *
81typedef short sample_t; 82typedef short sample_t;
82#endif 83#endif
83static const int channels = 2; /* count of channels */ 84static const int channels = 2; /* count of channels */
84static unsigned int real_sample_rate = 0; 85static unsigned int real_sample_rate;
85static unsigned int last_sample_rate = 0; 86static unsigned int last_sample_rate;
86 87
87static snd_pcm_t *handle = NULL; 88static snd_pcm_t *handle = NULL;
88static snd_pcm_sframes_t buffer_size; 89static snd_pcm_sframes_t buffer_size;
@@ -452,34 +453,39 @@ void cleanup(void)
452 free(frames); 453 free(frames);
453 frames = NULL; 454 frames = NULL;
454 snd_pcm_close(handle); 455 snd_pcm_close(handle);
456 handle = NULL;
455} 457}
456 458
457void pcm_play_dma_init(void) 459static void open_hwdev(const char *device)
458{ 460{
459 int err; 461 int err;
460 462
461 logf("PCM DMA Init"); 463 logf("opendev %s (%p)", device, handle);
462 464
463 audiohw_preinit(); 465 /* Close old handle first, if needed */
466 if (handle) {
467 pcm_play_dma_stop();
468 snd_pcm_close(handle);
469 handle = NULL;
470 }
464 471
465 if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) 472 if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
466 { 473 {
467 panicf("%s(): Cannot open device %s: %s\n", __func__, device, snd_strerror(err)); 474 panicf("%s(): Cannot open device %s: %s\n", __func__, device, snd_strerror(err));
468 } 475 }
469
470 if ((err = snd_pcm_nonblock(handle, 1))) 476 if ((err = snd_pcm_nonblock(handle, 1)))
471 panicf("Could not set non-block mode: %s\n", snd_strerror(err)); 477 panicf("Could not set non-block mode: %s\n", snd_strerror(err));
472 478
473 if ((err = set_hwparams(handle)) < 0) 479 last_sample_rate = 0;
474 { 480}
475 panicf("Setting of hwparams failed: %s\n", snd_strerror(err));
476 }
477 if ((err = set_swparams(handle)) < 0)
478 {
479 panicf("Setting of swparams failed: %s\n", snd_strerror(err));
480 }
481 481
482 pcm_dma_apply_settings(); 482void pcm_play_dma_init(void)
483{
484 logf("PCM DMA Init");
485
486 audiohw_preinit();
487
488 open_hwdev(DEFAULT_PLAYBACK_DEVICE);
483 489
484#ifdef USE_ASYNC_CALLBACK 490#ifdef USE_ASYNC_CALLBACK
485 pthread_mutexattr_t attr; 491 pthread_mutexattr_t attr;
@@ -527,7 +533,10 @@ static void pcm_dma_apply_settings_nolock(void)
527 audiohw_mute(true); 533 audiohw_mute(true);
528#endif 534#endif
529 snd_pcm_drop(handle); 535 snd_pcm_drop(handle);
530 set_hwparams(handle); 536
537 set_hwparams(handle); // FIXME: check return code?
538 set_swparams(handle); // FIXME: check return code?
539
531#if defined(HAVE_NWZ_LINUX_CODEC) 540#if defined(HAVE_NWZ_LINUX_CODEC)
532 /* Sony NWZ linux driver uses a nonstandard mecanism to set the sampling rate */ 541 /* Sony NWZ linux driver uses a nonstandard mecanism to set the sampling rate */
533 audiohw_set_frequency(pcm_sampr); 542 audiohw_set_frequency(pcm_sampr);