Implemented support for VGMStream external !tags.m3u metadata playlists
parent
319eb84744
commit
86681e9726
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue