mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-30 17:24:31 +01:00
vgmstream123: extra subsong options and info
This commit is contained in:
parent
a074e9f2d0
commit
bc68cccc63
@ -69,9 +69,10 @@
|
|||||||
#define LITTLE_ENDIAN_OUTPUT 1 /* untested in BE */
|
#define LITTLE_ENDIAN_OUTPUT 1 /* untested in BE */
|
||||||
|
|
||||||
|
|
||||||
#define DEFAULT_PARAMS { 0, -1, 2.0, 10.0, 0.0, 0, 0, 0, 0 }
|
#define DEFAULT_PARAMS { 0, 0, -1, 2.0, 10.0, 0.0, 0, 0, 0, 0 }
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int stream_index;
|
int subsong_index;
|
||||||
|
int subsong_end;
|
||||||
|
|
||||||
double min_time;
|
double min_time;
|
||||||
double loop_count;
|
double loop_count;
|
||||||
@ -240,7 +241,7 @@ static int play_vgmstream(const char* filename, song_settings_t* cfg) {
|
|||||||
|
|
||||||
vgmstream_set_log_stdout(VGM_LOG_LEVEL_ALL);
|
vgmstream_set_log_stdout(VGM_LOG_LEVEL_ALL);
|
||||||
|
|
||||||
sf->stream_index = cfg->stream_index;
|
sf->stream_index = cfg->subsong_index;
|
||||||
vgmstream = init_vgmstream_from_STREAMFILE(sf);
|
vgmstream = init_vgmstream_from_STREAMFILE(sf);
|
||||||
close_streamfile(sf);
|
close_streamfile(sf);
|
||||||
|
|
||||||
@ -249,15 +250,11 @@ static int play_vgmstream(const char* filename, song_settings_t* cfg) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Playing stream: %s\n", filename);
|
/* force load total subsongs if signalled */
|
||||||
|
if (cfg->subsong_end == -1) {
|
||||||
/* Print metadata in verbose mode
|
cfg->subsong_end = vgmstream->num_streams;
|
||||||
*/
|
close_vgmstream(vgmstream);
|
||||||
if (verbose) {
|
return 0;
|
||||||
char description[4096] = { '\0' };
|
|
||||||
describe_vgmstream(vgmstream, description, sizeof(description));
|
|
||||||
puts(description);
|
|
||||||
putchar('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the audio device hasn't been opened yet, then describe it
|
/* If the audio device hasn't been opened yet, then describe it
|
||||||
@ -273,6 +270,27 @@ static int play_vgmstream(const char* filename, song_settings_t* cfg) {
|
|||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vgmstream->num_streams > 0) {
|
||||||
|
int subsong = vgmstream->stream_index;
|
||||||
|
if (!subsong)
|
||||||
|
subsong = 1;
|
||||||
|
printf("Playing stream: %s [%i/%i]\n", filename, subsong, vgmstream->num_streams);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Playing stream: %s\n", filename);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print metadata in verbose mode
|
||||||
|
*/
|
||||||
|
if (verbose) {
|
||||||
|
char description[4096] = { '\0' };
|
||||||
|
describe_vgmstream(vgmstream, description, sizeof(description));
|
||||||
|
puts(description);
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Stupid hack to hang onto a few low-numbered file descriptors
|
/* Stupid hack to hang onto a few low-numbered file descriptors
|
||||||
* so that play_compressed_file() doesn't break, due to POSIX
|
* so that play_compressed_file() doesn't break, due to POSIX
|
||||||
* wackiness like https://bugs.debian.org/590920
|
* wackiness like https://bugs.debian.org/590920
|
||||||
@ -494,7 +512,7 @@ static int play_playlist(const char *filename, song_settings_t *default_par) {
|
|||||||
else if (PARAM_MATCHES("LOOPCOUNT"))
|
else if (PARAM_MATCHES("LOOPCOUNT"))
|
||||||
par.loop_count = atof(arg);
|
par.loop_count = atof(arg);
|
||||||
else if (PARAM_MATCHES("STREAMINDEX"))
|
else if (PARAM_MATCHES("STREAMINDEX"))
|
||||||
par.stream_index = atoi(arg);
|
par.subsong_index = atoi(arg);
|
||||||
|
|
||||||
param = strtok(NULL, ",");
|
param = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
@ -600,23 +618,49 @@ fail:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int play_file(const char *filename, song_settings_t *par) {
|
|
||||||
size_t len = strlen(filename);
|
|
||||||
|
|
||||||
#define ENDS_IN(EXT) !strcasecmp(EXT, filename + len - sizeof(EXT) + 1)
|
#define ENDS_IN(EXT) !strcasecmp(EXT, filename + len - sizeof(EXT) + 1)
|
||||||
|
|
||||||
|
static int play_standard(const char* filename, song_settings_t* cfg) {
|
||||||
|
int ret, subsong;
|
||||||
|
|
||||||
|
/* standard */
|
||||||
|
if (cfg->subsong_end == 0) {
|
||||||
|
return play_vgmstream(filename, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* N subsongs */
|
||||||
|
|
||||||
|
/* first call should force load max subsongs */
|
||||||
|
if (cfg->subsong_end == -1) {
|
||||||
|
ret = play_vgmstream(filename, cfg);
|
||||||
|
if (ret) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (subsong = cfg->subsong_index; subsong < cfg->subsong_end + 1; subsong++) {
|
||||||
|
cfg->subsong_index = subsong;
|
||||||
|
|
||||||
|
ret = play_vgmstream(filename, cfg);
|
||||||
|
if (ret) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int play_file(const char* filename, song_settings_t* cfg) {
|
||||||
|
size_t len = strlen(filename);
|
||||||
|
|
||||||
if (ENDS_IN(".m3u") || ENDS_IN(".m3u8"))
|
if (ENDS_IN(".m3u") || ENDS_IN(".m3u8"))
|
||||||
return play_playlist(filename, par);
|
return play_playlist(filename, cfg);
|
||||||
else if (ENDS_IN(".bz2"))
|
else if (ENDS_IN(".bz2"))
|
||||||
return play_compressed_file(filename, par, "bzip2 -cd");
|
return play_compressed_file(filename, cfg, "bzip2 -cd");
|
||||||
else if (ENDS_IN(".gz"))
|
else if (ENDS_IN(".gz"))
|
||||||
return play_compressed_file(filename, par, "gzip -cd");
|
return play_compressed_file(filename, cfg, "gzip -cd");
|
||||||
else if (ENDS_IN(".lzma"))
|
else if (ENDS_IN(".lzma"))
|
||||||
return play_compressed_file(filename, par, "lzma -cd");
|
return play_compressed_file(filename, cfg, "lzma -cd");
|
||||||
else if (ENDS_IN(".xz"))
|
else if (ENDS_IN(".xz"))
|
||||||
return play_compressed_file(filename, par, "xz -cd");
|
return play_compressed_file(filename, cfg, "xz -cd");
|
||||||
else
|
else
|
||||||
return play_vgmstream(filename, par);
|
return play_standard(filename, cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_driver_option(const char *key_value) {
|
static void add_driver_option(const char *key_value) {
|
||||||
@ -674,8 +718,9 @@ static void usage(const char* progname, int is_help) {
|
|||||||
" -@ LSTFILE Read playlist from LSTFILE\n"
|
" -@ LSTFILE Read playlist from LSTFILE\n"
|
||||||
"\n"
|
"\n"
|
||||||
" -o OUTFILE Set output filename for a file driver specified with -D\n"
|
" -o OUTFILE Set output filename for a file driver specified with -D\n"
|
||||||
" -m Display stream metadata and playback progress\n"
|
" -m Print metadata and playback progress\n"
|
||||||
" -s N Play subsong index N\n"
|
" -s N Play subsong N, if the format supports multiple subsongs\n"
|
||||||
|
" -S N Play up to end subsong N (set 0 for 'all')\n"
|
||||||
" -h Print this help\n"
|
" -h Print this help\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Looping options:\n"
|
"Looping options:\n"
|
||||||
@ -726,7 +771,7 @@ again_opts:
|
|||||||
cfg = default_par;
|
cfg = default_par;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "-D:f:l:M:s:B:d:o:P:@:hrmieEc")) != -1) {
|
while ((opt = getopt(argc, argv, "-D:f:l:M:s:B:d:o:P:@:hrmieEcS:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 1:
|
case 1:
|
||||||
/* glibc getopt extension
|
/* glibc getopt extension
|
||||||
@ -758,7 +803,14 @@ again_opts:
|
|||||||
cfg.loop_count = -1.0;
|
cfg.loop_count = -1.0;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
cfg.stream_index = atoi(optarg);
|
cfg.subsong_index = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
cfg.subsong_end = atoi(optarg);
|
||||||
|
if (!cfg.subsong_end)
|
||||||
|
cfg.subsong_end = -1; /* signal up to end (otherwise 0 = not set) */
|
||||||
|
if (!cfg.subsong_index)
|
||||||
|
cfg.subsong_index = 1;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
cfg.ignore_loop = 1;
|
cfg.ignore_loop = 1;
|
||||||
|
11
doc/USAGE.md
11
doc/USAGE.md
@ -121,10 +121,13 @@ document in vgmstream's source code (can be done with CMake or autotools).
|
|||||||
Usage: `vgmstream123 [options] INFILE ...`
|
Usage: `vgmstream123 [options] INFILE ...`
|
||||||
|
|
||||||
The program is meant to be a simple stand-alone player, supporting playback of
|
The program is meant to be a simple stand-alone player, supporting playback of
|
||||||
vgmstream files through libao. On Linux, files compressed with gzip/bzip2/xz also
|
vgmstream files through libao. Most options should be similar to CLI's
|
||||||
work, as identified by a `.gz/.bz2/.xz` extension. The file will be decompressed
|
(`-m`, `-i`, `-s N` and so on, though not fully equivalent), use `-h` for full info.
|
||||||
to a temp dir using the respective utility program (which must be installed
|
|
||||||
and accessible) and then loaded.
|
On Linux, files compressed with gzip/bzip2/xz also work, as identified by a
|
||||||
|
`.gz/.bz2/.xz` extension. The file will be decompressed to a temp dir using the
|
||||||
|
respective utility program (which must be installed and accessible) and then
|
||||||
|
loaded.
|
||||||
|
|
||||||
It also supports playlists, and will recognize a special extended-M3U tag
|
It also supports playlists, and will recognize a special extended-M3U tag
|
||||||
specific to vgmstream of the following form:
|
specific to vgmstream of the following form:
|
||||||
|
Loading…
Reference in New Issue
Block a user