Compare commits

...

5 commits

Author SHA1 Message Date
Takashi Iwai
68491dd464 aplaymidi2: Show meta data texts
Now aplaymidi2 shows the meta data texts embedded in Flex Data
messages such as copyright and lyrics.  The text output isn't
synchronized yet with the actual position, though.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
2024-07-08 18:32:18 +02:00
Takashi Iwai
330741d523 aconnect: Fix the indication of inactive ports
The inactive port should have been shown in each port line instead of
the client name line.

Fixes: 64b1d486b1 ("aconnect: Add UMP support")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2024-07-08 17:21:13 +02:00
Takashi Iwai
2ee6c170a8 arecordmidi2: Fix the tick in 1us tempo-base
The recorded tick is incorrectly converted for 1us tempo-base on the
old kernels.  Since we correct the queue tempo, we don't have to
adjust the returned tick value any longer.  The current code applies
it doubly, resulting in 100 times slower.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
2024-07-08 17:14:06 +02:00
Takashi Iwai
e609d66807 arecordmidi2: Correct the MIDI FB direction
The direction was wrongly passed to the FB setup.  It has to be
"OUTPUT" instead of "INPUT, so that other applications can write to
arecordmidi2 port.

Fixes: 2cdf5ebedb ("arecordmidi2: Add initial version")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2024-07-08 16:26:31 +02:00
Takashi Iwai
16533f81de arecordmidi2: Start queue at starting the stream
The queue should be started at the very same time of the start of the
stream itself in the interactive mode.  Otherwise it'll get bogus long
waits until the start of the clip.

Move the code to start the queue in start_bar(), so that it's always
tied with the start sequence.

Fixes: 1205dd5f6c ("arecordmidi2: Add passive mode and interactive mode")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2024-07-08 16:26:09 +02:00
3 changed files with 131 additions and 12 deletions

View file

@ -215,10 +215,6 @@ static void print_port(snd_seq_t *seq ATTRIBUTE_UNUSED,
break;
}
#endif
#ifdef HANDLE_SHOW_ALL
if (snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_INACTIVE)
printf(",INACTIVE");
#endif
#ifdef HAVE_SEQ_CLIENT_INFO_GET_CARD
card = snd_seq_client_info_get_card(cinfo);
#endif
@ -232,9 +228,14 @@ static void print_port(snd_seq_t *seq ATTRIBUTE_UNUSED,
printf(",pid=%d", pid);
printf("]\n");
}
printf(" %3d '%-16s'\n",
printf(" %3d '%-16s'",
snd_seq_port_info_get_port(pinfo),
snd_seq_port_info_get_name(pinfo));
#ifdef HANDLE_SHOW_ALL
if (snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_INACTIVE)
printf(" [INACTIVE]");
#endif
printf("\n");
}
static void print_port_and_subs(snd_seq_t *seq, snd_seq_client_info_t *cinfo,

View file

@ -288,6 +288,117 @@ static void send_ump(const uint32_t *ump, int len)
snd_seq_ump_event_output(seq, &ev);
}
struct flexdata_text_prefix {
unsigned char status_bank;
unsigned char status;
const char *prefix;
};
static struct flexdata_text_prefix text_prefix[] = {
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_PROJECT_NAME,
.prefix = "Project" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_SONG_NAME,
.prefix = "Song" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_MIDI_CLIP_NAME,
.prefix = "MIDI Clip" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_COPYRIGHT_NOTICE,
.prefix = "Copyright" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_COMPOSER_NAME,
.prefix = "Composer" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_LYRICIST_NAME,
.prefix = "Lyricist" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_ARRANGER_NAME,
.prefix = "Arranger" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_PUBLISHER_NAME,
.prefix = "Publisher" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_PRIMARY_PERFORMER,
.prefix = "Performer" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_ACCOMPANY_PERFORMAER,
.prefix = "Accompany Performer" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_RECORDING_DATE,
.prefix = "Recording Date" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_METADATA,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_RECORDING_LOCATION,
.prefix = "Recording Location" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_PERF_TEXT,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_LYRICS,
.prefix = "Lyrics" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_PERF_TEXT,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_LYRICS_LANGUAGE,
.prefix = "Lyrics Language" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_PERF_TEXT,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_RUBY,
.prefix = "Ruby" },
{ .status_bank = SND_UMP_FLEX_DATA_MSG_BANK_PERF_TEXT,
.status = SND_UMP_FLEX_DATA_MSG_STATUS_RUBY_LANGUAGE,
.prefix = "Ruby Language" },
{}
};
static void show_text(const uint32_t *ump)
{
static unsigned char textbuf[256];
static int len;
const snd_ump_msg_flex_data_t *fh =
(const snd_ump_msg_flex_data_t *)ump;
const char *prefix;
int i;
if (fh->meta.format == SND_UMP_FLEX_DATA_MSG_FORMAT_SINGLE ||
fh->meta.format == SND_UMP_FLEX_DATA_MSG_FORMAT_START)
len = 0;
for (i = 0; i < 12 && len < (int)sizeof(textbuf); i++) {
textbuf[len] = fh->meta.data[i / 4] >> ((3 - (i % 4)) * 8);
if (!textbuf[len])
break;
switch (textbuf[len]) {
case 0x0a: /* end of paragraph */
case 0x0d: /* end of line */
textbuf[len] = '\n';
break;
}
len++;
}
if (fh->meta.format != SND_UMP_FLEX_DATA_MSG_FORMAT_SINGLE &&
fh->meta.format != SND_UMP_FLEX_DATA_MSG_FORMAT_END)
return;
if (len >= (int)sizeof(textbuf))
len = sizeof(textbuf) - 1;
textbuf[len] = 0;
prefix = NULL;
for (i = 0; text_prefix[i].status_bank; i++) {
if (text_prefix[i].status_bank == fh->meta.status_bank &&
text_prefix[i].status == fh->meta.status) {
prefix = text_prefix[i].prefix;
break;
}
}
if (prefix) {
printf("%s: %s\n", prefix, textbuf);
} else {
printf("(%d:%d): %s\n", fh->meta.status_bank, fh->meta.status,
textbuf);
}
len = 0;
}
/* play the given MIDI Clip File content */
static void play_midi(FILE *file)
{
@ -318,6 +429,12 @@ static void play_midi(FILE *file)
set_tempo(fh->set_tempo.tempo);
continue;
}
if (fh->meta.status_bank == SND_UMP_FLEX_DATA_MSG_BANK_METADATA ||
fh->meta.status_bank == SND_UMP_FLEX_DATA_MSG_BANK_PERF_TEXT) {
show_text(ump);
continue;
}
} else if (h->type == SND_UMP_MSG_TYPE_STREAM) {
const snd_ump_msg_stream_t *sh =
(const snd_ump_msg_stream_t *)ump;

View file

@ -124,7 +124,7 @@ static void create_ump_client(void)
sprintf(blkname, "Group %d", i + 1);
snd_ump_block_info_set_name(blk, blkname);
snd_ump_block_info_set_direction(blk, SND_UMP_DIR_INPUT);
snd_ump_block_info_set_direction(blk, SND_UMP_DIR_OUTPUT);
snd_ump_block_info_set_first_group(blk, i);
snd_ump_block_info_set_num_groups(blk, 1);
snd_ump_block_info_set_ui_hint(blk, SND_UMP_BLOCK_UI_HINT_RECEIVER);
@ -321,8 +321,6 @@ static void delta_time(FILE *file, const snd_seq_ump_event_t *ev)
if (diff <= 0)
return;
if (tempo_base == 1000)
diff *= 100;
write_dcs(file, diff);
last_tick = ev->time.tick;
}
@ -355,6 +353,13 @@ static void write_file_header(FILE *file)
/* write start bar */
static void start_bar(FILE *file)
{
int err;
/* start the queue */
err = snd_seq_start_queue(seq, queue, NULL);
check_snd("start queue", err);
snd_seq_drain_output(seq);
write_start_clip(file);
write_tempo(file);
write_time_sig(file);
@ -489,10 +494,6 @@ int main(int argc, char *argv[])
start = 1;
}
err = snd_seq_start_queue(seq, queue, NULL);
check_snd("start queue", err);
snd_seq_drain_output(seq);
err = snd_seq_nonblock(seq, 1);
check_snd("set nonblock mode", err);