diff options
author | dvdli <70133153+dvdli@users.noreply.github.com> | 2021-02-01 13:29:04 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-01 13:29:04 +0800 |
commit | 1c5fb68ced57d838f2b7ecd0c00bc1fefc9ab60d (patch) | |
tree | 8b6a2d44a4291fa0c2cd3a79edbe123f52bb7a01 | |
parent | 8c5da09cd7c6b35323a61e50c9e988694eb81a8e (diff) | |
parent | 5e65c16b305b9e4a3ca858cfb1b7a188db0d5242 (diff) |
Merge pull request #198 from dvdli/tinyalsa-dev
fix bugs
-rw-r--r-- | .travis.yml | 2 | ||||
-rw-r--r-- | include/tinyalsa/pcm.h | 4 | ||||
-rw-r--r-- | src/pcm.c | 78 | ||||
-rw-r--r-- | tests/src/mixer_test.cc | 2 | ||||
-rw-r--r-- | tests/src/pcm_in_test.cc | 1 | ||||
-rw-r--r-- | tests/src/pcm_out_test.cc | 6 | ||||
-rw-r--r-- | utils/tinymix.c | 2 | ||||
-rw-r--r-- | utils/tinyplay.c | 3 |
8 files changed, 60 insertions, 38 deletions
diff --git a/.travis.yml b/.travis.yml index 28667cb..4186666 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ os: linux -dist: xenial +dist: bionic sudo: false language: c compiler: diff --git a/include/tinyalsa/pcm.h b/include/tinyalsa/pcm.h index 6569146..b40550c 100644 --- a/include/tinyalsa/pcm.h +++ b/include/tinyalsa/pcm.h @@ -335,9 +335,9 @@ int pcm_write(struct pcm *pcm, const void *data, unsigned int count) TINYALSA_DE int pcm_read(struct pcm *pcm, void *data, unsigned int count) TINYALSA_DEPRECATED; -int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count); +int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count) TINYALSA_DEPRECATED; -int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count); +int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count) TINYALSA_DEPRECATED; int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, unsigned int *frames); @@ -995,24 +995,25 @@ int pcm_close(struct pcm *pcm) * - @ref PCM_MONOTONIC * @param config The hardware and software parameters to open the PCM with. * @returns A PCM structure. - * If an error occurs allocating memory for the PCM, NULL is returned. - * Otherwise, client code should check that the PCM opened properly by calling @ref pcm_is_ready. - * If @ref pcm_is_ready, check @ref pcm_get_error for more information. + * If an error occurs, the pointer of bad_pcm is returned. + * Otherwise, it returns the pointer of PCM object. + * Client code should check that the PCM opened properly by calling @ref pcm_is_ready. + * If @ref pcm_is_ready returns false, check @ref pcm_get_error for more information. * @ingroup libtinyalsa-pcm */ struct pcm *pcm_open_by_name(const char *name, unsigned int flags, const struct pcm_config *config) { - unsigned int card, device; - if ((name[0] != 'h') - || (name[1] != 'w') - || (name[2] != ':')) { - return NULL; - } else if (sscanf(&name[3], "%u,%u", &card, &device) != 2) { - return NULL; - } - return pcm_open(card, device, flags, config); + unsigned int card, device; + if (name[0] != 'h' || name[1] != 'w' || name[2] != ':') { + oops(&bad_pcm, 0, "name format is not matched"); + return &bad_pcm; + } else if (sscanf(&name[3], "%u,%u", &card, &device) != 2) { + oops(&bad_pcm, 0, "name format is not matched"); + return &bad_pcm; + } + return pcm_open(card, device, flags, config); } /** Opens a PCM. @@ -1029,9 +1030,10 @@ struct pcm *pcm_open_by_name(const char *name, * - @ref PCM_MONOTONIC * @param config The hardware and software parameters to open the PCM with. * @returns A PCM structure. - * If an error occurs allocating memory for the PCM, NULL is returned. - * Otherwise, client code should check that the PCM opened properly by calling @ref pcm_is_ready. - * If @ref pcm_is_ready, check @ref pcm_get_error for more information. + * If an error occurs, the pointer of bad_pcm is returned. + * Otherwise, it returns the pointer of PCM object. + * Client code should check that the PCM opened properly by calling @ref pcm_is_ready. + * If @ref pcm_is_ready returns false, check @ref pcm_get_error for more information. * @ingroup libtinyalsa-pcm */ struct pcm *pcm_open(unsigned int card, unsigned int device, @@ -1042,8 +1044,10 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, int rc; pcm = calloc(1, sizeof(struct pcm)); - if (!pcm) + if (!pcm) { + oops(&bad_pcm, ENOMEM, "can't allocate PCM object"); return &bad_pcm; + } /* Default to hw_ops, attemp plugin open only if hw (/dev/snd/pcm*) open fails */ pcm->ops = &hw_ops; @@ -1055,7 +1059,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, pcm->snd_node = snd_utils_open_pcm(card, device); pcm_type = snd_utils_get_node_type(pcm->snd_node); if (!pcm->snd_node || pcm_type != SND_NODE_TYPE_PLUGIN) { - oops(pcm, -ENODEV, "no device (hw/plugin) for card(%u), device(%u)", + oops(&bad_pcm, ENODEV, "no device (hw/plugin) for card(%u), device(%u)", card, device); goto fail_close_dev_node; } @@ -1064,7 +1068,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, } #endif if (pcm->fd < 0) { - oops(pcm, errno, "cannot open device (%u) for card (%u)", + oops(&bad_pcm, errno, "cannot open device (%u) for card (%u)", device, card); goto fail_close_dev_node; } @@ -1072,7 +1076,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, pcm->flags = flags; if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_INFO, &info)) { - oops(pcm, errno, "cannot get info"); + oops(&bad_pcm, errno, "cannot get info"); goto fail_close; } pcm->subdevice = info.subdevice; @@ -1082,7 +1086,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, rc = pcm_hw_mmap_status(pcm); if (rc < 0) { - oops(pcm, errno, "mmap status failed"); + oops(&bad_pcm, errno, "mmap status failed"); goto fail; } @@ -1091,16 +1095,12 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, int arg = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC; rc = pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_TTSTAMP, &arg); if (rc < 0) { - oops(pcm, errno, "cannot set timestamp type"); + oops(&bad_pcm, errno, "cannot set timestamp type"); goto fail; } } #endif - /* prepare here so the user does not need to do this later */ - if (pcm_prepare(pcm)) - goto fail; - pcm->xruns = 0; return pcm; @@ -1238,6 +1238,7 @@ static inline int pcm_mmap_capture_avail(struct pcm *pcm) int pcm_mmap_avail(struct pcm *pcm) { + pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC); if (pcm->flags & PCM_IN) return pcm_mmap_capture_avail(pcm); else @@ -1546,18 +1547,31 @@ int pcm_mmap_transfer(struct pcm *pcm, void *buffer, unsigned int frames) int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count) { if ((~pcm->flags) & (PCM_OUT | PCM_MMAP)) - return -ENOSYS; + return -EINVAL; - return pcm_mmap_transfer(pcm, (void *)data, - pcm_bytes_to_frames(pcm, count)); + unsigned int frames = pcm_bytes_to_frames(pcm, count); + int res = pcm_writei(pcm, (void *) data, frames); + + if (res < 0) { + return res; + } + + return (unsigned int) res == frames ? 0 : -EIO; } int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count) { if ((~pcm->flags) & (PCM_IN | PCM_MMAP)) - return -ENOSYS; + return -EINVAL; + + unsigned int frames = pcm_bytes_to_frames(pcm, count); + int res = pcm_readi(pcm, data, frames); + + if (res < 0) { + return res; + } - return pcm_mmap_transfer(pcm, data, pcm_bytes_to_frames(pcm, count)); + return (unsigned int) res == frames ? 0 : -EIO; } /* Returns current read/write position in the mmap buffer with associated time stamp. */ @@ -1623,6 +1637,10 @@ static int pcm_generic_transfer(struct pcm *pcm, void *data, if (frames > INT_MAX) return -EINVAL; + if (pcm_state(pcm) == PCM_STATE_SETUP && pcm_prepare(pcm) != 0) { + return -1; + } + again: if (pcm->flags & PCM_MMAP) diff --git a/tests/src/mixer_test.cc b/tests/src/mixer_test.cc index 717269c..903fb8f 100644 --- a/tests/src/mixer_test.cc +++ b/tests/src/mixer_test.cc @@ -288,7 +288,7 @@ TEST_P(MixerControlsTest, Event) { EXPECT_EQ(mixer_wait_event(mixer_object, 1000), 1); - EXPECT_EQ(mixer_consume_event(mixer_object), 0); + EXPECT_EQ(mixer_consume_event(mixer_object), 1); thread.join(); ASSERT_EQ(mixer_subscribe_events(mixer_object, 0), 0); diff --git a/tests/src/pcm_in_test.cc b/tests/src/pcm_in_test.cc index e912abb..4d8a697 100644 --- a/tests/src/pcm_in_test.cc +++ b/tests/src/pcm_in_test.cc @@ -73,6 +73,7 @@ class PcmInTest : public ::testing::Test { }; TEST_F(PcmInTest, GetDelay) { + pcm_prepare(pcm_object); long delay = pcm_get_delay(pcm_object); std::cout << delay << std::endl; ASSERT_GE(delay, 0); diff --git a/tests/src/pcm_out_test.cc b/tests/src/pcm_out_test.cc index cbc6983..f8d4345 100644 --- a/tests/src/pcm_out_test.cc +++ b/tests/src/pcm_out_test.cc @@ -192,13 +192,13 @@ TEST_F(PcmOutMmapTest, Write) { buffer[i] = static_cast<char>(i); } - int written_frames = 0; + int res = 0; unsigned int frames = pcm_bytes_to_frames(pcm_object, buffer_size); pcm_start(pcm_object); auto start = std::chrono::steady_clock::now(); for (uint32_t i = 0; i < write_count; ++i) { - written_frames = pcm_mmap_write(pcm_object, buffer.get(), buffer_size); - ASSERT_EQ(written_frames, frames); + res = pcm_mmap_write(pcm_object, buffer.get(), buffer_size); + ASSERT_EQ(res, 0); } pcm_stop(pcm_object); diff --git a/utils/tinymix.c b/utils/tinymix.c index 5c0378c..e272ade 100644 --- a/utils/tinymix.c +++ b/utils/tinymix.c @@ -370,7 +370,7 @@ fail: static int is_int(const char *value) { - return value[0] >= '0' || value[0] <= '9'; + return value[0] >= '0' && value[0] <= '9'; } struct parsed_int diff --git a/utils/tinyplay.c b/utils/tinyplay.c index 2689158..4c7ccf6 100644 --- a/utils/tinyplay.c +++ b/utils/tinyplay.c @@ -303,6 +303,9 @@ int main(int argc, char **argv) case 'i': cmd.filetype = opts.optarg; break; + case 'M': + cmd.flags |= PCM_MMAP; + break; case 'h': print_usage(argv[0]); return EXIT_SUCCESS; |