[Job Queue] Overhauled long action handling
Long actions, such as file opening, playlist loading, metadata loading and refreshing, etc, are now handled through NSProgress. Additionally, a new status bar change displays the progress of the task instead of the total duration of the playlist. Finally, app quit is blocked by a running task, and if the app is quit while a task is running, it will be delayed until the task completes, at which time the app will terminate cleanly. Signed-off-by: Christopher Snowhill <kode54@gmail.com>swiftingly
parent
6c7a3e581c
commit
92573ec088
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#import "ColorToValueTransformer.h"
|
#import "ColorToValueTransformer.h"
|
||||||
|
|
||||||
|
#import "TotalTimeTransformer.h"
|
||||||
|
|
||||||
#import "Shortcuts.h"
|
#import "Shortcuts.h"
|
||||||
#import <MASShortcut/Shortcut.h>
|
#import <MASShortcut/Shortcut.h>
|
||||||
|
|
||||||
|
@ -53,8 +55,11 @@ void *kAppControllerContext = &kAppControllerContext;
|
||||||
NSValueTransformer *colorToValueTransformer = [[ColorToValueTransformer alloc] init];
|
NSValueTransformer *colorToValueTransformer = [[ColorToValueTransformer alloc] init];
|
||||||
[NSValueTransformer setValueTransformer:colorToValueTransformer
|
[NSValueTransformer setValueTransformer:colorToValueTransformer
|
||||||
forName:@"ColorToValueTransformer"];
|
forName:@"ColorToValueTransformer"];
|
||||||
}
|
|
||||||
|
|
||||||
|
NSValueTransformer *totalTimeTransformer = [[TotalTimeTransformer alloc] init];
|
||||||
|
[NSValueTransformer setValueTransformer:totalTimeTransformer
|
||||||
|
forName:@"TotalTimeTransformer"];
|
||||||
|
}
|
||||||
- (id)init {
|
- (id)init {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if(self) {
|
if(self) {
|
||||||
|
@ -307,6 +312,12 @@ void *kAppControllerContext = &kAppControllerContext;
|
||||||
miniWindow.title = title;
|
miniWindow.title = title;
|
||||||
mainWindow.title = title;
|
mainWindow.title = title;
|
||||||
}
|
}
|
||||||
|
} else if([keyPath isEqualToString:@"finished"]) {
|
||||||
|
NSProgress *progress = (NSProgress *)object;
|
||||||
|
if([progress isFinished]) {
|
||||||
|
playbackController.progressOverall = nil;
|
||||||
|
[NSApp terminate:nil];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,6 +335,15 @@ void *kAppControllerContext = &kAppControllerContext;
|
||||||
[expandedNodes removeObject:url];
|
[expandedNodes removeObject:url];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
|
||||||
|
if(playbackController.progressOverall) {
|
||||||
|
[playbackController.progressOverall addObserver:self forKeyPath:@"finished" options:0 context:kAppControllerContext];
|
||||||
|
return NSTerminateLater;
|
||||||
|
} else {
|
||||||
|
return NSTerminateNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||||
CogStatus currentStatus = [playbackController playbackStatus];
|
CogStatus currentStatus = [playbackController playbackStatus];
|
||||||
NSInteger lastTrackPlaying = -1;
|
NSInteger lastTrackPlaying = -1;
|
||||||
|
|
|
@ -16,14 +16,22 @@ static NSString *DockIconPlaybackStatusObservationContext = @"DockIconPlaybackSt
|
||||||
|
|
||||||
- (void)startObserving {
|
- (void)startObserving {
|
||||||
[playbackController addObserver:self forKeyPath:@"playbackStatus" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
[playbackController addObserver:self forKeyPath:@"playbackStatus" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
||||||
[playbackController addObserver:self forKeyPath:@"progressBarStatus" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
[playbackController addObserver:self forKeyPath:@"progressOverall" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionOld) context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
||||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.colorfulDockIcons" options:0 context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.colorfulDockIcons" options:0 context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)stopObserving {
|
- (void)stopObserving {
|
||||||
[playbackController removeObserver:self forKeyPath:@"playbackStatus"];
|
[playbackController removeObserver:self forKeyPath:@"playbackStatus" context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
||||||
[playbackController removeObserver:self forKeyPath:@"progressBarStatus"];
|
[playbackController removeObserver:self forKeyPath:@"progressOverall" context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
||||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.colorfulDockIcons"];
|
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.colorfulDockIcons" context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startObservingProgress:(NSProgress *)progress {
|
||||||
|
[progress addObserver:self forKeyPath:@"fractionCompleted" options:0 context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopObservingProgress:(NSProgress *)progress {
|
||||||
|
[progress removeObserver:self forKeyPath:@"fractionCompleted" context:(__bridge void *_Nullable)(DockIconPlaybackStatusObservationContext)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons) {
|
static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons) {
|
||||||
|
@ -151,12 +159,35 @@ static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons) {
|
||||||
NSInteger playbackStatus = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
|
NSInteger playbackStatus = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
|
||||||
|
|
||||||
[self refreshDockIcon:playbackStatus withProgress:-10];
|
[self refreshDockIcon:playbackStatus withProgress:-10];
|
||||||
} else if([keyPath isEqualToString:@"progressBarStatus"]) {
|
} else if([keyPath isEqualToString:@"progressOverall"]) {
|
||||||
double progressStatus = [[change objectForKey:NSKeyValueChangeNewKey] doubleValue];
|
double progressStatus = [lastProgressStatus doubleValue];
|
||||||
|
|
||||||
|
id objNew = [change objectForKey:NSKeyValueChangeNewKey];
|
||||||
|
id objOld = [change objectForKey:NSKeyValueChangeOldKey];
|
||||||
|
|
||||||
|
NSProgress *progressNew = nil, *progressOld = nil;
|
||||||
|
|
||||||
|
if(objNew && [objNew isKindOfClass:[NSProgress class]])
|
||||||
|
progressNew = (NSProgress *)objNew;
|
||||||
|
if(objOld && [objOld isKindOfClass:[NSProgress class]])
|
||||||
|
progressOld = (NSProgress *)objOld;
|
||||||
|
|
||||||
|
if(progressOld) {
|
||||||
|
[self stopObservingProgress:progressOld];
|
||||||
|
progressStatus = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(progressNew) {
|
||||||
|
[self startObservingProgress:progressNew];
|
||||||
|
progressStatus = progressNew.fractionCompleted * 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
[self refreshDockIcon:-1 withProgress:progressStatus];
|
[self refreshDockIcon:-1 withProgress:progressStatus];
|
||||||
} else if([keyPath isEqualToString:@"values.colorfulDockIcons"]) {
|
} else if([keyPath isEqualToString:@"values.colorfulDockIcons"]) {
|
||||||
[self refreshDockIcon:-1 withProgress:-10];
|
[self refreshDockIcon:-1 withProgress:-10];
|
||||||
|
} else if([keyPath isEqualToString:@"fractionCompleted"]) {
|
||||||
|
double progressStatus = [(NSProgress *)object fractionCompleted];
|
||||||
|
[self refreshDockIcon:-1 withProgress:progressStatus * 100.0];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
||||||
|
|
|
@ -53,14 +53,16 @@ extern NSDictionary *makeRGInfo(PlaylistEntry *pe);
|
||||||
BOOL fading;
|
BOOL fading;
|
||||||
|
|
||||||
// progress bar display
|
// progress bar display
|
||||||
double progressBarStatus;
|
NSProgress *progressOverall;
|
||||||
|
NSProgress *progressJob;
|
||||||
|
|
||||||
AudioUnit _eq;
|
AudioUnit _eq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property CogStatus playbackStatus;
|
@property CogStatus playbackStatus;
|
||||||
|
|
||||||
@property double progressBarStatus;
|
@property NSProgress *progressOverall;
|
||||||
|
@property NSProgress *progressJob;
|
||||||
|
|
||||||
- (IBAction)changeVolume:(id)sender;
|
- (IBAction)changeVolume:(id)sender;
|
||||||
- (IBAction)volumeDown:(id)sender;
|
- (IBAction)volumeDown:(id)sender;
|
||||||
|
|
|
@ -30,7 +30,8 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
|
||||||
|
|
||||||
@synthesize playbackStatus;
|
@synthesize playbackStatus;
|
||||||
|
|
||||||
@synthesize progressBarStatus;
|
@synthesize progressOverall;
|
||||||
|
@synthesize progressJob;
|
||||||
|
|
||||||
+ (NSSet *)keyPathsForValuesAffectingSeekable {
|
+ (NSSet *)keyPathsForValuesAffectingSeekable {
|
||||||
return [NSSet setWithObjects:@"playlistController.currentEntry", @"playlistController.currentEntry.seekable", nil];
|
return [NSSet setWithObjects:@"playlistController.currentEntry", @"playlistController.currentEntry.seekable", nil];
|
||||||
|
@ -44,7 +45,8 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
|
||||||
seekable = NO;
|
seekable = NO;
|
||||||
fading = NO;
|
fading = NO;
|
||||||
|
|
||||||
progressBarStatus = -1;
|
progressOverall = nil;
|
||||||
|
progressJob = nil;
|
||||||
|
|
||||||
audioPlayer = [[AudioPlayer alloc] init];
|
audioPlayer = [[AudioPlayer alloc] init];
|
||||||
[audioPlayer setDelegate:self];
|
[audioPlayer setDelegate:self];
|
||||||
|
|
|
@ -25,17 +25,17 @@
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<splitView dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2123">
|
<splitView dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2123">
|
||||||
<rect key="frame" x="0.0" y="73" width="1000" height="327"/>
|
<rect key="frame" x="0.0" y="107" width="1000" height="293"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<scrollView fixedFrame="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="0.0" verticalLineScroll="24" verticalPageScroll="0.0" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="206" userLabel="Scroll View - Playlist View">
|
<scrollView fixedFrame="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="0.0" verticalLineScroll="24" verticalPageScroll="0.0" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="206" userLabel="Scroll View - Playlist View">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="1000" height="344"/>
|
<rect key="frame" x="0.0" y="0.0" width="1000" height="293"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="KWC-Ti-8KY">
|
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="KWC-Ti-8KY">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="1000" height="344"/>
|
<rect key="frame" x="0.0" y="0.0" width="1000" height="293"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" alternatingRowBackgroundColors="YES" autosaveName="Playlist" rowHeight="18" headerView="1517" viewBased="YES" id="207" customClass="PlaylistView">
|
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" alternatingRowBackgroundColors="YES" autosaveName="Playlist" rowHeight="18" headerView="1517" viewBased="YES" id="207" customClass="PlaylistView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="1000" height="327"/>
|
<rect key="frame" x="0.0" y="0.0" width="1000" height="276"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<size key="intercellSpacing" width="3" height="6"/>
|
<size key="intercellSpacing" width="3" height="6"/>
|
||||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
@ -651,9 +651,15 @@
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
<connections>
|
<connections>
|
||||||
<binding destination="218" name="displayPatternValue1" keyPath="totalTime" id="1891">
|
<binding destination="218" name="displayPatternValue1" keyPath="totalTime" id="Kih-ky-A1h">
|
||||||
<dictionary key="options">
|
<dictionary key="options">
|
||||||
<string key="NSDisplayPattern">Total Duration: %{value1}@</string>
|
<string key="NSDisplayPattern">%{value1}@%{value2}@</string>
|
||||||
|
<string key="NSValueTransformerName">TotalTimeTransformer</string>
|
||||||
|
</dictionary>
|
||||||
|
</binding>
|
||||||
|
<binding destination="218" name="displayPatternValue2" keyPath="currentStatus" previousBinding="Kih-ky-A1h" id="5bQ-Qy-2KR">
|
||||||
|
<dictionary key="options">
|
||||||
|
<string key="NSDisplayPattern">%{value1}@%{value2}@</string>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</binding>
|
</binding>
|
||||||
</connections>
|
</connections>
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
83489C6B2782F78700BDCEA2 /* libvgmPlayer.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83489C542782F2DF00BDCEA2 /* libvgmPlayer.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
83489C6B2782F78700BDCEA2 /* libvgmPlayer.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83489C542782F2DF00BDCEA2 /* libvgmPlayer.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
8349270C27B4EFFC0009AB2B /* duplicateItemsTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 8349270127B4EFFC0009AB2B /* duplicateItemsTemplate.pdf */; };
|
8349270C27B4EFFC0009AB2B /* duplicateItemsTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 8349270127B4EFFC0009AB2B /* duplicateItemsTemplate.pdf */; };
|
||||||
8349270D27B4EFFC0009AB2B /* deadItemsTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 8349270B27B4EFFC0009AB2B /* deadItemsTemplate.pdf */; };
|
8349270D27B4EFFC0009AB2B /* deadItemsTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 8349270B27B4EFFC0009AB2B /* deadItemsTemplate.pdf */; };
|
||||||
|
834B05EA2859C006000B7DC0 /* TotalTimeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 834B05E92859C006000B7DC0 /* TotalTimeTransformer.m */; };
|
||||||
834D793F20E4EFEA00C4A5CC /* OpusPlugin.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 830B62B320E4EF89004A74B2 /* OpusPlugin.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
834D793F20E4EFEA00C4A5CC /* OpusPlugin.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 830B62B320E4EF89004A74B2 /* OpusPlugin.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
834D794020E4EFEF00C4A5CC /* VorbisPlugin.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8301F94520E4EEF70017B2DC /* VorbisPlugin.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
834D794020E4EFEF00C4A5CC /* VorbisPlugin.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8301F94520E4EEF70017B2DC /* VorbisPlugin.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
834F7F4320E4E4ED00228DAB /* AdPlug.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8303A30920E4E3D000951EF8 /* AdPlug.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
834F7F4320E4E4ED00228DAB /* AdPlug.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8303A30920E4E3D000951EF8 /* AdPlug.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
@ -1004,6 +1005,8 @@
|
||||||
83489C4E2782F2DF00BDCEA2 /* libvgmPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libvgmPlayer.xcodeproj; path = Plugins/libvgmPlayer/libvgmPlayer.xcodeproj; sourceTree = "<group>"; };
|
83489C4E2782F2DF00BDCEA2 /* libvgmPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libvgmPlayer.xcodeproj; path = Plugins/libvgmPlayer/libvgmPlayer.xcodeproj; sourceTree = "<group>"; };
|
||||||
8349270127B4EFFC0009AB2B /* duplicateItemsTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = duplicateItemsTemplate.pdf; path = Images/duplicateItemsTemplate.pdf; sourceTree = "<group>"; };
|
8349270127B4EFFC0009AB2B /* duplicateItemsTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = duplicateItemsTemplate.pdf; path = Images/duplicateItemsTemplate.pdf; sourceTree = "<group>"; };
|
||||||
8349270B27B4EFFC0009AB2B /* deadItemsTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = deadItemsTemplate.pdf; path = Images/deadItemsTemplate.pdf; sourceTree = "<group>"; };
|
8349270B27B4EFFC0009AB2B /* deadItemsTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = deadItemsTemplate.pdf; path = Images/deadItemsTemplate.pdf; sourceTree = "<group>"; };
|
||||||
|
834B05E82859C006000B7DC0 /* TotalTimeTransformer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TotalTimeTransformer.h; path = Transformers/TotalTimeTransformer.h; sourceTree = "<group>"; };
|
||||||
|
834B05E92859C006000B7DC0 /* TotalTimeTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TotalTimeTransformer.m; path = Transformers/TotalTimeTransformer.m; sourceTree = "<group>"; };
|
||||||
8355D6B4180612F300D05687 /* NSData+MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+MD5.h"; sourceTree = "<group>"; };
|
8355D6B4180612F300D05687 /* NSData+MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+MD5.h"; sourceTree = "<group>"; };
|
||||||
8355D6B5180612F300D05687 /* NSData+MD5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+MD5.m"; sourceTree = "<group>"; };
|
8355D6B5180612F300D05687 /* NSData+MD5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+MD5.m"; sourceTree = "<group>"; };
|
||||||
8355D6B7180613FB00D05687 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
8355D6B7180613FB00D05687 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||||
|
@ -1539,6 +1542,8 @@
|
||||||
17E0D6140F520F87005B6FED /* StringToURLTransformer.h */,
|
17E0D6140F520F87005B6FED /* StringToURLTransformer.h */,
|
||||||
17E0D6150F520F87005B6FED /* StringToURLTransformer.m */,
|
17E0D6150F520F87005B6FED /* StringToURLTransformer.m */,
|
||||||
838F84FF25687C5C00C3E614 /* Cog-Bridging-Header.h */,
|
838F84FF25687C5C00C3E614 /* Cog-Bridging-Header.h */,
|
||||||
|
834B05E82859C006000B7DC0 /* TotalTimeTransformer.h */,
|
||||||
|
834B05E92859C006000B7DC0 /* TotalTimeTransformer.m */,
|
||||||
);
|
);
|
||||||
name = Transformers;
|
name = Transformers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -2775,6 +2780,7 @@
|
||||||
17249F0F0D82E17700F33392 /* ToggleQueueTitleTransformer.m in Sources */,
|
17249F0F0D82E17700F33392 /* ToggleQueueTitleTransformer.m in Sources */,
|
||||||
179D031E0E0CB2500064A77A /* ContainedNode.m in Sources */,
|
179D031E0E0CB2500064A77A /* ContainedNode.m in Sources */,
|
||||||
179D031F0E0CB2500064A77A /* ContainerNode.m in Sources */,
|
179D031F0E0CB2500064A77A /* ContainerNode.m in Sources */,
|
||||||
|
834B05EA2859C006000B7DC0 /* TotalTimeTransformer.m in Sources */,
|
||||||
839DA7CF274A2D4C001B18E5 /* NSDictionary+Merge.m in Sources */,
|
839DA7CF274A2D4C001B18E5 /* NSDictionary+Merge.m in Sources */,
|
||||||
179D03200E0CB2500064A77A /* DirectoryNode.m in Sources */,
|
179D03200E0CB2500064A77A /* DirectoryNode.m in Sources */,
|
||||||
179D03210E0CB2500064A77A /* FileIconCell.m in Sources */,
|
179D03210E0CB2500064A77A /* FileIconCell.m in Sources */,
|
||||||
|
|
|
@ -46,16 +46,20 @@ typedef NS_ENUM(NSInteger, URLOrigin) {
|
||||||
NSMutableArray *queueList;
|
NSMutableArray *queueList;
|
||||||
|
|
||||||
NSString *totalTime;
|
NSString *totalTime;
|
||||||
|
NSString *currentStatus;
|
||||||
|
|
||||||
PlaylistEntry *currentEntry;
|
PlaylistEntry *currentEntry;
|
||||||
|
|
||||||
PlaylistEntry *nextEntryAfterDeleted;
|
PlaylistEntry *nextEntryAfterDeleted;
|
||||||
|
|
||||||
NSUndoManager *undoManager;
|
NSUndoManager *undoManager;
|
||||||
|
|
||||||
|
BOOL observersRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property(nonatomic, retain) PlaylistEntry *_Nullable currentEntry;
|
@property(nonatomic, retain) PlaylistEntry *_Nullable currentEntry;
|
||||||
@property(retain) NSString *_Nullable totalTime;
|
@property(retain) NSString *_Nullable totalTime;
|
||||||
|
@property(retain) NSString *_Nullable currentStatus;
|
||||||
|
|
||||||
// Private Methods
|
// Private Methods
|
||||||
- (void)updateTotalTime;
|
- (void)updateTotalTime;
|
||||||
|
|
|
@ -28,9 +28,12 @@
|
||||||
|
|
||||||
@synthesize currentEntry;
|
@synthesize currentEntry;
|
||||||
@synthesize totalTime;
|
@synthesize totalTime;
|
||||||
|
@synthesize currentStatus;
|
||||||
|
|
||||||
static NSArray *cellIdentifiers = nil;
|
static NSArray *cellIdentifiers = nil;
|
||||||
|
|
||||||
|
static void *playlistControllerContext = &playlistControllerContext;
|
||||||
|
|
||||||
+ (void)initialize {
|
+ (void)initialize {
|
||||||
cellIdentifiers = @[@"index", @"status", @"title", @"albumartist", @"artist",
|
cellIdentifiers = @[@"index", @"status", @"title", @"albumartist", @"artist",
|
||||||
@"album", @"length", @"year", @"genre", @"track", @"path",
|
@"album", @"length", @"year", @"genre", @"track", @"path",
|
||||||
|
@ -117,22 +120,93 @@ static NSArray *cellIdentifiers = nil;
|
||||||
[self addObserver:self
|
[self addObserver:self
|
||||||
forKeyPath:@"arrangedObjects"
|
forKeyPath:@"arrangedObjects"
|
||||||
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
|
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
|
||||||
context:nil];
|
context:playlistControllerContext];
|
||||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.fontSize" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:nil];
|
[playbackController addObserver:self
|
||||||
|
forKeyPath:@"progressOverall"
|
||||||
|
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionOld)
|
||||||
|
context:playlistControllerContext];
|
||||||
|
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.fontSize" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:playlistControllerContext];
|
||||||
|
|
||||||
|
observersRegistered = YES;
|
||||||
|
|
||||||
[self.tableView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
|
[self.tableView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)deinit {
|
||||||
|
if(observersRegistered) {
|
||||||
|
[self removeObserver:self forKeyPath:@"arrangedObjects" context:playlistControllerContext];
|
||||||
|
[playbackController removeObserver:self forKeyPath:@"progressOverall" context:playlistControllerContext];
|
||||||
|
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.fontSize" context:playlistControllerContext];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startObservingProgress:(NSProgress *)progress {
|
||||||
|
[progress addObserver:self forKeyPath:@"localizedDescription" options:0 context:playlistControllerContext];
|
||||||
|
[progress addObserver:self forKeyPath:@"fractionCompleted" options:0 context:playlistControllerContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopObservingProgress:(NSProgress *)progress {
|
||||||
|
[progress removeObserver:self forKeyPath:@"localizedDescription" context:playlistControllerContext];
|
||||||
|
[progress removeObserver:self forKeyPath:@"fractionCompleted" context:playlistControllerContext];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||||
ofObject:(id)object
|
ofObject:(id)object
|
||||||
change:(NSDictionary *)change
|
change:(NSDictionary *)change
|
||||||
context:(void *)context {
|
context:(void *)context {
|
||||||
if([keyPath isEqualToString:@"arrangedObjects"]) {
|
if(context == playlistControllerContext) {
|
||||||
[self updatePlaylistIndexes];
|
if([keyPath isEqualToString:@"arrangedObjects"]) {
|
||||||
|
[self updatePlaylistIndexes];
|
||||||
|
[self updateTotalTime];
|
||||||
|
[self.tableView reloadData];
|
||||||
|
} else if([keyPath isEqualToString:@"values.fontSize"]) {
|
||||||
|
[self updateRowSize];
|
||||||
|
} else if([keyPath isEqualToString:@"progressOverall"]) {
|
||||||
|
id objNew = [change objectForKey:NSKeyValueChangeNewKey];
|
||||||
|
id objOld = [change objectForKey:NSKeyValueChangeOldKey];
|
||||||
|
|
||||||
|
NSProgress *progressNew = nil, *progressOld = nil;
|
||||||
|
|
||||||
|
if(objNew && [objNew isKindOfClass:[NSProgress class]])
|
||||||
|
progressNew = (NSProgress *)objNew;
|
||||||
|
if(objOld && [objOld isKindOfClass:[NSProgress class]])
|
||||||
|
progressOld = (NSProgress *)objOld;
|
||||||
|
|
||||||
|
if(progressOld) {
|
||||||
|
[self stopObservingProgress:progressOld];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(progressNew) {
|
||||||
|
[self startObservingProgress:progressNew];
|
||||||
|
}
|
||||||
|
|
||||||
|
[self updateProgressText];
|
||||||
|
} else if([keyPath isEqualToString:@"localizedDescription"] ||
|
||||||
|
[keyPath isEqualToString:@"fractionCompleted"]) {
|
||||||
|
[self updateProgressText];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateProgressText {
|
||||||
|
NSString *description = nil;
|
||||||
|
if(playbackController.progressOverall) {
|
||||||
|
if(playbackController.progressJob) {
|
||||||
|
description = [NSString stringWithFormat:@"%@ - %@", playbackController.progressOverall.localizedDescription, playbackController.progressJob.localizedDescription];
|
||||||
|
} else {
|
||||||
|
description = playbackController.progressOverall.localizedDescription;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(description) {
|
||||||
|
[self setTotalTime:nil];
|
||||||
|
description = [description stringByAppendingFormat:@" - %.2f%% complete", playbackController.progressOverall.fractionCompleted * 100.0];
|
||||||
|
[self setCurrentStatus:description];
|
||||||
|
} else {
|
||||||
|
[self setCurrentStatus:nil];
|
||||||
[self updateTotalTime];
|
[self updateTotalTime];
|
||||||
[self.tableView reloadData];
|
|
||||||
} else if([keyPath isEqualToString:@"values.fontSize"]) {
|
|
||||||
[self updateRowSize];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,13 +218,31 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setProgressBarStatus:(double)status {
|
- (void)beginProgress:(NSString *)localizedDescription {
|
||||||
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
[self->playbackController setProgressBarStatus:status];
|
self->playbackController.progressOverall = [NSProgress progressWithTotalUnitCount:100000];
|
||||||
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.001]];
|
self->playbackController.progressOverall.localizedDescription = localizedDescription;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)completeProgress {
|
||||||
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
[self->playbackController.progressOverall setCompletedUnitCount:100000];
|
||||||
|
self->playbackController.progressOverall = nil;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setProgressStatus:(double)status {
|
||||||
|
if(status >= 0) {
|
||||||
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
NSUInteger jobCount = (NSUInteger)ceil(1000.0 * status);
|
||||||
|
[self->playbackController.progressOverall setCompletedUnitCount:jobCount];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
[self completeProgress];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updatePlaylistIndexes {
|
- (void)updatePlaylistIndexes {
|
||||||
NSArray *arranged = [self arrangedObjects];
|
NSArray *arranged = [self arrangedObjects];
|
||||||
NSUInteger n = [arranged count];
|
NSUInteger n = [arranged count];
|
||||||
|
@ -163,10 +255,12 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(updated) {
|
if(updated) {
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionUpdatingIndexes", @"updating playlist indexes")];
|
||||||
[[SQLiteStore sharedStore] syncPlaylistEntries:arranged
|
[[SQLiteStore sharedStore] syncPlaylistEntries:arranged
|
||||||
progressCall:^(double progress) {
|
progressCall:^(double progress) {
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressStatus:progress];
|
||||||
}];
|
}];
|
||||||
|
[self completeProgress];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,12 +555,16 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
[super moveObjectsFromIndex:fromIndex toArrangedObjectIndexes:indexSet];
|
[super moveObjectsFromIndex:fromIndex toArrangedObjectIndexes:indexSet];
|
||||||
|
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionMovingEntries", @"moving playlist entries")];
|
||||||
|
|
||||||
[[SQLiteStore sharedStore] playlistMoveObjectsFromIndex:fromIndex
|
[[SQLiteStore sharedStore] playlistMoveObjectsFromIndex:fromIndex
|
||||||
toArrangedObjectIndexes:indexSet
|
toArrangedObjectIndexes:indexSet
|
||||||
progressCall:^(double progress) {
|
progressCall:^(double progress) {
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressStatus:progress];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
[self completeProgress];
|
||||||
|
|
||||||
[playbackController playlistDidChange:self];
|
[playbackController playlistDidChange:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,12 +579,16 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
[super moveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:insertIndex];
|
[super moveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:insertIndex];
|
||||||
|
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionMovingEntries", @"moving playlist entries")];
|
||||||
|
|
||||||
[[SQLiteStore sharedStore] playlistMoveObjectsInArrangedObjectsFromIndexes:indexSet
|
[[SQLiteStore sharedStore] playlistMoveObjectsInArrangedObjectsFromIndexes:indexSet
|
||||||
toIndex:insertIndex
|
toIndex:insertIndex
|
||||||
progressCall:^(double progress) {
|
progressCall:^(double progress) {
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressStatus:progress];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
[self completeProgress];
|
||||||
|
|
||||||
[playbackController playlistDidChange:self];
|
[playbackController playlistDidChange:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,14 +771,18 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
pe.deleted = NO;
|
pe.deleted = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionInsertingEntries", @"inserting playlist entries")];
|
||||||
|
|
||||||
[[SQLiteStore sharedStore] playlistInsertTracks:objects
|
[[SQLiteStore sharedStore] playlistInsertTracks:objects
|
||||||
atObjectIndexes:indexes
|
atObjectIndexes:indexes
|
||||||
progressCall:^(double progress) {
|
progressCall:^(double progress) {
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressStatus:progress];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[super insertObjects:objects atArrangedObjectIndexes:indexes];
|
[super insertObjects:objects atArrangedObjectIndexes:indexes];
|
||||||
|
|
||||||
|
[self completeProgress];
|
||||||
|
|
||||||
if([self shuffle] != ShuffleOff) [self resetShuffleList];
|
if([self shuffle] != ShuffleOff) [self resetShuffleList];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,14 +802,18 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
pe.trashURL = nil;
|
pe.trashURL = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionUntrashingEntries", @"restoring playlist entries from the trash")];
|
||||||
|
|
||||||
[[SQLiteStore sharedStore] playlistInsertTracks:objects
|
[[SQLiteStore sharedStore] playlistInsertTracks:objects
|
||||||
atObjectIndexes:indexes
|
atObjectIndexes:indexes
|
||||||
progressCall:^(double progress) {
|
progressCall:^(double progress) {
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressStatus:progress];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[super insertObjects:objects atArrangedObjectIndexes:indexes];
|
[super insertObjects:objects atArrangedObjectIndexes:indexes];
|
||||||
|
|
||||||
|
[self completeProgress];
|
||||||
|
|
||||||
if([self shuffle] != ShuffleOff) [self resetShuffleList];
|
if([self shuffle] != ShuffleOff) [self resetShuffleList];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,15 +869,19 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
currentEntry.index = -i - 1;
|
currentEntry.index = -i - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionRemovingEntries", @"removing playlist entries")];
|
||||||
|
|
||||||
[[SQLiteStore sharedStore] playlistRemoveTracksAtIndexes:unarrangedIndexes
|
[[SQLiteStore sharedStore] playlistRemoveTracksAtIndexes:unarrangedIndexes
|
||||||
progressCall:^(double progress) {
|
progressCall:^(double progress) {
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressStatus:progress];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[super removeObjectsAtArrangedObjectIndexes:indexes];
|
[super removeObjectsAtArrangedObjectIndexes:indexes];
|
||||||
|
|
||||||
if([self shuffle] != ShuffleOff) [self resetShuffleList];
|
if([self shuffle] != ShuffleOff) [self resetShuffleList];
|
||||||
|
|
||||||
|
[self completeProgress];
|
||||||
|
|
||||||
[playbackController playlistDidChange:self];
|
[playbackController playlistDidChange:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,9 +913,11 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionTrashingEntries", @"moving playlist entries to the trash")];
|
||||||
|
|
||||||
[[SQLiteStore sharedStore] playlistRemoveTracksAtIndexes:unarrangedIndexes
|
[[SQLiteStore sharedStore] playlistRemoveTracksAtIndexes:unarrangedIndexes
|
||||||
progressCall:^(double progress) {
|
progressCall:^(double progress) {
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressStatus:progress];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[super removeObjectsAtArrangedObjectIndexes:indexes];
|
[super removeObjectsAtArrangedObjectIndexes:indexes];
|
||||||
|
@ -818,6 +934,8 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
pe.trashURL = removed;
|
pe.trashURL = removed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self completeProgress];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setSortDescriptors:(NSArray *)sortDescriptors {
|
- (void)setSortDescriptors:(NSArray *)sortDescriptors {
|
||||||
|
|
|
@ -26,6 +26,8 @@ typedef enum {
|
||||||
IBOutlet PlaybackController *playbackController;
|
IBOutlet PlaybackController *playbackController;
|
||||||
|
|
||||||
NSOperationQueue *queue;
|
NSOperationQueue *queue;
|
||||||
|
|
||||||
|
BOOL metadataLoadInProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)initDefaults;
|
- (void)initDefaults;
|
||||||
|
|
|
@ -261,12 +261,62 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setProgressBarStatus:(double)status {
|
- (void)beginProgress:(NSString *)localizedDescription {
|
||||||
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
[self->playbackController setProgressBarStatus:status];
|
self->playbackController.progressOverall = [NSProgress progressWithTotalUnitCount:100000];
|
||||||
|
self->playbackController.progressOverall.localizedDescription = localizedDescription;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)completeProgress {
|
||||||
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
if(self->playbackController.progressJob) {
|
||||||
|
[self->playbackController.progressJob setCompletedUnitCount:100000];
|
||||||
|
self->playbackController.progressJob = nil;
|
||||||
|
}
|
||||||
|
[self->playbackController.progressOverall setCompletedUnitCount:100000];
|
||||||
|
self->playbackController.progressOverall = nil;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)beginProgressJob:(NSString *)localizedDescription percentOfTotal:(double)percent {
|
||||||
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
NSUInteger jobCount = (NSUInteger)ceil(1000.0 * percent);
|
||||||
|
self->playbackController.progressJob = [NSProgress progressWithTotalUnitCount:100000];
|
||||||
|
self->playbackController.progressJob.localizedDescription = localizedDescription;
|
||||||
|
[self->playbackController.progressOverall addChild:self->playbackController.progressJob withPendingUnitCount:jobCount];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)completeProgressJob {
|
||||||
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
[self->playbackController.progressJob setCompletedUnitCount:100000];
|
||||||
|
self->playbackController.progressJob = nil;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setProgressStatus:(double)status {
|
||||||
|
if(status >= 0) {
|
||||||
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
NSUInteger jobCount = (NSUInteger)ceil(1000.0 * status);
|
||||||
|
[self->playbackController.progressOverall setCompletedUnitCount:jobCount];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
[self completeProgress];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setProgressJobStatus:(double)status {
|
||||||
|
if(status >= 0) {
|
||||||
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
NSUInteger jobCount = (NSUInteger)ceil(1000.0 * status);
|
||||||
|
[self->playbackController.progressJob setCompletedUnitCount:jobCount];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
[self completeProgressJob];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray *)insertURLs:(NSArray *)urls atIndex:(NSInteger)index sort:(BOOL)sort {
|
- (NSArray *)insertURLs:(NSArray *)urls atIndex:(NSInteger)index sort:(BOOL)sort {
|
||||||
NSMutableSet *uniqueURLs = [NSMutableSet set];
|
NSMutableSet *uniqueURLs = [NSMutableSet set];
|
||||||
|
|
||||||
|
@ -276,19 +326,23 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
NSMutableArray *validURLs = [NSMutableArray array];
|
NSMutableArray *validURLs = [NSMutableArray array];
|
||||||
NSDictionary *xmlData = nil;
|
NSDictionary *xmlData = nil;
|
||||||
|
|
||||||
double progress = 0.0;
|
double progress;
|
||||||
|
|
||||||
if(!urls) {
|
if(!urls) {
|
||||||
[self setProgressBarStatus:-1];
|
[self completeProgress];
|
||||||
return @[];
|
return @[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionLoader", @"playlist loader inserting files")];
|
||||||
|
|
||||||
|
[self beginProgressJob:NSLocalizedString(@"ProgressSubActionLoaderListingFiles", @"collecting files") percentOfTotal:20.0];
|
||||||
|
|
||||||
if(index < 0)
|
if(index < 0)
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
[self setProgressBarStatus:progress];
|
progress = 0.0;
|
||||||
|
|
||||||
double progressstep = [urls count] ? 20.0 / (double)([urls count]) : 0;
|
double progressstep = [urls count] ? 100.0 / (double)([urls count]) : 0;
|
||||||
|
|
||||||
NSURL *url;
|
NSURL *url;
|
||||||
for(url in urls) {
|
for(url in urls) {
|
||||||
|
@ -309,12 +363,12 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
progress += progressstep;
|
progress += progressstep;
|
||||||
|
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressJobStatus:progress];
|
||||||
}
|
}
|
||||||
|
|
||||||
progress = 20.0;
|
[self completeProgressJob];
|
||||||
|
|
||||||
[self setProgressBarStatus:progress];
|
progress = 0.0;
|
||||||
|
|
||||||
DLog(@"Expanded urls: %@", expandedURLs);
|
DLog(@"Expanded urls: %@", expandedURLs);
|
||||||
|
|
||||||
|
@ -326,7 +380,9 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
sortedURLs = expandedURLs;
|
sortedURLs = expandedURLs;
|
||||||
}
|
}
|
||||||
|
|
||||||
progressstep = [sortedURLs count] ? 20.0 / (double)([sortedURLs count]) : 0;
|
[self beginProgressJob:NSLocalizedString(@"ProgressSubActionLoaderFilteringContainerFiles", @"handling container file types") percentOfTotal:20.0];
|
||||||
|
|
||||||
|
progressstep = [sortedURLs count] ? 100.0 / (double)([sortedURLs count]) : 0;
|
||||||
|
|
||||||
for(url in sortedURLs) {
|
for(url in sortedURLs) {
|
||||||
// Container vs non-container url
|
// Container vs non-container url
|
||||||
|
@ -349,17 +405,23 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
}
|
}
|
||||||
|
|
||||||
progress += progressstep;
|
progress += progressstep;
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressJobStatus:progress];
|
||||||
}
|
}
|
||||||
|
|
||||||
progress = 40.0;
|
progress = 0.0;
|
||||||
[self setProgressBarStatus:progress];
|
[self completeProgressJob];
|
||||||
|
|
||||||
|
if([fileURLs count] > 0) {
|
||||||
|
[self beginProgressJob:NSLocalizedString(@"ProgressSubActionLoaderFilteringFiles", @"eliminating unsupported file types") percentOfTotal:20.0];
|
||||||
|
} else {
|
||||||
|
[self setProgressStatus:60.0];
|
||||||
|
}
|
||||||
|
|
||||||
DLog(@"File urls: %@", fileURLs);
|
DLog(@"File urls: %@", fileURLs);
|
||||||
|
|
||||||
DLog(@"Contained urls: %@", containedURLs);
|
DLog(@"Contained urls: %@", containedURLs);
|
||||||
|
|
||||||
progressstep = [fileURLs count] ? 20.0 / (double)([fileURLs count]) : 0;
|
progressstep = [fileURLs count] ? 100.0 / (double)([fileURLs count]) : 0;
|
||||||
|
|
||||||
for(url in fileURLs) {
|
for(url in fileURLs) {
|
||||||
progress += progressstep;
|
progress += progressstep;
|
||||||
|
@ -379,16 +441,24 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
[uniqueURLs addObject:url];
|
[uniqueURLs addObject:url];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressJobStatus:progress];
|
||||||
}
|
}
|
||||||
|
|
||||||
progress = 60.0;
|
progress = 0.0;
|
||||||
|
|
||||||
[self setProgressBarStatus:progress];
|
if([fileURLs count] > 0) {
|
||||||
|
[self completeProgressJob];
|
||||||
|
}
|
||||||
|
|
||||||
|
if([containedURLs count] > 0) {
|
||||||
|
[self beginProgressJob:NSLocalizedString(@"ProgressSubActionLoaderFilteringContainedFiles", @"eliminating unsupported file types from containers") percentOfTotal:20.0];
|
||||||
|
} else {
|
||||||
|
[self setProgressStatus:80.0];
|
||||||
|
}
|
||||||
|
|
||||||
DLog(@"Valid urls: %@", validURLs);
|
DLog(@"Valid urls: %@", validURLs);
|
||||||
|
|
||||||
progressstep = [containedURLs count] ? 20.0 / (double)([containedURLs count]) : 0;
|
progressstep = [containedURLs count] ? 100.0 / (double)([containedURLs count]) : 0;
|
||||||
|
|
||||||
for(url in containedURLs) {
|
for(url in containedURLs) {
|
||||||
progress += progressstep;
|
progress += progressstep;
|
||||||
|
@ -402,12 +472,13 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
[validURLs addObject:url];
|
[validURLs addObject:url];
|
||||||
|
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressJobStatus:progress];
|
||||||
}
|
}
|
||||||
|
|
||||||
progress = 80.0;
|
progress = 0.0;
|
||||||
|
if([containedURLs count] > 0) {
|
||||||
[self setProgressBarStatus:progress];
|
[self completeProgressJob];
|
||||||
|
}
|
||||||
|
|
||||||
// Create actual entries
|
// Create actual entries
|
||||||
int count = (int)[validURLs count];
|
int count = (int)[validURLs count];
|
||||||
|
@ -415,11 +486,13 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
// no valid URLs, or they use an unsupported URL scheme
|
// no valid URLs, or they use an unsupported URL scheme
|
||||||
if(!count) {
|
if(!count) {
|
||||||
[self setProgressBarStatus:-1];
|
[self completeProgress];
|
||||||
return @[];
|
return @[];
|
||||||
}
|
}
|
||||||
|
|
||||||
progressstep = 20.0 / (double)(count);
|
[self beginProgressJob:NSLocalizedString(@"ProgressSubActionLoaderAddingEntries", @"creating and adding playlist entries") percentOfTotal:20.0];
|
||||||
|
|
||||||
|
progressstep = 100.0 / (double)(count);
|
||||||
|
|
||||||
NSInteger i = 0;
|
NSInteger i = 0;
|
||||||
NSMutableArray *entries = [NSMutableArray arrayWithCapacity:count];
|
NSMutableArray *entries = [NSMutableArray arrayWithCapacity:count];
|
||||||
|
@ -436,7 +509,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
progress += progressstep;
|
progress += progressstep;
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressJobStatus:progress];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSInteger j = index + i;
|
NSInteger j = index + i;
|
||||||
|
@ -455,8 +528,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
progress = 100.0;
|
[self completeProgress];
|
||||||
[self setProgressBarStatus:progress];
|
|
||||||
|
|
||||||
NSIndexSet *is = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(index, [entries count])];
|
NSIndexSet *is = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(index, [entries count])];
|
||||||
|
|
||||||
|
@ -486,19 +558,21 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
NSMutableArray *arrayRest = [entries mutableCopy];
|
NSMutableArray *arrayRest = [entries mutableCopy];
|
||||||
[arrayRest removeObjectAtIndex:0];
|
[arrayRest removeObjectAtIndex:0];
|
||||||
|
|
||||||
progress = 0.0;
|
metadataLoadInProgress = YES;
|
||||||
[self setProgressBarStatus:progress];
|
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionLoadingMetadata", @"loading metadata for tracks")];
|
||||||
|
[self beginProgressJob:NSLocalizedString(@"ProgressSubActionLoadingMetadata", @"processing files") percentOfTotal:50.0];
|
||||||
|
|
||||||
[self performSelectorOnMainThread:@selector(syncLoadInfoForEntries:) withObject:arrayFirst waitUntilDone:YES];
|
[self performSelectorOnMainThread:@selector(syncLoadInfoForEntries:) withObject:arrayFirst waitUntilDone:YES];
|
||||||
|
|
||||||
progressstep = 100.0 / (double)([entries count]);
|
progressstep = 100.0 / (double)([entries count]);
|
||||||
progress += progressstep;
|
progress = progressstep;
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressJobStatus:progress];
|
||||||
|
|
||||||
if([arrayRest count])
|
if([arrayRest count])
|
||||||
[self performSelectorInBackground:@selector(loadInfoForEntries:) withObject:arrayRest];
|
[self performSelectorInBackground:@selector(loadInfoForEntries:) withObject:arrayRest];
|
||||||
else
|
else
|
||||||
[self setProgressBarStatus:-1];
|
[self completeProgress];
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,17 +584,20 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
SQLiteStore *store = [SQLiteStore sharedStore];
|
SQLiteStore *store = [SQLiteStore sharedStore];
|
||||||
|
|
||||||
__block double progress = [playbackController progressBarStatus];
|
__block double progress = 0.0;
|
||||||
|
|
||||||
if(progress < 0 || progress >= 100)
|
double progressstep;
|
||||||
progress = 0;
|
|
||||||
|
|
||||||
double progressRemaining = 100.0 - progress;
|
if(metadataLoadInProgress && [entries count]) {
|
||||||
|
progressstep = 100.0 / (double)([entries count] + 1);
|
||||||
|
progress = progressstep;
|
||||||
|
} else if([entries count]) {
|
||||||
|
[self beginProgress:NSLocalizedString(@"ProgressActionLoadingMetadata", @"loading metadata for tracks")];
|
||||||
|
[self beginProgressJob:NSLocalizedString(@"ProgressSubActionLoadingMetadata", @"processing files") percentOfTotal:50.0];
|
||||||
|
|
||||||
// 50% for properties reading, 50% for applying them to the main thread
|
progressstep = 100.0 / (double)([entries count]);
|
||||||
const double progressstep = [entries count] ? (progressRemaining / 2.0) / [entries count] : 0;
|
progress = 0.0;
|
||||||
|
}
|
||||||
progressRemaining = progress + (progressRemaining / 2.0);
|
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
j = 0;
|
j = 0;
|
||||||
|
@ -537,6 +614,8 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
if(!i) {
|
if(!i) {
|
||||||
[playlistController performSelectorOnMainThread:@selector(updateTotalTime) withObject:nil waitUntilDone:NO];
|
[playlistController performSelectorOnMainThread:@selector(updateTotalTime) withObject:nil waitUntilDone:NO];
|
||||||
|
[self completeProgress];
|
||||||
|
metadataLoadInProgress = NO;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,11 +634,13 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
NSBlockOperation *op = [[NSBlockOperation alloc] init];
|
NSBlockOperation *op = [[NSBlockOperation alloc] init];
|
||||||
|
|
||||||
[op addExecutionBlock:^{
|
[op addExecutionBlock:^{
|
||||||
[weakLock lock];
|
if(weakPe.deleted) {
|
||||||
progress += progressstep;
|
[weakLock lock];
|
||||||
[weakLock unlock];
|
progress += progressstep;
|
||||||
|
[self setProgressJobStatus:progress];
|
||||||
if(weakPe.deleted) return;
|
[weakLock unlock];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DLog(@"Loading metadata for %@", weakPe.URL);
|
DLog(@"Loading metadata for %@", weakPe.URL);
|
||||||
|
|
||||||
|
@ -575,7 +656,8 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
entryInfo = [weakDataStore coalesceEntryInfo:entryInfo];
|
entryInfo = [weakDataStore coalesceEntryInfo:entryInfo];
|
||||||
[weakArray addObject:weakPe];
|
[weakArray addObject:weakPe];
|
||||||
[weakArray addObject:entryInfo];
|
[weakArray addObject:entryInfo];
|
||||||
[self setProgressBarStatus:progress];
|
progress += progressstep;
|
||||||
|
[self setProgressJobStatus:progress];
|
||||||
[weakLock unlock];
|
[weakLock unlock];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
@ -585,8 +667,12 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
[queue waitUntilAllOperationsAreFinished];
|
[queue waitUntilAllOperationsAreFinished];
|
||||||
|
|
||||||
progress = progressRemaining;
|
progress = 0.0;
|
||||||
[self setProgressBarStatus:progress];
|
[self completeProgressJob];
|
||||||
|
|
||||||
|
[self beginProgressJob:NSLocalizedString(@"ProgressSubActionMetadataApply", @"applying info to playlist storage") percentOfTotal:50.0];
|
||||||
|
|
||||||
|
progressstep = 200.0 / (double)([outArray count]);
|
||||||
|
|
||||||
for(i = 0, j = [outArray count]; i < j; i += 2) {
|
for(i = 0, j = [outArray count]; i < j; i += 2) {
|
||||||
__block PlaylistEntry *weakPe = [outArray objectAtIndex:i];
|
__block PlaylistEntry *weakPe = [outArray objectAtIndex:i];
|
||||||
|
@ -597,7 +683,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
[store trackUpdate:weakPe];
|
[store trackUpdate:weakPe];
|
||||||
}
|
}
|
||||||
progress += progressstep;
|
progress += progressstep;
|
||||||
[self setProgressBarStatus:progress];
|
[self setProgressJobStatus:progress];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,8 +698,10 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[self setProgressBarStatus:-1];
|
[self completeProgress];
|
||||||
|
metadataLoadInProgress = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be called on main thread only
|
// To be called on main thread only
|
||||||
- (void)syncLoadInfoForEntries:(NSArray *)entries {
|
- (void)syncLoadInfoForEntries:(NSArray *)entries {
|
||||||
NSMutableIndexSet *update_indexes = [[NSMutableIndexSet alloc] init];
|
NSMutableIndexSet *update_indexes = [[NSMutableIndexSet alloc] init];
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// TotalTimeTransformer.h
|
||||||
|
// Cog
|
||||||
|
//
|
||||||
|
// Created by Christopher Snowhill on 6/15/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface TotalTimeTransformer : NSValueTransformer
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// TotalTimeTransformer.m
|
||||||
|
// Cog
|
||||||
|
//
|
||||||
|
// Created by Christopher Snowhill on 6/15/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "TotalTimeTransformer.h"
|
||||||
|
|
||||||
|
@implementation TotalTimeTransformer
|
||||||
|
|
||||||
|
+ (Class)transformedValueClass {
|
||||||
|
return [NSString class];
|
||||||
|
}
|
||||||
|
+ (BOOL)allowsReverseTransformation {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)transformedValue:(id)value {
|
||||||
|
if(value == nil) return @"";
|
||||||
|
|
||||||
|
if([value isKindOfClass:[NSString class]]) {
|
||||||
|
NSString *string = (NSString *)value;
|
||||||
|
if([string length] > 0) {
|
||||||
|
return [@"Total Duration: " stringByAppendingString:string];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -45,3 +45,21 @@
|
||||||
"CogTitle" = "Cog";
|
"CogTitle" = "Cog";
|
||||||
|
|
||||||
"PreferencesTitle" = "Preferences";
|
"PreferencesTitle" = "Preferences";
|
||||||
|
|
||||||
|
"ProgressActionUpdatingIndexes" = "updating playlist indexes";
|
||||||
|
"ProgressActionMovingEntries" = "moving playlist entries";
|
||||||
|
"ProgressActionInsertingEntries" = "inserting playlist entries";
|
||||||
|
"ProgressActionUntrashingEntries" = "restoring playlist entries from the trash";
|
||||||
|
"ProgressActionRemovingEntries" = "removing playlist entries";
|
||||||
|
"ProgressActionTrashingEntries" = "moving playlist entries to the trash";
|
||||||
|
|
||||||
|
"ProgressActionLoader" = "playlist loader inserting files";
|
||||||
|
"ProgressSubActionLoaderListingFiles" = "collecting files";
|
||||||
|
"ProgressSubActionLoaderFilteringContainerFiles" = "handling container file types";
|
||||||
|
"ProgressSubActionLoaderFilteringFiles" = "eliminating unsupported file types";
|
||||||
|
"ProgressSubActionLoaderFilteringContainedFiles" = "eliminating unsupported file types from containers";
|
||||||
|
"ProgressSubActionLoaderAddingEntries" = "creating and adding playlist entries";
|
||||||
|
|
||||||
|
"ProgressActionLoadingMetadata" = "loading metadata for tracks";
|
||||||
|
"ProgressSubActionLoadingMetadata" = "processing files";
|
||||||
|
"ProgressSubActionMetadataApply" = "applying info to playlist storage";
|
||||||
|
|
|
@ -45,3 +45,21 @@
|
||||||
"CogTitle" = "Cog";
|
"CogTitle" = "Cog";
|
||||||
|
|
||||||
"PreferencesTitle" = "Preferences";
|
"PreferencesTitle" = "Preferences";
|
||||||
|
|
||||||
|
"ProgressActionUpdatingIndexes" = "updating playlist indexes";
|
||||||
|
"ProgressActionMovingEntries" = "moving playlist entries";
|
||||||
|
"ProgressActionInsertingEntries" = "inserting playlist entries";
|
||||||
|
"ProgressActionUntrashingEntries" = "restoring playlist entries from the trash";
|
||||||
|
"ProgressActionRemovingEntries" = "removing playlist entries";
|
||||||
|
"ProgressActionTrashingEntries" = "moving playlist entries to the trash";
|
||||||
|
|
||||||
|
"ProgressActionLoader" = "playlist loader inserting files";
|
||||||
|
"ProgressSubActionLoaderListingFiles" = "collecting files";
|
||||||
|
"ProgressSubActionLoaderFilteringContainerFiles" = "handling container file types";
|
||||||
|
"ProgressSubActionLoaderFilteringFiles" = "eliminating unsupported file types";
|
||||||
|
"ProgressSubActionLoaderFilteringContainedFiles" = "eliminating unsupported file types from containers";
|
||||||
|
"ProgressSubActionLoaderAddingEntries" = "creating and adding playlist entries";
|
||||||
|
|
||||||
|
"ProgressActionLoadingMetadata" = "loading metadata for tracks";
|
||||||
|
"ProgressSubActionLoadingMetadata" = "processing files";
|
||||||
|
"ProgressSubActionMetadataApply" = "applying info to playlist storage";
|
||||||
|
|
Loading…
Reference in New Issue