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:
Takashi Iwai 2024-07-03 15:00:20 +02:00
parent 568b2ac1db
commit 24c7f42733
6 changed files with 74 additions and 3 deletions

View file

@ -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
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
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;
}
/**
* \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
* \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;
}
/**
* \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
* \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)
{
assert(seq && tempo);
if (!seq->has_queue_tempo_base &&
tempo->tempo_base && tempo->tempo_base != 1000)
return -EINVAL;
tempo->queue = q;
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;
}
/*----------------------------------------------------------------*/