Skip to content

Commit

Permalink
SQLite Store / Drag and Drop: Now correctly store changes made by dra…
Browse files Browse the repository at this point in the history
…gging playlist entries around to the database
  • Loading branch information
kode54 committed Jan 24, 2022
1 parent fee7fcd commit d8b16e4
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 83 deletions.
10 changes: 7 additions & 3 deletions Playlist/PlaylistController.m
Expand Up @@ -379,6 +379,10 @@ - (void)moveObjectsFromIndex:(NSUInteger)fromIndex
[[self undoManager] setActionName:actionName];

[super moveObjectsFromIndex:fromIndex toArrangedObjectIndexes:indexSet];

[[SQLiteStore sharedStore] playlistMoveObjectsFromIndex:fromIndex toArrangedObjectIndexes:indexSet progressCall:^(double progress) {
[self setProgressBarStatus:progress];
}];

[playbackController playlistDidChange:self];
}
Expand All @@ -393,9 +397,9 @@ - (void)moveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet

[super moveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:insertIndex];

#if 0 // syncPlaylistEntries is already called for rearrangement
[[SQLiteStore sharedStore] playlistMoveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:insertIndex];
#endif
[[SQLiteStore sharedStore] playlistMoveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:insertIndex progressCall:^(double progress) {
[self setProgressBarStatus:progress];
}];

[playbackController playlistDidChange:self];
}
Expand Down
6 changes: 3 additions & 3 deletions Utils/SQLiteStore.h
Expand Up @@ -35,9 +35,9 @@
- (PlaylistEntry *)playlistGetItem:(int64_t)index;
- (PlaylistEntry *)playlistGetCachedItem:(int64_t)index;
- (int64_t)playlistGetCount;
#if 0
- (void)playlistMoveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex;
#endif

- (void)playlistMoveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex progressCall:(void (^)(double))callback;
- (void)playlistMoveObjectsFromIndex:(NSUInteger)fromIndex toArrangedObjectIndexes:(NSIndexSet *)indexSet progressCall:(void (^)(double))callback;

- (void)syncPlaylistEntries:(NSArray *)entries progressCall:(void(^)(double progress))callback;

Expand Down
217 changes: 140 additions & 77 deletions Utils/SQLiteStore.m
Expand Up @@ -1855,109 +1855,172 @@ - (int64_t)playlistGetCount
return ret;
}

#if 0 // syncPlaylistEntries is already called where this would be needed
- (void)playlistMoveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex
- (void)playlistMoveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex progressCall:(void (^)(double))callback
{
__block NSMutableArray *entryIds = [[NSMutableArray alloc] init];
__block NSMutableArray *trackIds = [[NSMutableArray alloc] init];

NSMutableArray *postEntryIds = [[NSMutableArray alloc] init];
NSMutableArray *postTrackIds = [[NSMutableArray alloc] init];
__block NSUInteger rangeCount = 0;
__block NSUInteger firstIndex = 0;
[indexSet enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
if (++rangeCount == 1)
firstIndex = range.location;
}];

sqlite3_stmt *st = stmt[stmt_select_playlist];
if (rangeCount == 1 &&
(insertIndex >= firstIndex &&
insertIndex < firstIndex + [indexSet count])) // Null operation
return;

[indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, select_playlist_in_id, idx) ||
sqlite3_step(st) != SQLITE_ROW)
{
*stop = YES;
return;
NSArray *objects = databaseMirror;
NSUInteger index = [indexSet lastIndex];

NSUInteger aboveInsertIndexCount = 0;
id object;
NSUInteger removeIndex;

callback(0);
double progress = 0;
double progressstep = 100.0 / [indexSet count];

while (NSNotFound != index) {
if (index >= insertIndex) {
removeIndex = index + aboveInsertIndexCount;
aboveInsertIndexCount += 1;
} else {
removeIndex = index;
insertIndex -= 1;
}

object = objects[removeIndex];

sqlite3_stmt * st = stmt[stmt_remove_playlist_by_range];
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, remove_playlist_by_range_in_low, removeIndex) ||
sqlite3_bind_int64(st, remove_playlist_by_range_in_high, removeIndex) ||
sqlite3_step(st) != SQLITE_DONE)
break;

int64_t entryId = sqlite3_column_int64(st, select_playlist_out_entry_id);
int64_t trackId = sqlite3_column_int64(st, select_playlist_out_track_id);
st = stmt[stmt_decrement_playlist_for_removal];
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, decrement_playlist_for_removal_in_count, 1) ||
sqlite3_bind_int64(st, decrement_playlist_for_removal_in_index, removeIndex + 1) ||
sqlite3_step(st) != SQLITE_DONE)
break;

[entryIds addObject:[NSNumber numberWithInteger:entryId]];
[trackIds addObject:[NSNumber numberWithInteger:trackId]];
}];

int64_t count = [self playlistGetCount];

sqlite3_reset(st);

st = stmt[stmt_select_playlist_range];

int rc;

if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, select_playlist_range_in_id_low, insertIndex) ||
sqlite3_bind_int64(st, select_playlist_range_in_id_high, count - 1) ||
(rc = sqlite3_step(st)) != SQLITE_ROW)
{
return;
}

