diff options
-rw-r--r-- | firmware/target/hosted/pcm-alsa.c | 47 |
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 */ |
73 | static char device[] = "plughw:0,0"; /* playback device */ | 71 | #define DEFAULT_PLAYBACK_DEVICE "plughw:0,0" |
72 | |||
73 | #define USE_ASYNC_CALLBACK | ||
74 | |||
74 | static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */ | 75 | static 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 * | |||
81 | typedef short sample_t; | 82 | typedef short sample_t; |
82 | #endif | 83 | #endif |
83 | static const int channels = 2; /* count of channels */ | 84 | static const int channels = 2; /* count of channels */ |
84 | static unsigned int real_sample_rate = 0; | 85 | static unsigned int real_sample_rate; |
85 | static unsigned int last_sample_rate = 0; | 86 | static unsigned int last_sample_rate; |
86 | 87 | ||
87 | static snd_pcm_t *handle = NULL; | 88 | static snd_pcm_t *handle = NULL; |
88 | static snd_pcm_sframes_t buffer_size; | 89 | static 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 | ||
457 | void pcm_play_dma_init(void) | 459 | static 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(); | 482 | void 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); |