Significantly reduce memory usage all around
Added a string dictionary for deduplication of metadata, and actually initialize both it and the art dictionary on startup, so they actually work like they should. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
c242d53200
commit
3de43b55a7
3 changed files with 91 additions and 40 deletions
|
@ -460,6 +460,7 @@
|
||||||
[self setMetadataLoaded:YES];
|
[self setMetadataLoaded:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now we duplicate the object to a new handle, but merely reference the same data
|
||||||
- (id)copyWithZone:(NSZone *)zone {
|
- (id)copyWithZone:(NSZone *)zone {
|
||||||
PlaylistEntry *pe = [[[self class] allocWithZone:zone] init];
|
PlaylistEntry *pe = [[[self class] allocWithZone:zone] init];
|
||||||
|
|
||||||
|
@ -479,22 +480,22 @@
|
||||||
pe->queuePosition = queuePosition;
|
pe->queuePosition = queuePosition;
|
||||||
|
|
||||||
pe->error = error;
|
pe->error = error;
|
||||||
pe->errorMessage = [errorMessage copyWithZone:zone];
|
pe->errorMessage = errorMessage;
|
||||||
|
|
||||||
pe->URL = [URL copyWithZone:zone];
|
pe->URL = URL;
|
||||||
|
|
||||||
pe->artist = [artist copyWithZone:zone];
|
pe->artist = artist;
|
||||||
pe->albumartist = [albumartist copyWithZone:zone];
|
pe->albumartist = albumartist;
|
||||||
pe->album = [album copyWithZone:zone];
|
pe->album = album;
|
||||||
pe->title = [title copyWithZone:zone];
|
pe->title = title;
|
||||||
pe->genre = [genre copyWithZone:zone];
|
pe->genre = genre;
|
||||||
pe->year = [year copyWithZone:zone];
|
pe->year = year;
|
||||||
pe->track = [track copyWithZone:zone];
|
pe->track = track;
|
||||||
pe->disc = [disc copyWithZone:zone];
|
pe->disc = disc;
|
||||||
|
|
||||||
pe->cuesheet = [cuesheet copyWithZone:zone];
|
pe->cuesheet = cuesheet;
|
||||||
|
|
||||||
pe->albumArtInternal = albumArtInternal; // Only allocated item not duplicated
|
pe->albumArtInternal = albumArtInternal;
|
||||||
|
|
||||||
pe->replayGainAlbumGain = replayGainAlbumGain;
|
pe->replayGainAlbumGain = replayGainAlbumGain;
|
||||||
pe->replayGainAlbumPeak = replayGainAlbumPeak;
|
pe->replayGainAlbumPeak = replayGainAlbumPeak;
|
||||||
|
@ -513,11 +514,11 @@
|
||||||
pe->Unsigned = Unsigned;
|
pe->Unsigned = Unsigned;
|
||||||
pe->sampleRate = sampleRate;
|
pe->sampleRate = sampleRate;
|
||||||
|
|
||||||
pe->codec = [codec copyWithZone:zone];
|
pe->codec = codec;
|
||||||
|
|
||||||
pe->endian = [endian copyWithZone:zone];
|
pe->endian = endian;
|
||||||
|
|
||||||
pe->encoding = [encoding copyWithZone:zone];
|
pe->encoding = encoding;
|
||||||
|
|
||||||
pe->seekable = seekable;
|
pe->seekable = seekable;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
@private
|
@private
|
||||||
NSMutableArray *databaseMirror;
|
NSMutableArray *databaseMirror;
|
||||||
NSMutableDictionary *artTable;
|
NSMutableDictionary *artTable;
|
||||||
|
NSMutableDictionary *stringTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property(nonatomic, readwrite) NSString *databasePath;
|
@property(nonatomic, readwrite) NSString *databasePath;
|
||||||
|
|
|
@ -511,7 +511,7 @@ NSURL *urlForPath(NSString *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@interface SQLiteStore (Private)
|
@interface SQLiteStore (Private)
|
||||||
- (int64_t)addString:(NSString *)string;
|
- (int64_t)addString:(NSString **)string;
|
||||||
- (NSString *)getString:(int64_t)stringId;
|
- (NSString *)getString:(int64_t)stringId;
|
||||||
- (void)removeString:(int64_t)stringId;
|
- (void)removeString:(int64_t)stringId;
|
||||||
- (int64_t)addArt:(NSData *)art;
|
- (int64_t)addArt:(NSData *)art;
|
||||||
|
@ -668,6 +668,8 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
size_t count = [self playlistGetCount];
|
size_t count = [self playlistGetCount];
|
||||||
|
|
||||||
databaseMirror = [[NSMutableArray alloc] init];
|
databaseMirror = [[NSMutableArray alloc] init];
|
||||||
|
artTable = [[NSMutableDictionary alloc] init];
|
||||||
|
stringTable = [[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
for(size_t i = 0; i < count; ++i) {
|
for(size_t i = 0; i < count; ++i) {
|
||||||
PlaylistEntry *pe = [self playlistGetItem:i];
|
PlaylistEntry *pe = [self playlistGetItem:i];
|
||||||
|
@ -690,12 +692,12 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int64_t)addString:(NSString *)string {
|
- (int64_t)addString:(NSString **)string {
|
||||||
if(!string || [string length] == 0) {
|
if(!*string || [*string length] == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = [string UTF8String];
|
const char *str = [*string UTF8String];
|
||||||
uint64_t len = strlen(str); // SQLite expects number of bytes, not characters
|
uint64_t len = strlen(str); // SQLite expects number of bytes, not characters
|
||||||
|
|
||||||
sqlite3_stmt *st = stmt[stmt_select_string];
|
sqlite3_stmt *st = stmt[stmt_select_string];
|
||||||
|
@ -732,6 +734,8 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
|
|
||||||
ret = sqlite3_last_insert_rowid(g_database);
|
ret = sqlite3_last_insert_rowid(g_database);
|
||||||
refcount = 1;
|
refcount = 1;
|
||||||
|
|
||||||
|
[stringTable setObject:*string forKey:[[NSNumber numberWithInteger:ret] stringValue]];
|
||||||
} else {
|
} else {
|
||||||
st = stmt[stmt_bump_string];
|
st = stmt[stmt_bump_string];
|
||||||
|
|
||||||
|
@ -741,6 +745,8 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
sqlite3_reset(st)) {
|
sqlite3_reset(st)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*string = [stringTable objectForKey:[[NSNumber numberWithInteger:ret] stringValue]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -750,6 +756,9 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
if(stringId < 0)
|
if(stringId < 0)
|
||||||
return @"";
|
return @"";
|
||||||
|
|
||||||
|
NSString *ret = [stringTable objectForKey:[[NSNumber numberWithInteger:stringId] stringValue]];
|
||||||
|
if(ret) return ret;
|
||||||
|
|
||||||
sqlite3_stmt *st = stmt[stmt_select_string_value];
|
sqlite3_stmt *st = stmt[stmt_select_string_value];
|
||||||
|
|
||||||
if(sqlite3_reset(st) ||
|
if(sqlite3_reset(st) ||
|
||||||
|
@ -764,7 +773,7 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
return @"";
|
return @"";
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *ret = @"";
|
ret = @"";
|
||||||
|
|
||||||
if(rc == SQLITE_ROW) {
|
if(rc == SQLITE_ROW) {
|
||||||
const unsigned char *str = sqlite3_column_text(st, select_string_value_out_value);
|
const unsigned char *str = sqlite3_column_text(st, select_string_value_out_value);
|
||||||
|
@ -817,6 +826,8 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
sqlite3_reset(st)) {
|
sqlite3_reset(st)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[stringTable removeObjectForKey:[[NSNumber numberWithInteger:stringId] stringValue]];
|
||||||
} else {
|
} else {
|
||||||
st = stmt[stmt_pop_string];
|
st = stmt[stmt_pop_string];
|
||||||
|
|
||||||
|
@ -978,7 +989,7 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
NSURL *url = [track URL];
|
NSURL *url = [track URL];
|
||||||
NSString *urlString = [url absoluteString];
|
NSString *urlString = [url absoluteString];
|
||||||
|
|
||||||
int64_t urlId = [self addString:urlString];
|
int64_t urlId = [self addString:&urlString];
|
||||||
|
|
||||||
sqlite3_stmt *st = stmt[stmt_select_track];
|
sqlite3_stmt *st = stmt[stmt_select_track];
|
||||||
|
|
||||||
|
@ -1005,14 +1016,31 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
sqlite3_reset(stmt[stmt_select_string]);
|
sqlite3_reset(stmt[stmt_select_string]);
|
||||||
|
|
||||||
if(rc != SQLITE_ROW) {
|
if(rc != SQLITE_ROW) {
|
||||||
int64_t albumId = [self addString:[track album]];
|
NSString *temp;
|
||||||
int64_t albumartistId = [self addString:[track albumartist]];
|
temp = [track album];
|
||||||
int64_t artistId = [self addString:[track artist]];
|
int64_t albumId = [self addString:&temp];
|
||||||
int64_t titleId = [self addString:[track rawTitle]];
|
[track setAlbum:temp];
|
||||||
int64_t genreId = [self addString:[track genre]];
|
temp = [track albumartist];
|
||||||
int64_t codecId = [self addString:[track codec]];
|
int64_t albumartistId = [self addString:&temp];
|
||||||
int64_t cuesheetId = [self addString:[track cuesheet]];
|
[track setAlbumartist:temp];
|
||||||
int64_t encodingId = [self addString:[track encoding]];
|
temp = [track artist];
|
||||||
|
int64_t artistId = [self addString:&temp];
|
||||||
|
[track setArtist:temp];
|
||||||
|
temp = [track rawTitle];
|
||||||
|
int64_t titleId = [self addString:&temp];
|
||||||
|
[track setTitle:temp];
|
||||||
|
temp = [track genre];
|
||||||
|
int64_t genreId = [self addString:&temp];
|
||||||
|
[track setGenre:temp];
|
||||||
|
temp = [track codec];
|
||||||
|
int64_t codecId = [self addString:&temp];
|
||||||
|
[track setCodec:temp];
|
||||||
|
temp = [track cuesheet];
|
||||||
|
int64_t cuesheetId = [self addString:&temp];
|
||||||
|
[track setCuesheet:temp];
|
||||||
|
temp = [track encoding];
|
||||||
|
int64_t encodingId = [self addString:&temp];
|
||||||
|
[track setEncoding:temp];
|
||||||
int64_t trackNr = [[track track] intValue] | (((uint64_t)[[track disc] intValue]) << 32);
|
int64_t trackNr = [[track track] intValue] | (((uint64_t)[[track disc] intValue]) << 32);
|
||||||
int64_t year = [[track year] intValue];
|
int64_t year = [[track year] intValue];
|
||||||
int64_t unsignedFmt = [track Unsigned];
|
int64_t unsignedFmt = [track Unsigned];
|
||||||
|
@ -1021,7 +1049,9 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
int64_t bitspersample = [track bitsPerSample];
|
int64_t bitspersample = [track bitsPerSample];
|
||||||
int64_t channels = [track channels];
|
int64_t channels = [track channels];
|
||||||
int64_t channelConfig = [track channelConfig];
|
int64_t channelConfig = [track channelConfig];
|
||||||
int64_t endianId = [self addString:[track endian]];
|
temp = [track endian];
|
||||||
|
int64_t endianId = [self addString:&temp];
|
||||||
|
[track setEndian:temp];
|
||||||
int64_t floatingpoint = [track floatingPoint];
|
int64_t floatingpoint = [track floatingPoint];
|
||||||
int64_t totalframes = [track totalFrames];
|
int64_t totalframes = [track totalFrames];
|
||||||
int64_t metadataloaded = [track metadataLoaded];
|
int64_t metadataloaded = [track metadataLoaded];
|
||||||
|
@ -1113,7 +1143,7 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
NSURL *url = [track URL];
|
NSURL *url = [track URL];
|
||||||
NSString *urlString = [url absoluteString];
|
NSString *urlString = [url absoluteString];
|
||||||
|
|
||||||
int64_t urlId = [self addString:urlString];
|
int64_t urlId = [self addString:&urlString];
|
||||||
|
|
||||||
sqlite3_stmt *st = stmt[stmt_select_track];
|
sqlite3_stmt *st = stmt[stmt_select_track];
|
||||||
|
|
||||||
|
@ -1201,14 +1231,31 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
sqlite3_reset(st);
|
sqlite3_reset(st);
|
||||||
|
|
||||||
{
|
{
|
||||||
int64_t albumId = [self addString:[track album]];
|
NSString *temp;
|
||||||
int64_t albumartistId = [self addString:[track albumartist]];
|
temp = [track album];
|
||||||
int64_t artistId = [self addString:[track artist]];
|
int64_t albumId = [self addString:&temp];
|
||||||
int64_t titleId = [self addString:[track rawTitle]];
|
[track setAlbum:temp];
|
||||||
int64_t genreId = [self addString:[track genre]];
|
temp = [track albumartist];
|
||||||
int64_t codecId = [self addString:[track codec]];
|
int64_t albumartistId = [self addString:&temp];
|
||||||
int64_t cuesheetId = [self addString:[track cuesheet]];
|
[track setAlbumartist:temp];
|
||||||
int64_t encodingId = [self addString:[track encoding]];
|
temp = [track artist];
|
||||||
|
int64_t artistId = [self addString:&temp];
|
||||||
|
[track setArtist:temp];
|
||||||
|
temp = [track rawTitle];
|
||||||
|
int64_t titleId = [self addString:&temp];
|
||||||
|
[track setTitle:temp];
|
||||||
|
temp = [track genre];
|
||||||
|
int64_t genreId = [self addString:&temp];
|
||||||
|
[track setGenre:temp];
|
||||||
|
temp = [track codec];
|
||||||
|
int64_t codecId = [self addString:&temp];
|
||||||
|
[track setCodec:temp];
|
||||||
|
temp = [track cuesheet];
|
||||||
|
int64_t cuesheetId = [self addString:&temp];
|
||||||
|
[track setCuesheet:temp];
|
||||||
|
temp = [track encoding];
|
||||||
|
int64_t encodingId = [self addString:&temp];
|
||||||
|
[track setEncoding:temp];
|
||||||
int64_t trackNr = [[track track] intValue] | (((uint64_t)[[track disc] intValue]) << 32);
|
int64_t trackNr = [[track track] intValue] | (((uint64_t)[[track disc] intValue]) << 32);
|
||||||
int64_t year = [[track year] intValue];
|
int64_t year = [[track year] intValue];
|
||||||
int64_t unsignedFmt = [track Unsigned];
|
int64_t unsignedFmt = [track Unsigned];
|
||||||
|
@ -1217,7 +1264,9 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
int64_t bitspersample = [track bitsPerSample];
|
int64_t bitspersample = [track bitsPerSample];
|
||||||
int64_t channels = [track channels];
|
int64_t channels = [track channels];
|
||||||
int64_t channelConfig = [track channelConfig];
|
int64_t channelConfig = [track channelConfig];
|
||||||
int64_t endianId = [self addString:[track endian]];
|
temp = [track endian];
|
||||||
|
int64_t endianId = [self addString:&temp];
|
||||||
|
[track setEndian:temp];
|
||||||
int64_t floatingpoint = [track floatingPoint];
|
int64_t floatingpoint = [track floatingPoint];
|
||||||
int64_t totalframes = [track totalFrames];
|
int64_t totalframes = [track totalFrames];
|
||||||
int64_t metadataloaded = [track metadataLoaded];
|
int64_t metadataloaded = [track metadataLoaded];
|
||||||
|
|
Loading…
Reference in a new issue