do
{
int64_t entryId = sqlite3_column_int64(st, select_playlist_range_out_entry_id);
int64_t trackId = sqlite3_column_int64(st, select_playlist_range_out_track_id);
[databaseMirror removeObjectAtIndex:removeIndex];

if (![entryIds containsObject:[NSNumber numberWithInteger:entryId]])
{
[postEntryIds addObject:[NSNumber numberWithInteger:entryId]];
[postTrackIds addObject:[NSNumber numberWithInteger:trackId]];
}
st = stmt[stmt_increment_playlist_for_insert];
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, increment_playlist_for_insert_in_count, 1) ||
sqlite3_bind_int64(st, increment_playlist_for_insert_in_index, insertIndex) ||
sqlite3_step(st) != SQLITE_DONE)
break;

rc = sqlite3_step(st);
st = stmt[stmt_add_playlist];
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, add_playlist_in_entry_index, insertIndex) ||
sqlite3_bind_int64(st, add_playlist_in_track_id, [object dbIndex]) ||
sqlite3_step(st) != SQLITE_DONE)
break;

[databaseMirror insertObject:object atIndex:insertIndex];

index = [indexSet indexLessThanIndex:index];

progress += progressstep;
callback(progress);
}
while (rc == SQLITE_ROW);

if (rc != SQLITE_DONE)
{
return;
}
callback(-1);
}

- (void)playlistMoveObjectsFromIndex:(NSUInteger)fromIndex
toArrangedObjectIndexes:(NSIndexSet *)indexSet
progressCall:(void (^)(double))callback {
__block NSUInteger rangeCount = 0;
__block NSUInteger firstIndex = 0;
__block NSUInteger _fromIndex = fromIndex;
[indexSet enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
if (++rangeCount == 1)
firstIndex = range.location;
if (_fromIndex >= range.location) {
if (_fromIndex < range.location + range.length)
_fromIndex = range.location;
else
_fromIndex -= range.length;
}
}];

int64_t i;
if (rangeCount == 1 &&
(fromIndex >= firstIndex &&
fromIndex < firstIndex + [indexSet count])) // Null operation
return;

const int64_t entryIndexBase = insertIndex + [entryIds count];
callback(0);
double progress = 0;
double progressstep = 50.0 / [indexSet count];

fromIndex = _fromIndex;

st = stmt[stmt_update_playlist];
NSArray *objects = [databaseMirror subarrayWithRange:NSMakeRange(fromIndex, [indexSet count])];
NSUInteger index = [indexSet firstIndex];

for (i = 0, count = [postEntryIds count]; i < count; ++i)
NSUInteger itemIndex = 0;
id object;

sqlite3_stmt * st;

fromIndex += [objects count];
{
int64_t entryId = [[postEntryIds objectAtIndex:i] integerValue];
int64_t trackId = [[postTrackIds objectAtIndex:i] integerValue];
st = stmt[stmt_remove_playlist_by_range];
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, remove_playlist_by_range_in_low, fromIndex) ||
sqlite3_bind_int64(st, remove_playlist_by_range_in_high, fromIndex + [indexSet count] - 1) ||
sqlite3_step(st) != SQLITE_DONE) {
callback(-1);
return;
}

st = stmt[stmt_decrement_playlist_for_removal];
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, update_playlist_in_entry_index, entryIndexBase + i) ||
sqlite3_bind_int64(st, update_playlist_in_track_id, trackId) ||
sqlite3_bind_int64(st, update_playlist_in_id, entryId) ||
sqlite3_step(st) != SQLITE_DONE)
{
sqlite3_reset(st);
sqlite3_bind_int64(st, decrement_playlist_for_removal_in_count, [indexSet count]) ||
sqlite3_bind_int64(st, decrement_playlist_for_removal_in_index, fromIndex) ||
sqlite3_step(st) != SQLITE_DONE) {
callback(-1);
return;
}

[databaseMirror removeObjectsInRange:NSMakeRange(fromIndex, [indexSet count])];

progress += progressstep;
callback(progress);
}

for (i = 0, count = [entryIds count]; i < count; ++i)
{
int64_t entryId = [[entryIds objectAtIndex:i] integerValue];
int64_t trackId = [[trackIds objectAtIndex:i] integerValue];
while (NSNotFound != index) {
object = objects[itemIndex++];

st = stmt[stmt_increment_playlist_for_insert];
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, increment_playlist_for_insert_in_count, 1) ||
sqlite3_bind_int64(st, increment_playlist_for_insert_in_index, index) ||
sqlite3_step(st) != SQLITE_DONE)
break;

st = stmt[stmt_add_playlist];
if (sqlite3_reset(st) ||
sqlite3_bind_int64(st, update_playlist_in_entry_index, insertIndex + i) ||
sqlite3_bind_int64(st, update_playlist_in_track_id, trackId) ||
sqlite3_bind_int64(st, update_playlist_in_id, entryId) ||
sqlite3_bind_int64(st, add_playlist_in_entry_index, index) ||
sqlite3_bind_int64(st, add_playlist_in_track_id, [object dbIndex]) ||
sqlite3_step(st) != SQLITE_DONE)
{
return;
}
}
break;

[databaseMirror insertObject:object atIndex:index];

sqlite3_reset(st);
index = [indexSet indexGreaterThanIndex:index];

progress += progressstep;
callback(progress);
}

callback(-1);
}
#endif

- (void)syncPlaylistEntries:(NSArray *)entries progressCall:(void (^)(double))callback
{
Expand Down

0 comments on commit d8b16e4

Please sign in to comment.