Skip to content

Commit

Permalink
Merge pull request #198 from dvdli/tinyalsa-dev
Browse files Browse the repository at this point in the history
fix bugs
  • Loading branch information
dvdli committed Feb 1, 2021
2 parents 8c5da09 + 5e65c16 commit 1c5fb68
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
@@ -1,5 +1,5 @@
os: linux
dist: xenial
dist: bionic
sudo: false
language: c
compiler:
Expand Down
4 changes: 2 additions & 2 deletions include/tinyalsa/pcm.h
Expand Up @@ -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);

Expand Down
78 changes: 48 additions & 30 deletions src/pcm.c
Expand Up @@ -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.
Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -1064,15 +1068,15 @@ 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;
}

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;
Expand All @@ -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;
}

Expand All @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion tests/src/mixer_test.cc
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions tests/src/pcm_in_test.cc
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions tests/src/pcm_out_test.cc
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion utils/tinymix.c
Expand Up @@ -370,7 +370,7 @@ static void tinymix_set_byte_ctl(struct mixer_ctl *ctl,

static int is_int(const char *value)
{
return value[0] >= '0' || value[0] <= '9';
return value[0] >= '0' && value[0] <= '9';
}

struct parsed_int
Expand Down
3 changes: 3 additions & 0 deletions utils/tinyplay.c
Expand Up @@ -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;
Expand Down

0 comments on commit 1c5fb68

Please sign in to comment.