mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-03-27 07:58:02 -04:00
rawmidi: hide the frame structure using a decoder function
The frame structure should be hidden. Remove it and add snd_rawmidi_decode_frame0() which returns the timestamp and the midi chunk pointer to the application. BugLink: https://github.com/alsa-project/alsa-lib/issues/172 Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
754c696aef
commit
5e8a5fb754
3 changed files with 58 additions and 36 deletions
|
|
@ -93,26 +93,6 @@ typedef enum _snd_rawmidi_framing {
|
||||||
SND_RAWMIDI_FRAMING_TSTAMP = 1,
|
SND_RAWMIDI_FRAMING_TSTAMP = 1,
|
||||||
} snd_rawmidi_framing_t;
|
} snd_rawmidi_framing_t;
|
||||||
|
|
||||||
#define SND_RAWMIDI_FRAME_TYPE_DEFAULT 0
|
|
||||||
|
|
||||||
#define SND_RAWMIDI_FRAMING_DATA_LENGTH 16
|
|
||||||
|
|
||||||
/** Incoming RawMidi bytes is put inside this container if tstamp type framing is enabled. */
|
|
||||||
struct _snd_rawmidi_framing_tstamp {
|
|
||||||
/**
|
|
||||||
* For now, frame_type is always SND_RAWMIDI_FRAME_TYPE_DEFAULT.
|
|
||||||
* Midi 2.0 is expected to add new types here.
|
|
||||||
* Applications are expected to skip unknown frame types.
|
|
||||||
*/
|
|
||||||
uint8_t frame_type;
|
|
||||||
uint8_t length; /* number of valid bytes in data field */
|
|
||||||
uint8_t reserved[2];
|
|
||||||
uint32_t tv_nsec; /* nanoseconds */
|
|
||||||
uint64_t tv_sec; /* seconds */
|
|
||||||
uint8_t data[SND_RAWMIDI_FRAMING_DATA_LENGTH];
|
|
||||||
} __attribute__((packed));
|
|
||||||
typedef struct _snd_rawmidi_framing_tstamp snd_rawmidi_framing_tstamp_t;
|
|
||||||
|
|
||||||
int snd_rawmidi_open(snd_rawmidi_t **in_rmidi, snd_rawmidi_t **out_rmidi,
|
int snd_rawmidi_open(snd_rawmidi_t **in_rmidi, snd_rawmidi_t **out_rmidi,
|
||||||
const char *name, int mode);
|
const char *name, int mode);
|
||||||
int snd_rawmidi_open_lconf(snd_rawmidi_t **in_rmidi, snd_rawmidi_t **out_rmidi,
|
int snd_rawmidi_open_lconf(snd_rawmidi_t **in_rmidi, snd_rawmidi_t **out_rmidi,
|
||||||
|
|
@ -184,6 +164,8 @@ int snd_rawmidi_drain(snd_rawmidi_t *rmidi);
|
||||||
int snd_rawmidi_drop(snd_rawmidi_t *rmidi);
|
int snd_rawmidi_drop(snd_rawmidi_t *rmidi);
|
||||||
ssize_t snd_rawmidi_write(snd_rawmidi_t *rmidi, const void *buffer, size_t size);
|
ssize_t snd_rawmidi_write(snd_rawmidi_t *rmidi, const void *buffer, size_t size);
|
||||||
ssize_t snd_rawmidi_read(snd_rawmidi_t *rmidi, void *buffer, size_t size);
|
ssize_t snd_rawmidi_read(snd_rawmidi_t *rmidi, void *buffer, size_t size);
|
||||||
|
ssize_t snd_rawmidi_decode_frame0(snd_rawmidi_t *rmidi, void *buffer, size_t size,
|
||||||
|
struct timespec *tstamp, void *data, size_t *data_size);
|
||||||
const char *snd_rawmidi_name(snd_rawmidi_t *rmidi);
|
const char *snd_rawmidi_name(snd_rawmidi_t *rmidi);
|
||||||
snd_rawmidi_type_t snd_rawmidi_type(snd_rawmidi_t *rmidi);
|
snd_rawmidi_type_t snd_rawmidi_type(snd_rawmidi_t *rmidi);
|
||||||
snd_rawmidi_stream_t snd_rawmidi_stream(snd_rawmidi_t *rawmidi);
|
snd_rawmidi_stream_t snd_rawmidi_stream(snd_rawmidi_t *rawmidi);
|
||||||
|
|
|
||||||
|
|
@ -1075,6 +1075,41 @@ ssize_t snd_rawmidi_read(snd_rawmidi_t *rawmidi, void *buffer, size_t size)
|
||||||
{
|
{
|
||||||
assert(rawmidi);
|
assert(rawmidi);
|
||||||
assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
|
assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
|
||||||
|
if ((rawmidi->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK) == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
|
||||||
|
size &= ~(sizeof(struct snd_rawmidi_framing_tstamp) - 1);
|
||||||
assert(buffer || size == 0);
|
assert(buffer || size == 0);
|
||||||
return (rawmidi->ops->read)(rawmidi, buffer, size);
|
return (rawmidi->ops->read)(rawmidi, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief decode the MIDI frame with timestamp
|
||||||
|
* \param rawmidi RawMidi handle
|
||||||
|
* \param buffer frame buffer with the frame stream
|
||||||
|
* \param size frame buffer size in bytes
|
||||||
|
* \param tstamp returned timestamp
|
||||||
|
* \param data returned pointer to the midi data
|
||||||
|
* \param data_size returned size of the midi data
|
||||||
|
* \return number of consumed bytes otherwise a negative error code
|
||||||
|
*/
|
||||||
|
ssize_t snd_rawmidi_decode_frame0(snd_rawmidi_t *rawmidi, void *buffer, size_t size,
|
||||||
|
struct timespec *tstamp, void *data, size_t *data_size)
|
||||||
|
{
|
||||||
|
struct snd_rawmidi_framing_tstamp *f;
|
||||||
|
|
||||||
|
assert(rawmidi && buffer && tstamp && data && data_size);
|
||||||
|
assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
|
||||||
|
if (size < sizeof(*data))
|
||||||
|
return 0;
|
||||||
|
if ((rawmidi->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK) != SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
|
||||||
|
return -EINVAL;
|
||||||
|
f = buffer;
|
||||||
|
if (f->frame_type != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (f->length == 0 || f->length > SNDRV_RAWMIDI_FRAMING_DATA_LENGTH)
|
||||||
|
return -EINVAL;
|
||||||
|
tstamp->tv_sec = f->tv_sec;
|
||||||
|
tstamp->tv_nsec = f->tv_nsec;
|
||||||
|
*(void **)data = f->data;
|
||||||
|
*data_size = f->length;
|
||||||
|
return sizeof(*f);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -179,27 +179,32 @@ int main(int argc,char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle_in) {
|
if (handle_in) {
|
||||||
unsigned char ch;
|
ssize_t ret, ret2;
|
||||||
snd_rawmidi_framing_tstamp_t frame;
|
unsigned char buf[1024];
|
||||||
while (!stop) {
|
while (!stop) {
|
||||||
if (clock_type != -1) {
|
ret = snd_rawmidi_read(handle_in, &buf, sizeof(buf));
|
||||||
snd_rawmidi_read(handle_in, &frame, sizeof(frame));
|
if (clock_type != -1 && ret > 0) {
|
||||||
if (verbose) {
|
unsigned char *ptr = buf;
|
||||||
int i;
|
while (ret > 0) {
|
||||||
if (frame.frame_type) {
|
struct timespec tstamp;
|
||||||
fprintf(stderr, "read unknown frame %d", frame.frame_type);
|
unsigned char *data;
|
||||||
continue;
|
size_t j, data_size;
|
||||||
|
ret2 = snd_rawmidi_decode_frame0(handle_in, ptr, ret, &tstamp, &data, &data_size);
|
||||||
|
if (ret2 <= 0) {
|
||||||
|
fprintf(stderr, "read unknown frame %zd\n", ret2);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "read [%lld:%09d]", frame.tv_sec, frame.tv_nsec);
|
ptr += ret2;
|
||||||
for (i = 0; i < frame.length; i++)
|
ret -= ret2;
|
||||||
fprintf(stderr, " %02x", frame.data[i]);
|
fprintf(stderr, "read [%lld:%09lld]", (long long)tstamp.tv_sec, (long long)tstamp.tv_nsec);
|
||||||
|
for (j = 0; j < data_size; j++)
|
||||||
|
fprintf(stderr, " %02x", data[j]);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
snd_rawmidi_read(handle_in,&ch,1);
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr,"read %02x\n",ch);
|
for (i = 0; i < ret; i++)
|
||||||
|
fprintf(stderr,"read %02x\n",buf[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue