mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
tools: add sysex play option in pw-cat
This makes it possible to upload raw midi (sysex) into the graph.
This commit is contained in:
parent
564c9b1ba5
commit
737ca4ee7b
2 changed files with 61 additions and 2 deletions
|
|
@ -59,6 +59,7 @@ if get_option('pw-cat').allowed() and sndfile_dep.found()
|
||||||
'pw-midirecord',
|
'pw-midirecord',
|
||||||
'pw-dsdplay',
|
'pw-dsdplay',
|
||||||
'pw-encplay',
|
'pw-encplay',
|
||||||
|
'pw-sysex',
|
||||||
]
|
]
|
||||||
|
|
||||||
pw_cat = executable('pw-cat',
|
pw_cat = executable('pw-cat',
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ struct data {
|
||||||
#define TYPE_DSD 2
|
#define TYPE_DSD 2
|
||||||
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
|
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
|
||||||
#define TYPE_ENCODED 3
|
#define TYPE_ENCODED 3
|
||||||
|
#define TYPE_SYSEX 4
|
||||||
#endif
|
#endif
|
||||||
int data_type;
|
int data_type;
|
||||||
bool raw;
|
bool raw;
|
||||||
|
|
@ -162,6 +163,9 @@ struct data {
|
||||||
int64_t accumulated_excess_playtime;
|
int64_t accumulated_excess_playtime;
|
||||||
} encoded;
|
} encoded;
|
||||||
#endif
|
#endif
|
||||||
|
struct {
|
||||||
|
FILE *file;
|
||||||
|
} sysex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define STR_FMTS "(ulaw|alaw|u8|s8|s16|s32|f32|f64)"
|
#define STR_FMTS "(ulaw|alaw|u8|s8|s16|s32|f32|f64)"
|
||||||
|
|
@ -942,6 +946,7 @@ static const struct option long_options[] = {
|
||||||
{ "midi", no_argument, NULL, 'm' },
|
{ "midi", no_argument, NULL, 'm' },
|
||||||
{ "dsd", no_argument, NULL, 'd' },
|
{ "dsd", no_argument, NULL, 'd' },
|
||||||
{ "encoded", no_argument, NULL, 'o' },
|
{ "encoded", no_argument, NULL, 'o' },
|
||||||
|
{ "sysex", no_argument, NULL, 's' },
|
||||||
|
|
||||||
{ "remote", required_argument, NULL, 'R' },
|
{ "remote", required_argument, NULL, 'R' },
|
||||||
|
|
||||||
|
|
@ -1020,6 +1025,7 @@ static void show_usage(const char *name, bool is_error)
|
||||||
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
|
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
|
||||||
" -o, --encoded Encoded mode\n"
|
" -o, --encoded Encoded mode\n"
|
||||||
#endif
|
#endif
|
||||||
|
" -s, --sysex SysEx mode\n"
|
||||||
"\n"), fp);
|
"\n"), fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1163,6 +1169,47 @@ static int setup_midifile(struct data *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sysex_play(struct data *d, void *dst, unsigned int n_frames, bool *null_frame)
|
||||||
|
{
|
||||||
|
struct spa_pod_builder b;
|
||||||
|
struct spa_pod_frame f;
|
||||||
|
size_t size, to_read = n_frames - 64;
|
||||||
|
uint8_t bytes[to_read];
|
||||||
|
|
||||||
|
spa_zero(b);
|
||||||
|
spa_pod_builder_init(&b, dst, n_frames);
|
||||||
|
|
||||||
|
spa_pod_builder_push_sequence(&b, &f, 0);
|
||||||
|
spa_pod_builder_control(&b, 0, SPA_CONTROL_Midi);
|
||||||
|
|
||||||
|
size = fread(bytes, 1, to_read, d->sysex.file);
|
||||||
|
|
||||||
|
spa_pod_builder_bytes(&b, bytes, size);
|
||||||
|
spa_pod_builder_pop(&b, &f);
|
||||||
|
|
||||||
|
return b.state.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setup_sysex(struct data *data)
|
||||||
|
{
|
||||||
|
if (data->mode == mode_record)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
data->sysex.file = fopen(data->filename, "r");
|
||||||
|
if (data->sysex.file == NULL) {
|
||||||
|
fprintf(stderr, "sysex: can't read file '%s': %m\n", data->filename);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->verbose)
|
||||||
|
fprintf(stderr, "sysex: opened file \"%s\"\n", data->filename);
|
||||||
|
|
||||||
|
data->fill = sysex_play;
|
||||||
|
data->stride = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct dsd_layout_info {
|
struct dsd_layout_info {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
struct spa_audio_layout_info info;
|
struct spa_audio_layout_info info;
|
||||||
|
|
@ -1672,6 +1719,9 @@ int main(int argc, char *argv[])
|
||||||
} else if (spa_streq(prog, "pw-midirecord")) {
|
} else if (spa_streq(prog, "pw-midirecord")) {
|
||||||
data.mode = mode_record;
|
data.mode = mode_record;
|
||||||
data.data_type = TYPE_MIDI;
|
data.data_type = TYPE_MIDI;
|
||||||
|
} else if (spa_streq(prog, "pw-sysex")) {
|
||||||
|
data.mode = mode_playback;
|
||||||
|
data.data_type = TYPE_SYSEX;
|
||||||
} else if (spa_streq(prog, "pw-dsdplay")) {
|
} else if (spa_streq(prog, "pw-dsdplay")) {
|
||||||
data.mode = mode_playback;
|
data.mode = mode_playback;
|
||||||
data.data_type = TYPE_DSD;
|
data.data_type = TYPE_DSD;
|
||||||
|
|
@ -1697,9 +1747,9 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
|
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
|
||||||
while ((c = getopt_long(argc, argv, "hvprmdoR:q:P:a", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "hvprmdosR:q:P:a", long_options, NULL)) != -1) {
|
||||||
#else
|
#else
|
||||||
while ((c = getopt_long(argc, argv, "hvprmdR:q:P:a", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "hvprmdsR:q:P:a", long_options, NULL)) != -1) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|
@ -1742,6 +1792,9 @@ int main(int argc, char *argv[])
|
||||||
data.data_type = TYPE_ENCODED;
|
data.data_type = TYPE_ENCODED;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case 's':
|
||||||
|
data.data_type = TYPE_SYSEX;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
data.remote_name = optarg;
|
data.remote_name = optarg;
|
||||||
|
|
@ -1831,6 +1884,7 @@ int main(int argc, char *argv[])
|
||||||
if (!data.media_type) {
|
if (!data.media_type) {
|
||||||
switch (data.data_type) {
|
switch (data.data_type) {
|
||||||
case TYPE_MIDI:
|
case TYPE_MIDI:
|
||||||
|
case TYPE_SYSEX:
|
||||||
data.media_type = DEFAULT_MIDI_MEDIA_TYPE;
|
data.media_type = DEFAULT_MIDI_MEDIA_TYPE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -1918,6 +1972,9 @@ int main(int argc, char *argv[])
|
||||||
ret = setup_encodedfile(&data);
|
ret = setup_encodedfile(&data);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case TYPE_SYSEX:
|
||||||
|
ret = setup_sysex(&data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1980,6 +2037,7 @@ int main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE_MIDI:
|
case TYPE_MIDI:
|
||||||
|
case TYPE_SYSEX:
|
||||||
params[n_params++] = spa_pod_builder_add_object(&b,
|
params[n_params++] = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
|
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
|
||||||
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
|
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue