Implemented support for VGMStream external !tags.m3u metadata playlists

CQTexperiment
Christopher Snowhill 2019-11-23 20:36:57 -08:00
parent 319eb84744
commit 86681e9726
3 changed files with 94 additions and 13 deletions

View File

@ -35,11 +35,73 @@
int sampleRate = stream->sample_rate; int sampleRate = stream->sample_rate;
int channels = stream->channels; int channels = stream->channels;
long totalFrames = get_vgmstream_play_samples( 2.0, 10.0, 10.0, stream ); long totalFrames = get_vgmstream_play_samples( 2.0, 10.0, 10.0, stream );
long framesFade = stream->loop_flag ? sampleRate * 10 : 0;
long framesLength = totalFrames - framesFade;
int bitrate = get_vgmstream_average_bitrate(stream); int bitrate = get_vgmstream_average_bitrate(stream);
NSURL *folder = [url URLByDeletingLastPathComponent];
NSURL *tagurl = [folder URLByAppendingPathComponent:@"!tags.m3u" isDirectory:NO];
NSString *filename = [url lastPathComponent];
NSString *album = @"";
NSString *artist = @"";
NSNumber *year = [NSNumber numberWithInt:0];
NSNumber *track = [NSNumber numberWithInt:0];
NSString *title = @"";
NSNumber *rgTrackGain = [NSNumber numberWithInt:0];
NSNumber *rgTrackPeak = [NSNumber numberWithInt:0];
NSNumber *rgAlbumGain = [NSNumber numberWithInt:0];
NSNumber *rgAlbumPeak = [NSNumber numberWithInt:0];
STREAMFILE *tagFile = cogsf_create_from_url(tagurl);
if (tagFile) {
VGMSTREAM_TAGS *tags;
const char *tag_key, *tag_val;
tags = vgmstream_tags_init(&tag_key, &tag_val);
vgmstream_tags_reset(tags, [filename UTF8String]);
while (vgmstream_tags_next_tag(tags, tagFile)) {
NSString *value = [NSString stringWithUTF8String:tag_val];
if (!strncasecmp(tag_key, "REPLAYGAIN_", strlen("REPLAYGAIN_"))) {
if (!strncasecmp(tag_key+strlen("REPLAYGAIN_"), "TRACK_", strlen("TRACK_"))) {
if (!strcasecmp(tag_key+strlen("REPLAYGAIN_TRACK_"), "GAIN")) {
rgTrackGain = [NSNumber numberWithFloat:[value floatValue]];
}
else if (!strcasecmp(tag_key+strlen("REPLAYGAIN_TRACK_"), "PEAK")) {
rgTrackPeak = [NSNumber numberWithFloat:[value floatValue]];
}
}
else if (!strncasecmp(tag_key+strlen("REPLAYGAIN_"), "ALBUM_", strlen("ALBUM_"))) {
if (!strcasecmp(tag_key+strlen("REPLAYGAIN_ALBUM_"), "GAIN")) {
rgAlbumGain = [NSNumber numberWithFloat:[value floatValue]];
}
else if (!strcasecmp(tag_key+strlen("REPLAYGAIN_ALBUM_"), "PEAK")) {
rgAlbumPeak = [NSNumber numberWithFloat:[value floatValue]];
}
}
}
else if (!strcasecmp(tag_key, "ALBUM")) {
album = value;
}
else if (!strcasecmp(tag_key, "ARTIST")) {
artist = value;
}
else if (!strcasecmp(tag_key, "DATE")) {
year = [NSNumber numberWithInt:[value intValue]];
}
else if (!strcasecmp(tag_key, "TRACK") ||
!strcasecmp(tag_key, "TRACKNUMBER")) {
track = [NSNumber numberWithInt:[value intValue]];
}
else if (!strcasecmp(tag_key, "TITLE")) {
title = value;
}
}
vgmstream_tags_close(tags);
close_streamfile(tagFile);
}
NSDictionary * properties = NSDictionary * properties =
[NSDictionary dictionaryWithObjectsAndKeys: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:bitrate / 1000], @"bitrate", [NSNumber numberWithInt:bitrate / 1000], @"bitrate",
@ -52,20 +114,32 @@
@"host", @"endian", @"host", @"endian",
nil]; nil];
NSString * title; if ( [title isEqualToString:@""] ) {
if ( stream->num_streams > 1 ) { if ( stream->num_streams > 1 ) {
title = [NSString stringWithFormat:@"%@ - %s", [[url URLByDeletingPathExtension] lastPathComponent], stream->stream_name]; title = [NSString stringWithFormat:@"%@ - %s", [[url URLByDeletingPathExtension] lastPathComponent], stream->stream_name];
} else { } else {
title = [[url URLByDeletingPathExtension] lastPathComponent]; title = [[url URLByDeletingPathExtension] lastPathComponent];
} }
}
NSDictionary * metadata = if ( [track isEqualToNumber:[NSNumber numberWithInt:0]] )
[NSDictionary dictionaryWithObjectsAndKeys: track = [NSNumber numberWithInt:track_num];
NSMutableDictionary * mutableMetadata =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
title, @"title", title, @"title",
[NSNumber numberWithInt:track_num], @"track", track, @"track",
nil]; nil];
if ( ![album isEqualToString:@""] )
[mutableMetadata setValue:album forKey:@"album"];
if ( ![artist isEqualToString:@""] )
[mutableMetadata setValue:artist forKey:@"artist"];
if ( ![year isEqualToNumber:[NSNumber numberWithInt:0]] )
[mutableMetadata setValue:year forKey:@"year"];
NSDictionary * metadata = mutableMetadata;
NSDictionary * package = NSDictionary * package =
[NSDictionary dictionaryWithObjectsAndKeys: [NSDictionary dictionaryWithObjectsAndKeys:
properties, @"properties", properties, @"properties",

View File

@ -7,6 +7,7 @@
// //
#import <libvgmstream/vgmstream.h> #import <libvgmstream/vgmstream.h>
#import <libvgmstream/plugins.h>
typedef struct _COGSTREAMFILE { typedef struct _COGSTREAMFILE {
STREAMFILE sf; STREAMFILE sf;
@ -15,4 +16,6 @@ typedef struct _COGSTREAMFILE {
char name[PATH_LIMIT]; char name[PATH_LIMIT];
} COGSTREAMFILE; } COGSTREAMFILE;
STREAMFILE *cogsf_create_from_url(NSURL * url);
VGMSTREAM *init_vgmstream_from_cogfile(const char *path, int subsong); VGMSTREAM *init_vgmstream_from_cogfile(const char *path, int subsong);

View File

@ -81,10 +81,14 @@ static STREAMFILE *cogsf_create(id file, const char *path) {
} }
STREAMFILE *cogsf_create_from_path(const char *path) { STREAMFILE *cogsf_create_from_path(const char *path) {
id<CogSource> source;
NSString * urlString = [NSString stringWithUTF8String:path]; NSString * urlString = [NSString stringWithUTF8String:path];
NSURL * url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSURL * url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
return cogsf_create_from_url(url);
}
STREAMFILE *cogsf_create_from_url(NSURL * url) {
id<CogSource> source;
id audioSourceClass = NSClassFromString(@"AudioSource"); id audioSourceClass = NSClassFromString(@"AudioSource");
source = [audioSourceClass audioSourceForURL:url]; source = [audioSourceClass audioSourceForURL:url];
@ -94,7 +98,7 @@ STREAMFILE *cogsf_create_from_path(const char *path) {
if (![source seekable]) if (![source seekable])
return 0; return 0;
return cogsf_create(source, path); return cogsf_create(source, [[[url absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] UTF8String]);
} }
VGMSTREAM *init_vgmstream_from_cogfile(const char *path, int subsong) { VGMSTREAM *init_vgmstream_from_cogfile(const char *path, int subsong) {