mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-01 22:58:49 -04:00
seq: Add API functions to set different tempo base values
MIDI2 Set Tempo message uses 10ns-based values, and we need to update the API to change the base time unit. This patch adds a few new API functions: - snd_seq_has_queue_tempo_base() returns 1 if the client supports a new tempo-base value; if 0, it's an old system and application has to use the tempo in the fixed 1us unit - the tempo base can be changed with snd_seq_queue_tempo_set_tempo_base(), provided in nsec unit; the value has to be either 10 or 1000 (or 0 as default, equivalent with 1000) The protocol version is checked and fallback to the fixed 1us base for the old clients. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
568b2ac1db
commit
24c7f42733
6 changed files with 74 additions and 3 deletions
|
|
@ -506,13 +506,16 @@ unsigned int snd_seq_queue_tempo_get_tempo(const snd_seq_queue_tempo_t *info);
|
||||||
int snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t *info);
|
int snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t *info);
|
||||||
unsigned int snd_seq_queue_tempo_get_skew(const snd_seq_queue_tempo_t *info);
|
unsigned int snd_seq_queue_tempo_get_skew(const snd_seq_queue_tempo_t *info);
|
||||||
unsigned int snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t *info);
|
unsigned int snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t *info);
|
||||||
|
unsigned int snd_seq_queue_tempo_get_tempo_base(const snd_seq_queue_tempo_t *info);
|
||||||
void snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t *info, unsigned int tempo);
|
void snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t *info, unsigned int tempo);
|
||||||
void snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t *info, int ppq);
|
void snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t *info, int ppq);
|
||||||
void snd_seq_queue_tempo_set_skew(snd_seq_queue_tempo_t *info, unsigned int skew);
|
void snd_seq_queue_tempo_set_skew(snd_seq_queue_tempo_t *info, unsigned int skew);
|
||||||
void snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t *info, unsigned int base);
|
void snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t *info, unsigned int base);
|
||||||
|
void snd_seq_queue_tempo_set_tempo_base(snd_seq_queue_tempo_t *info, unsigned int tempo_base);
|
||||||
|
|
||||||
int snd_seq_get_queue_tempo(snd_seq_t *handle, int q, snd_seq_queue_tempo_t *tempo);
|
int snd_seq_get_queue_tempo(snd_seq_t *handle, int q, snd_seq_queue_tempo_t *tempo);
|
||||||
int snd_seq_set_queue_tempo(snd_seq_t *handle, int q, snd_seq_queue_tempo_t *tempo);
|
int snd_seq_set_queue_tempo(snd_seq_t *handle, int q, snd_seq_queue_tempo_t *tempo);
|
||||||
|
int snd_seq_has_queue_tempo_base(snd_seq_t *handle);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
#include <sound/asound.h>
|
#include <sound/asound.h>
|
||||||
|
|
||||||
/** version of the sequencer */
|
/** version of the sequencer */
|
||||||
#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 3)
|
#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 4)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* definition of sequencer event types
|
* definition of sequencer event types
|
||||||
|
|
@ -539,11 +539,12 @@ struct snd_seq_queue_status {
|
||||||
/* queue tempo */
|
/* queue tempo */
|
||||||
struct snd_seq_queue_tempo {
|
struct snd_seq_queue_tempo {
|
||||||
int queue; /* sequencer queue */
|
int queue; /* sequencer queue */
|
||||||
unsigned int tempo; /* current tempo, us/tick */
|
unsigned int tempo; /* current tempo, us/tick (or different time-base below) */
|
||||||
int ppq; /* time resolution, ticks/quarter */
|
int ppq; /* time resolution, ticks/quarter */
|
||||||
unsigned int skew_value; /* queue skew */
|
unsigned int skew_value; /* queue skew */
|
||||||
unsigned int skew_base; /* queue skew base */
|
unsigned int skew_base; /* queue skew base */
|
||||||
char reserved[24]; /* for the future */
|
unsigned short tempo_base; /* tempo base in nsec unit; either 10 or 1000 */
|
||||||
|
char reserved[22]; /* for the future */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,9 @@ ALSA_1.2.13 {
|
||||||
#ifdef HAVE_SEQ_SYMS
|
#ifdef HAVE_SEQ_SYMS
|
||||||
@SYMBOL_PREFIX@snd_seq_create_ump_endpoint;
|
@SYMBOL_PREFIX@snd_seq_create_ump_endpoint;
|
||||||
@SYMBOL_PREFIX@snd_seq_create_ump_block;
|
@SYMBOL_PREFIX@snd_seq_create_ump_block;
|
||||||
|
@SYMBOL_PREFIX@snd_seq_queue_tempo_get_tempo_base;
|
||||||
|
@SYMBOL_PREFIX@snd_seq_queue_tempo_set_tempo_base;
|
||||||
|
@SYMBOL_PREFIX@snd_seq_has_tempo_base;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_RAWMIDI_SYMS
|
#ifdef HAVE_RAWMIDI_SYMS
|
||||||
@SYMBOL_PREFIX@snd_ump_endpoint_info_clear;
|
@SYMBOL_PREFIX@snd_ump_endpoint_info_clear;
|
||||||
|
|
|
||||||
|
|
@ -490,6 +490,21 @@ the buffer is flushed by #snd_seq_drain_output() call.
|
||||||
You can schedule the event in a certain queue so that the tempo
|
You can schedule the event in a certain queue so that the tempo
|
||||||
change happens at the scheduled time, too.
|
change happens at the scheduled time, too.
|
||||||
|
|
||||||
|
The tempo is set as default in microsecond unit as defined for
|
||||||
|
Standard MIDI Format 1. But since the value in MIDI2 Set Tempo message
|
||||||
|
is based on 10-nanosecand unit, sequencer queue also allows to set up
|
||||||
|
in 10-nanosecond unit. For that, change the tempo-base value in
|
||||||
|
#snd_seq_queue_tempo_t to 10 via #snd_seq_queue_tempo_set_tempo_base()
|
||||||
|
along with the 10-nanobased tempo value. The default tempo base is 1000,
|
||||||
|
i.e. 1 microsecond.
|
||||||
|
Currently the API supports only either 0, 10 or 1000 as the tempo-base
|
||||||
|
(where 0 is treated as 1000).
|
||||||
|
|
||||||
|
The older kernel might not support the different tempo-base, and setting a
|
||||||
|
different value from 1000 would fail. The application may heck the
|
||||||
|
availability of tempo-base change via #snd_seq_has_tempo_base() function
|
||||||
|
beforehand, and re-calculate in microsecond unit as fallback.
|
||||||
|
|
||||||
\subsection seq_ev_start Starting and stopping a queue
|
\subsection seq_ev_start Starting and stopping a queue
|
||||||
|
|
||||||
To start, stop, or continue a queue, you need to send a queue-control
|
To start, stop, or continue a queue, you need to send a queue-control
|
||||||
|
|
@ -3878,6 +3893,19 @@ unsigned int snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t *info
|
||||||
return info->skew_base;
|
return info->skew_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the tempo base of a queue_status container
|
||||||
|
* \param info queue_status container
|
||||||
|
* \return tempo base time in nsec unit
|
||||||
|
*
|
||||||
|
* \sa snd_seq_get_queue_tempo()
|
||||||
|
*/
|
||||||
|
unsigned int snd_seq_queue_tempo_get_tempo_base(const snd_seq_queue_tempo_t *info)
|
||||||
|
{
|
||||||
|
assert(info);
|
||||||
|
return info->tempo_base;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set the tempo of a queue_status container
|
* \brief Set the tempo of a queue_status container
|
||||||
* \param info queue_status container
|
* \param info queue_status container
|
||||||
|
|
@ -3933,6 +3961,21 @@ void snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t *info, unsigned int
|
||||||
info->skew_base = base;
|
info->skew_base = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set the tempo base of a queue_status container
|
||||||
|
* \param info queue_status container
|
||||||
|
* \param tempo_base tempo base time in nsec unit
|
||||||
|
*
|
||||||
|
* \sa snd_seq_get_queue_tempo()
|
||||||
|
*/
|
||||||
|
void snd_seq_queue_tempo_set_tempo_base(snd_seq_queue_tempo_t *info, unsigned int tempo_base)
|
||||||
|
{
|
||||||
|
assert(info);
|
||||||
|
if (!tempo_base)
|
||||||
|
tempo_base = 1000;
|
||||||
|
info->tempo_base = tempo_base;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief obtain the current tempo of the queue
|
* \brief obtain the current tempo of the queue
|
||||||
* \param seq sequencer handle
|
* \param seq sequencer handle
|
||||||
|
|
@ -3962,10 +4005,25 @@ int snd_seq_get_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo
|
||||||
int snd_seq_set_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo)
|
int snd_seq_set_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo)
|
||||||
{
|
{
|
||||||
assert(seq && tempo);
|
assert(seq && tempo);
|
||||||
|
if (!seq->has_queue_tempo_base &&
|
||||||
|
tempo->tempo_base && tempo->tempo_base != 1000)
|
||||||
|
return -EINVAL;
|
||||||
tempo->queue = q;
|
tempo->queue = q;
|
||||||
return seq->ops->set_queue_tempo(seq, tempo);
|
return seq->ops->set_queue_tempo(seq, tempo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief inquiry the support of tempo base change
|
||||||
|
* \param seq sequencer handle
|
||||||
|
* \return 1 if the client supports the tempo base change, 0 if not
|
||||||
|
*
|
||||||
|
* \sa snd_seq_get_queue_tempo()
|
||||||
|
*/
|
||||||
|
int snd_seq_has_queue_tempo_base(snd_seq_t *seq)
|
||||||
|
{
|
||||||
|
assert(seq);
|
||||||
|
return seq->has_queue_tempo_base;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -275,12 +275,15 @@ static int snd_seq_hw_get_queue_tempo(snd_seq_t *seq, snd_seq_queue_tempo_t * te
|
||||||
/*SYSERR("SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO failed");*/
|
/*SYSERR("SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO failed");*/
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
if (!seq->has_queue_tempo_base)
|
||||||
|
tempo->tempo_base = 1000;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_seq_hw_set_queue_tempo(snd_seq_t *seq, snd_seq_queue_tempo_t * tempo)
|
static int snd_seq_hw_set_queue_tempo(snd_seq_t *seq, snd_seq_queue_tempo_t * tempo)
|
||||||
{
|
{
|
||||||
snd_seq_hw_t *hw = seq->private_data;
|
snd_seq_hw_t *hw = seq->private_data;
|
||||||
|
|
||||||
if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, tempo) < 0) {
|
if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, tempo) < 0) {
|
||||||
/*SYSERR("SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO failed");*/
|
/*SYSERR("SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO failed");*/
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
@ -587,6 +590,8 @@ int snd_seq_hw_open(snd_seq_t **handle, const char *name, int streams, int mode)
|
||||||
seq->ops = &snd_seq_hw_ops;
|
seq->ops = &snd_seq_hw_ops;
|
||||||
seq->private_data = hw;
|
seq->private_data = hw;
|
||||||
seq->packet_size = sizeof(snd_seq_event_t);
|
seq->packet_size = sizeof(snd_seq_event_t);
|
||||||
|
seq->has_queue_tempo_base = ver >= SNDRV_PROTOCOL_VERSION(1, 0, 4);
|
||||||
|
|
||||||
client = snd_seq_hw_client_id(seq);
|
client = snd_seq_hw_client_id(seq);
|
||||||
if (client < 0) {
|
if (client < 0) {
|
||||||
snd_seq_close(seq);
|
snd_seq_close(seq);
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ struct _snd_seq {
|
||||||
size_t tmpbufsize; /* size of errbuf */
|
size_t tmpbufsize; /* size of errbuf */
|
||||||
size_t packet_size; /* input packet alignment size */
|
size_t packet_size; /* input packet alignment size */
|
||||||
int midi_version; /* current protocol version */
|
int midi_version; /* current protocol version */
|
||||||
|
int has_queue_tempo_base; /* support queue tempo-base? */
|
||||||
|
|
||||||
unsigned int num_ump_groups; /* number of UMP groups */
|
unsigned int num_ump_groups; /* number of UMP groups */
|
||||||
snd_ump_endpoint_info_t *ump_ep; /* optional UMP info */
|
snd_ump_endpoint_info_t *ump_ep; /* optional UMP info */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue