Reformat my own source code with clang-format

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2022-02-06 21:49:27 -08:00
parent 361f61618a
commit 85c7073649
397 changed files with 2238946 additions and 210159 deletions

176
.clang-format Normal file
View file

@ -0,0 +1,176 @@
# The style used for all options not specifically set in the configuration.
BasedOnStyle: LLVM
# The extra indent or outdent of access modifiers, e.g. public:.
AccessModifierOffset: 0
# If true, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column.
AlignEscapedNewlinesLeft: false
# If true, aligns trailing comments.
AlignTrailingComments: false
# Allow putting all parameters of a function declaration onto the next line even if BinPackParameters is false.
AllowAllParametersOfDeclarationOnNextLine: false
# Allows contracting simple braced statements to a single line.
AllowShortBlocksOnASingleLine: true
# If true, short case labels will be contracted to a single line.
AllowShortCaseLabelsOnASingleLine: false
# Dependent on the value, int f() { return 0; } can be put on a single line. Possible values: None, Inline, All.
AllowShortFunctionsOnASingleLine: None
# If true, if (a) return; can be put on a single line.
AllowShortIfStatementsOnASingleLine: true
# If true, while (true) continue; can be put on a single line.
AllowShortLoopsOnASingleLine: true
# If true, always break after function definition return types. More truthfully called break before the identifier following the type in a function definition.
AlwaysBreakAfterDefinitionReturnType: false
# If true, always break before multiline string literals.
AlwaysBreakBeforeMultilineStrings: false
# If true, always break after the template<...> of a template declaration.
AlwaysBreakTemplateDeclarations: true
# If false, a function calls arguments will either be all on the same line or will have one line each.
#BinPackArguments: true
# If false, a function declarations or function definitions parameters will either all be on the same line or will have one line each.
BinPackParameters: true
# The way to wrap binary operators. Possible values: None, NonAssignment, All.
BreakBeforeBinaryOperators: None
# The brace breaking style to use. Possible values: Attach, Linux, Stroustrup, Allman, GNU.
BreakBeforeBraces: Attach
# If true, ternary operators will be placed after line breaks.
BreakBeforeTernaryOperators: false
# Always break constructor initializers before commas and align the commas with the colon.
BreakConstructorInitializersBeforeComma: false
# The column limit. A column limit of 0 means that there is no column limit.
ColumnLimit: 0
# A regular expression that describes comments with special meaning, which should not be split into lines or otherwise changed.
CommentPragmas: '^ IWYU pragma:'
# If the constructor initializers dont fit on a line, put each initializer on its own line.
ConstructorInitializerAllOnOneLineOrOnePerLine: false
# The number of characters to use for indentation of constructor initializer lists.
ConstructorInitializerIndentWidth: 0
# Indent width for line continuations.
ContinuationIndentWidth: 0
# If true, format braced lists as best suited for C++11 braced lists.
Cpp11BracedListStyle: false
# If true, analyze the formatted file for the most common alignment of & and *. PointerAlignment is then used only as fallback.
DerivePointerAlignment: true
# Disables formatting at all.
DisableFormat: false
# If true, clang-format detects whether function calls and definitions are formatted with one parameter per line.
ExperimentalAutoDetectBinPacking: false
# A vector of macros that should be interpreted as foreach loops instead of as function calls.
#ForEachMacros: ''
# Indent case labels one level from the switch statement. When false, use the same indentation level as for the switch statement. Switch statement body is always indented one level more than case labels.
IndentCaseLabels: true
# The number of columns to use for indentation.
IndentWidth: 4
# Indent if a function definition or declaration is wrapped after the type.
IndentWrappedFunctionNames: false
# If true, empty lines at the start of blocks are kept.
KeepEmptyLinesAtTheStartOfBlocks: false
# Language, this format style is targeted at. Possible values: None, Cpp, Java, JavaScript, Proto.
# Language: None
# The maximum number of consecutive empty lines to keep.
MaxEmptyLinesToKeep: 1
# The indentation used for namespaces. Possible values: None, Inner, All.
NamespaceIndentation: All
# The number of characters to use for indentation of ObjC blocks.
ObjCBlockIndentWidth: 4
# Add a space after @property in Objective-C, i.e. use \@property (readonly) instead of \@property(readonly).
ObjCSpaceAfterProperty: false
# Add a space in front of an Objective-C protocol list, i.e. use Foo <Protocol> instead of Foo<Protocol>.
ObjCSpaceBeforeProtocolList: true
# The penalty for breaking a function call after “call(”.
PenaltyBreakBeforeFirstCallParameter: 1000
# The penalty for each line break introduced inside a comment.
PenaltyBreakComment: 1000
# The penalty for breaking before the first <<.
PenaltyBreakFirstLessLess: 1000
# The penalty for each line break introduced inside a string literal.
PenaltyBreakString: 1000
# The penalty for each character outside of the column limit.
PenaltyExcessCharacter: 1000
# Penalty for putting the return type of a function onto its own line.
PenaltyReturnTypeOnItsOwnLine: 1000
# Pointer and reference alignment style. Possible values: Left, Right, Middle.
PointerAlignment: Left
# If true, a space may be inserted after C style casts.
SpaceAfterCStyleCast: false
# If false, spaces will be removed before assignment operators.
SpaceBeforeAssignmentOperators: true
# Defines in which cases to put a space before opening parentheses. Possible values: Never, ControlStatements, Always.
SpaceBeforeParens: Never
# If true, spaces may be inserted into ().
SpaceInEmptyParentheses: false
# The number of spaces before trailing line comments (// - comments).
SpacesBeforeTrailingComments: 1
# If true, spaces will be inserted after < and before > in template argument lists.
SpacesInAngles: false
# If true, spaces may be inserted into C style casts.
SpacesInCStyleCastParentheses: false
# If true, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals).
SpacesInContainerLiterals: false
# If true, spaces will be inserted after ( and before ).
SpacesInParentheses: false
# If true, spaces will be inserted after [ and before ].
SpacesInSquareBrackets: false
# Format compatible with this standard, e.g. use A<A<int> > instead of A<A<int>> for LS_Cpp03. Possible values: Cpp03, Cpp11, Auto.
Standard: Auto
# The number of columns used for tab stops.
TabWidth: 4
# The way to use tab characters in the resulting file. Possible values: Never, ForIndentation, Always.
UseTab: ForIndentation

View file

@ -9,8 +9,7 @@
@class PlaylistLoader;
@class SUUpdater;
@interface AppController : NSObject
{
@interface AppController : NSObject {
IBOutlet NSObjectController *currentEntryController;
IBOutlet PlaybackController *playbackController;
@ -56,8 +55,6 @@
NSMutableSet *expandedNodes;
BOOL miniMode;
}
@property(strong) IBOutlet NSButton *infoButton;

View file

@ -1,32 +1,31 @@
#import "AppController.h"
#import "Cog-Swift.h"
#import "FileTreeController.h"
#import "FileTreeViewController.h"
#import "FileTreeOutlineView.h"
#import "FileTreeViewController.h"
#import "FontSizetoLineHeightTransformer.h"
#import "OpenURLPanel.h"
#import "PathNode.h"
#import "PlaybackController.h"
#import "PlaylistController.h"
#import "PlaylistView.h"
#import "PlaylistEntry.h"
#import "PlaylistLoader.h"
#import "OpenURLPanel.h"
#import "PlaylistView.h"
#import "SpotlightWindowController.h"
#import "StringToURLTransformer.h"
#import "FontSizetoLineHeightTransformer.h"
#import "Cog-Swift.h"
#import "PathNode.h"
#import <CogAudio/Status.h>
#import "DualWindow.h"
#import "Logging.h"
#import "MiniModeMenuTitleTransformer.h"
#import "DualWindow.h"
#import <MASShortcut/Shortcut.h>
#import "Shortcuts.h"
#import <MASShortcut/Shortcut.h>
#import <Sparkle/Sparkle.h>
void *kAppControllerContext = &kAppControllerContext;
@implementation AppController {
BOOL _isFullToolbarStyle;
}
@ -34,8 +33,7 @@ void* kAppControllerContext = &kAppControllerContext;
@synthesize mainWindow;
@synthesize miniWindow;
+ (void)initialize
{
+ (void)initialize {
// Register transformers
NSValueTransformer *stringToURLTransformer = [[StringToURLTransformer alloc] init];
[NSValueTransformer setValueTransformer:stringToURLTransformer
@ -51,12 +49,9 @@ void* kAppControllerContext = &kAppControllerContext;
forName:@"MiniModeMenuTitleTransformer"];
}
- (id)init
{
- (id)init {
self = [super init];
if (self)
{
if(self) {
[self initDefaults];
queue = [[NSOperationQueue alloc] init];
@ -65,8 +60,7 @@ void* kAppControllerContext = &kAppControllerContext;
return self;
}
- (IBAction)openFiles:(id)sender
{
- (IBAction)openFiles:(id)sender {
NSOpenPanel *p;
p = [NSOpenPanel openPanel];
@ -76,7 +70,8 @@ void* kAppControllerContext = &kAppControllerContext;
[p setAllowsMultipleSelection:YES];
[p setResolvesAliases:YES];
[p beginSheetModalForWindow:mainWindow completionHandler:^(NSInteger result) {
[p beginSheetModalForWindow:mainWindow
completionHandler:^(NSInteger result) {
if(result == NSModalResponseOK) {
[self->playlistLoader willInsertURLs:[p URLs] origin:URLOriginInternal];
[self->playlistLoader didInsertURLs:[self->playlistLoader addURLs:[p URLs] sort:YES] origin:URLOriginInternal];
@ -86,8 +81,7 @@ void* kAppControllerContext = &kAppControllerContext;
}];
}
- (IBAction)savePlaylist:(id)sender
{
- (IBAction)savePlaylist:(id)sender {
NSSavePanel *p;
p = [NSSavePanel savePanel];
@ -97,7 +91,8 @@ void* kAppControllerContext = &kAppControllerContext;
* extension if the user does not supply one. */
[p setAllowedFileTypes:@[@"m3u", @"pls"]];
[p beginSheetModalForWindow:mainWindow completionHandler:^(NSInteger result) {
[p beginSheetModalForWindow:mainWindow
completionHandler:^(NSInteger result) {
if(result == NSModalResponseOK) {
[self->playlistLoader save:[[p URL] path]];
} else {
@ -106,8 +101,7 @@ void* kAppControllerContext = &kAppControllerContext;
}];
}
- (IBAction)openURL:(id)sender
{
- (IBAction)openURL:(id)sender {
OpenURLPanel *p;
p = [OpenURLPanel openURLPanel];
@ -115,32 +109,26 @@ void* kAppControllerContext = &kAppControllerContext;
[p beginSheetWithWindow:mainWindow delegate:self didEndSelector:@selector(openURLPanelDidEnd:returnCode:contextInfo:) contextInfo:nil];
}
- (void)openURLPanelDidEnd:(OpenURLPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
if (returnCode == NSModalResponseOK)
{
- (void)openURLPanelDidEnd:(OpenURLPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo {
if(returnCode == NSModalResponseOK) {
[playlistLoader willInsertURLs:@[[panel url]] origin:URLOriginInternal];
[playlistLoader didInsertURLs:[playlistLoader addURLs:@[[panel url]] sort:NO] origin:URLOriginInternal];
}
}
- (IBAction)delEntries:(id)sender
{
- (IBAction)delEntries:(id)sender {
[playlistController remove:self];
}
- (PlaylistEntry *)currentEntry
{
- (PlaylistEntry *)currentEntry {
return [playlistController currentEntry];
}
- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key
{
- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key {
return [key isEqualToString:@"currentEntry"] || [key isEqualToString:@"play"];
}
- (void)awakeFromNib
{
- (void)awakeFromNib {
#ifdef DEBUG
// Prevent updates automatically in debug builds
[updater setAutomaticallyChecksForUpdates:NO];
@ -168,28 +156,21 @@ void* kAppControllerContext = &kAppControllerContext;
NSString *oldFilename = @"Default.m3u";
NSString *newFilename = @"Default.xml";
if ([[NSFileManager defaultManager] fileExistsAtPath:[basePath stringByAppendingPathComponent:dbFilename]])
{
if([[NSFileManager defaultManager] fileExistsAtPath:[basePath stringByAppendingPathComponent:dbFilename]]) {
[playlistLoader addDatabase];
}
else if ([[NSFileManager defaultManager] fileExistsAtPath:[basePath stringByAppendingPathComponent:newFilename]])
{
} else if([[NSFileManager defaultManager] fileExistsAtPath:[basePath stringByAppendingPathComponent:newFilename]]) {
[playlistLoader addURL:[NSURL fileURLWithPath:[basePath stringByAppendingPathComponent:newFilename]]];
}
else
{
} else {
[playlistLoader addURL:[NSURL fileURLWithPath:[basePath stringByAppendingPathComponent:oldFilename]]];
}
[[playlistController undoManager] enableUndoRegistration];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"resumePlaybackOnStartup"])
{
if([[NSUserDefaults standardUserDefaults] boolForKey:@"resumePlaybackOnStartup"]) {
int lastStatus = (int)[[NSUserDefaults standardUserDefaults] integerForKey:@"lastPlaybackStatus"];
int lastIndex = (int)[[NSUserDefaults standardUserDefaults] integerForKey:@"lastTrackPlaying"];
if (lastStatus != CogStatusStopped && lastIndex >= 0)
{
if(lastStatus != CogStatusStopped && lastIndex >= 0) {
[playbackController playEntryAtIndex:lastIndex startPaused:(lastStatus == CogStatusPaused) andSeekTo:[NSNumber numberWithDouble:[[NSUserDefaults standardUserDefaults] floatForKey:@"lastTrackPosition"]]];
}
}
@ -221,12 +202,9 @@ void* kAppControllerContext = &kAppControllerContext;
NSArray *expandedNodesArray = [[NSUserDefaults standardUserDefaults] valueForKey:@"fileTreeViewExpandedNodes"];
if (expandedNodesArray)
{
if(expandedNodesArray) {
expandedNodes = [[NSMutableSet alloc] initWithArray:expandedNodesArray];
}
else
{
} else {
expandedNodes = [[NSMutableSet alloc] init];
}
@ -234,20 +212,17 @@ void* kAppControllerContext = &kAppControllerContext;
DLog(@"Num of rows: %ld", [outlineView numberOfRows]);
if (!outlineView)
{
if(!outlineView) {
DLog(@"outlineView is NULL!");
}
[outlineView reloadData];
for (NSInteger i=0; i<[outlineView numberOfRows]; i++)
{
for(NSInteger i = 0; i < [outlineView numberOfRows]; i++) {
PathNode *pn = [outlineView itemAtRow:i];
NSString *str = [[pn URL] absoluteString];
if ([expandedNodes containsObject:str])
{
if([expandedNodes containsObject:str]) {
[outlineView expandItem:pn];
}
}
@ -328,24 +303,21 @@ void* kAppControllerContext = &kAppControllerContext;
}
}
- (void)nodeExpanded:(NSNotification*)notification
{
- (void)nodeExpanded:(NSNotification *)notification {
PathNode *node = [[notification userInfo] objectForKey:@"NSObject"];
NSString *url = [[node URL] absoluteString];
[expandedNodes addObject:url];
}
- (void)nodeCollapsed:(NSNotification*)notification
{
- (void)nodeCollapsed:(NSNotification *)notification {
PathNode *node = [[notification userInfo] objectForKey:@"NSObject"];
NSString *url = [[node URL] absoluteString];
[expandedNodes removeObject:url];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
- (void)applicationWillTerminate:(NSNotification *)aNotification {
CogStatus currentStatus = [playbackController playbackStatus];
NSInteger lastTrackPlaying = -1;
double lastTrackPosition = 0;
@ -353,8 +325,7 @@ void* kAppControllerContext = &kAppControllerContext;
if(currentStatus == CogStatusStopping)
currentStatus = CogStatusStopped;
if (currentStatus != CogStatusStopped)
{
if(currentStatus != CogStatusStopped) {
PlaylistEntry *pe = [playlistController currentEntry];
lastTrackPlaying = [pe index];
lastTrackPosition = [pe currentPosition];
@ -371,8 +342,7 @@ void* kAppControllerContext = &kAppControllerContext;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *folder = [[paths firstObject] stringByAppendingPathComponent:@"Cog"];
if ([fileManager fileExistsAtPath: folder] == NO)
{
if([fileManager fileExistsAtPath:folder] == NO) {
[fileManager createDirectoryAtPath:folder withIntermediateDirectories:NO attributes:nil error:nil];
}
@ -395,8 +365,7 @@ void* kAppControllerContext = &kAppControllerContext;
[miniWindow saveFrameUsingName:@"Mini Window"];
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
{
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag {
if(flag == NO)
[mainWindow makeKeyAndOrderFront:self]; // TODO: do we really need this? We never close the main window.
@ -407,21 +376,18 @@ void* kAppControllerContext = &kAppControllerContext;
return NO;
}
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename {
NSArray *urls = @[[NSURL fileURLWithPath:filename]];
[playlistLoader willInsertURLs:urls origin:URLOriginExternal];
[playlistLoader didInsertURLs:[playlistLoader addURLs:urls sort:NO] origin:URLOriginExternal];
return YES;
}
- (void)application:(NSApplication *)theApplication openFiles:(NSArray *)filenames
{
- (void)application:(NSApplication *)theApplication openFiles:(NSArray *)filenames {
// Need to convert to urls
NSMutableArray *urls = [NSMutableArray array];
for (NSString *filename in filenames)
{
for(NSString *filename in filenames) {
[urls addObject:[NSURL fileURLWithPath:filename]];
}
[playlistLoader willInsertURLs:urls origin:URLOriginExternal];
@ -429,34 +395,30 @@ void* kAppControllerContext = &kAppControllerContext;
[theApplication replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
}
- (IBAction)openLiberapayPage:(id)sender
{
- (IBAction)openLiberapayPage:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://liberapay.com/kode54"]];
}
- (IBAction)openPaypalPage:(id)sender
{
- (IBAction)openPaypalPage:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.paypal.com/paypalme/kode54"]];
}
- (IBAction)openKofiPage:(id)sender
{
- (IBAction)openKofiPage:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://ko-fi.com/kode54"]];
}
- (IBAction)openPatreonPage:(id)sender
{
- (IBAction)openPatreonPage:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.patreon.com/kode54"]];
}
- (IBAction)feedback:(id)sender
{
- (IBAction)feedback:(id)sender {
NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
NSArray<NSURLQueryItem *> *query = @[
[NSURLQueryItem queryItemWithName:@"labels" value:@"bug"],
[NSURLQueryItem queryItemWithName:@"template" value:@"bug_report.md"],
[NSURLQueryItem queryItemWithName:@"labels"
value:@"bug"],
[NSURLQueryItem queryItemWithName:@"template"
value:@"bug_report.md"],
[NSURLQueryItem queryItemWithName:@"title"
value:[NSString stringWithFormat:@"[Cog %@] ", version]]
];
@ -468,8 +430,7 @@ void* kAppControllerContext = &kAppControllerContext;
[[NSWorkspace sharedWorkspace] openURL:components.URL];
}
- (void)initDefaults
{
- (void)initDefaults {
NSMutableDictionary *userDefaultsValuesDict = [NSMutableDictionary dictionary];
// Font defaults
@ -525,92 +486,81 @@ void* kAppControllerContext = &kAppControllerContext;
}
/* Unassign previous handler first, so dealloc can unregister it from the global map before the new instances are assigned */
- (void)registerHotKeys
{
- (void)registerHotKeys {
MASShortcutBinder *binder = [MASShortcutBinder sharedBinder];
[binder bindShortcutWithDefaultsKey:CogPlayShortcutKey toAction:^{
[binder bindShortcutWithDefaultsKey:CogPlayShortcutKey
toAction:^{
[self clickPlay];
}];
[binder bindShortcutWithDefaultsKey:CogNextShortcutKey toAction:^{
[binder bindShortcutWithDefaultsKey:CogNextShortcutKey
toAction:^{
[self clickNext];
}];
[binder bindShortcutWithDefaultsKey:CogPrevShortcutKey toAction:^{
[binder bindShortcutWithDefaultsKey:CogPrevShortcutKey
toAction:^{
[self clickPrev];
}];
[binder bindShortcutWithDefaultsKey:CogSpamShortcutKey toAction:^{
[binder bindShortcutWithDefaultsKey:CogSpamShortcutKey
toAction:^{
[self clickSpam];
}];
}
- (void)clickPlay
{
- (void)clickPlay {
[playbackController playPauseResume:self];
}
- (void)clickPause
{
- (void)clickPause {
[playbackController pause:self];
}
- (void)clickStop
{
- (void)clickStop {
[playbackController stop:self];
}
- (void)clickPrev
{
- (void)clickPrev {
[playbackController prev:nil];
}
- (void)clickNext
{
- (void)clickNext {
[playbackController next:nil];
}
- (void)clickSpam
{
- (void)clickSpam {
[playbackController spam:nil];
}
- (void)clickSeek:(NSTimeInterval)position
{
- (void)clickSeek:(NSTimeInterval)position {
[playbackController seek:self toTime:position];
}
- (void)changeFontSize:(float)size
{
- (void)changeFontSize:(float)size {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
float fCurrentSize = [defaults floatForKey:@"fontSize"];
NSNumber *newSize = [NSNumber numberWithFloat:(fCurrentSize + size)];
[defaults setObject:newSize forKey:@"fontSize"];
}
- (IBAction)increaseFontSize:(id)sender
{
- (IBAction)increaseFontSize:(id)sender {
[self changeFontSize:1];
}
- (IBAction)decreaseFontSize:(id)sender
{
- (IBAction)decreaseFontSize:(id)sender {
[self changeFontSize:-1];
}
- (IBAction)toggleMiniMode:(id)sender
{
- (IBAction)toggleMiniMode:(id)sender {
[self setMiniMode:(!miniMode)];
}
- (BOOL)miniMode
{
- (BOOL)miniMode {
return miniMode;
}
- (void)setMiniMode:(BOOL)newMiniMode
{
- (void)setMiniMode:(BOOL)newMiniMode {
miniMode = newMiniMode;
[[NSUserDefaults standardUserDefaults] setBool:miniMode forKey:@"miniMode"];
@ -651,8 +601,7 @@ void* kAppControllerContext = &kAppControllerContext;
[miniWindow setLevel:level];
}
- (void)updateDockMenu:(NSNotification *)notification
{
- (void)updateDockMenu:(NSNotification *)notification {
PlaylistEntry *pe = [playlistController currentEntry];
BOOL hideItem = NO;
@ -662,8 +611,7 @@ void* kAppControllerContext = &kAppControllerContext;
if(hideItem && [dockMenu indexOfItem:currentArtistItem] == 0) {
[dockMenu removeItem:currentArtistItem];
}
else if (!hideItem && [dockMenu indexOfItem:currentArtistItem] < 0) {
} else if(!hideItem && [dockMenu indexOfItem:currentArtistItem] < 0) {
[dockMenu insertItem:currentArtistItem atIndex:0];
}
}

View file

@ -7,57 +7,48 @@
//
#import "DockIconController.h"
#import <CogAudio/Status.h>
#import "PlaybackController.h"
#import <CogAudio/Status.h>
@implementation DockIconController
static NSString *DockIconPlaybackStatusObservationContext = @"DockIconPlaybackStatusObservationContext";
- (void)startObserving
{
- (void)startObserving {
[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)];
[[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:@"progressBarStatus"];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.colorfulDockIcons"];
}
static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons)
{
if (colorfulIcons)
{
static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons) {
if(colorfulIcons) {
return [baseName stringByAppendingString:@"Colorful"];
}
else
{
} else {
return baseName;
}
}
- (void)refreshDockIcon:(NSInteger)playbackStatus withProgress:(double)progressStatus
{
- (void)refreshDockIcon:(NSInteger)playbackStatus withProgress:(double)progressStatus {
BOOL displayChanged = NO;
BOOL drawIcon = NO;
BOOL removeProgress = NO;
if(playbackStatus < 0)
playbackStatus = lastPlaybackStatus;
else
{
else {
lastPlaybackStatus = playbackStatus;
drawIcon = YES;
}
if(progressStatus < -2)
progressStatus = [lastProgressStatus doubleValue];
else
{
else {
if(progressStatus < 0 && [lastProgressStatus doubleValue] >= 0)
removeProgress = YES;
lastProgressStatus = [NSNumber numberWithDouble:progressStatus];
@ -70,16 +61,14 @@ static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons)
BOOL colorfulIcons = [[NSUserDefaults standardUserDefaults] boolForKey:@"colorfulDockIcons"];
if((colorfulIcons && lastColorfulStatus < 1) ||
(!colorfulIcons && lastColorfulStatus != 0))
{
(!colorfulIcons && lastColorfulStatus != 0)) {
lastColorfulStatus = colorfulIcons ? 1 : 0;
drawIcon = YES;
}
NSDockTile *dockTile = [NSApp dockTile];
if (drawIcon)
{
if(drawIcon) {
switch(playbackStatus) {
case CogStatusPlaying:
badgeImage = [NSImage imageNamed:getBadgeName(@"playDockBadge", colorfulIcons)];
@ -100,7 +89,8 @@ static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons)
[badgeImage drawInRect:NSMakeRect(0, 0, 128, 128)
fromRect:NSMakeRect(0, 0, badgeSize.width, badgeSize.height)
operation:NSCompositingOperationSourceOver fraction:1.0];
operation:NSCompositingOperationSourceOver
fraction:1.0];
[newDockImage unlockFocus];
@ -121,17 +111,14 @@ static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons)
displayChanged = YES;
}
if (displayProgress)
{
if (!imageView)
{
if(displayProgress) {
if(!imageView) {
imageView = [[NSImageView alloc] init];
[imageView setImage:[NSApp applicationIconImage]];
[dockTile setContentView:imageView];
}
if (!progressIndicator)
{
if(!progressIndicator) {
progressIndicator = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(0.0, 0.0, dockTile.size.width, 10.0)];
[progressIndicator setIndeterminate:NO];
[progressIndicator setBezeled:YES];
@ -147,8 +134,7 @@ static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons)
displayChanged = YES;
}
if (removeProgress)
{
if(removeProgress) {
if(progressIndicator)
[progressIndicator setHidden:YES];
@ -159,35 +145,25 @@ static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons)
[dockTile display];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([DockIconPlaybackStatusObservationContext isEqual:(__bridge id)(context)])
{
if ([keyPath isEqualToString:@"playbackStatus"])
{
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([DockIconPlaybackStatusObservationContext isEqual:(__bridge id)(context)]) {
if([keyPath isEqualToString:@"playbackStatus"]) {
NSInteger playbackStatus = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
[self refreshDockIcon:playbackStatus withProgress:-10];
}
else if ([keyPath isEqualToString:@"progressBarStatus"])
{
} else if([keyPath isEqualToString:@"progressBarStatus"]) {
double progressStatus = [[change objectForKey:NSKeyValueChangeNewKey] doubleValue];
[self refreshDockIcon:-1 withProgress:progressStatus];
}
else if ([keyPath isEqualToString:@"values.colorfulDockIcons"])
{
} else if([keyPath isEqualToString:@"values.colorfulDockIcons"]) {
[self refreshDockIcon:-1 withProgress:-10];
}
}
else
{
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)awakeFromNib
{
- (void)awakeFromNib {
dockImage = [[NSImage imageNamed:@"icon_blank"] copy];
lastColorfulStatus = -1;
lastProgressStatus = [NSNumber numberWithDouble:-1];
@ -196,8 +172,7 @@ static NSString *getBadgeName(NSString *baseName, BOOL colorfulIcons)
[self startObserving];
}
- (void)dealloc
{
- (void)dealloc {
[self stopObserving];
}

View file

@ -11,4 +11,3 @@
@interface MediaKeysApplication : NSApplication
@end

View file

@ -10,10 +10,10 @@
#import "AppController.h"
#import "Logging.h"
#import <MediaPlayer/MPNowPlayingInfoCenter.h>
#import <MediaPlayer/MPRemoteCommandCenter.h>
#import <MediaPlayer/MPRemoteCommand.h>
#import <MediaPlayer/MPMediaItem.h>
#import <MediaPlayer/MPNowPlayingInfoCenter.h>
#import <MediaPlayer/MPRemoteCommand.h>
#import <MediaPlayer/MPRemoteCommandCenter.h>
#import <MediaPlayer/MPRemoteCommandEvent.h>
@implementation MediaKeysApplication {
@ -73,5 +73,4 @@
return MPRemoteCommandHandlerStatusSuccess;
}
@end

View file

@ -2,15 +2,15 @@
#import <Cocoa/Cocoa.h>
#import "AppController.h"
#import "AudioScrobbler.h"
#import "CogAudio/AudioPlayer.h"
#import "CogAudio/Status.h"
#import "TrackingSlider.h"
#import "AudioScrobbler.h"
#import "AppController.h"
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>
#import "AUPlayerView.h"
@ -29,8 +29,7 @@ extern NSDictionary * makeRGInfo(PlaylistEntry *pe);
@class PlaylistView;
@class PlaylistLoader;
@interface PlaybackController : NSObject
{
@interface PlaybackController : NSObject {
IBOutlet AppController *appController;
IBOutlet PlaylistController *playlistController;

View file

@ -1,8 +1,8 @@
#import "PlaybackController.h"
#import "CogAudio/Helper.h"
#import "CogAudio/Status.h"
#import "PlaylistView.h"
#import <Foundation/NSTimer.h>
#import "CogAudio/Status.h"
#import "CogAudio/Helper.h"
#import "PlaylistController.h"
#import "PlaylistEntry.h"
@ -11,10 +11,10 @@
#import "MainWindow.h"
#import "MiniWindow.h"
#import <MediaPlayer/MPNowPlayingInfoCenter.h>
#import <MediaPlayer/MPRemoteCommandCenter.h>
#import <MediaPlayer/MPRemoteCommand.h>
#import <MediaPlayer/MPMediaItem.h>
#import <MediaPlayer/MPNowPlayingInfoCenter.h>
#import <MediaPlayer/MPRemoteCommand.h>
#import <MediaPlayer/MPRemoteCommandCenter.h>
#import <MediaPlayer/MPRemoteCommandEvent.h>
#import "Logging.h"
@ -32,16 +32,13 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
@synthesize progressBarStatus;
+ (NSSet *)keyPathsForValuesAffectingSeekable
{
+ (NSSet *)keyPathsForValuesAffectingSeekable {
return [NSSet setWithObjects:@"playlistController.currentEntry", @"playlistController.currentEntry.seekable", nil];
}
- (id)init
{
- (id)init {
self = [super init];
if (self)
{
if(self) {
[self initDefaults];
seekable = NO;
@ -59,8 +56,7 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
return self;
}
- (void)initDefaults
{
- (void)initDefaults {
NSDictionary *defaultsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:100.0], @"volume",
[NSNumber numberWithBool:NO], @"GraphicEQenable",
@ -73,10 +69,7 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDictionary];
}
- (void)awakeFromNib
{
- (void)awakeFromNib {
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
@ -88,30 +81,24 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
[self setSeekable:NO];
}
- (IBAction)playPauseResume:(id)sender
{
if (playbackStatus == CogStatusStopped || playbackStatus == CogStatusStopping)
{
- (IBAction)playPauseResume:(id)sender {
if(playbackStatus == CogStatusStopped || playbackStatus == CogStatusStopping) {
[self play:self];
}
else
{
} else {
[self pauseResume:self];
}
[self sendMetaData];
}
- (IBAction)pauseResume:(id)sender
{
- (IBAction)pauseResume:(id)sender {
if(playbackStatus == CogStatusPaused)
[self resume:self];
else
[self pause:self];
}
- (IBAction)pause:(id)sender
{
- (IBAction)pause:(id)sender {
[[NSUserDefaults standardUserDefaults] setInteger:CogStatusPaused forKey:@"lastPlaybackStatus"];
[audioPlayer pause];
@ -120,16 +107,13 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
[self sendMetaData];
}
- (IBAction)resume:(id)sender
{
- (IBAction)resume:(id)sender {
[[NSUserDefaults standardUserDefaults] setInteger:CogStatusPlaying forKey:@"lastPlaybackStatus"];
[audioPlayer resume];
}
- (IBAction)stop:(id)sender
{
- (IBAction)stop:(id)sender {
[[NSUserDefaults standardUserDefaults] setInteger:CogStatusStopped forKey:@"lastPlaybackStatus"];
[self audioPlayer:audioPlayer removeEqualizer:_eq];
@ -142,28 +126,23 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
}
// called by double-clicking on table
- (void)playEntryAtIndex:(NSInteger)i
{
- (void)playEntryAtIndex:(NSInteger)i {
[self playEntryAtIndex:i startPaused:NO andSeekTo:[NSNumber numberWithDouble:0.0]];
}
- (void)playEntryAtIndex:(NSInteger)i startPaused:(BOOL)paused
{
- (void)playEntryAtIndex:(NSInteger)i startPaused:(BOOL)paused {
PlaylistEntry *pe = [playlistController entryAtIndex:i];
[self playEntry:pe startPaused:paused andSeekTo:[NSNumber numberWithDouble:0.0]];
}
- (void)playEntryAtIndex:(NSInteger)i startPaused:(BOOL)paused andSeekTo:(id)offset
{
- (void)playEntryAtIndex:(NSInteger)i startPaused:(BOOL)paused andSeekTo:(id)offset {
PlaylistEntry *pe = [playlistController entryAtIndex:i];
[self playEntry:pe startPaused:paused andSeekTo:offset];
}
- (IBAction)play:(id)sender
{
- (IBAction)play:(id)sender {
if([playlistView selectedRow] == -1)
[playlistView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
@ -171,8 +150,7 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
[self playEntryAtIndex:(int)[playlistView selectedRow]];
}
NSDictionary * makeRGInfo(PlaylistEntry *pe)
{
NSDictionary *makeRGInfo(PlaylistEntry *pe) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
if([pe replayGainAlbumGain] != 0)
[dictionary setObject:[NSNumber numberWithFloat:[pe replayGainAlbumGain]] forKey:@"replayGainAlbumGain"];
@ -187,18 +165,15 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
return dictionary;
}
- (void)playEntry:(PlaylistEntry *)pe
{
- (void)playEntry:(PlaylistEntry *)pe {
[self playEntry:pe startPaused:NO andSeekTo:[NSNumber numberWithDouble:0.0]];
}
- (void)playEntry:(PlaylistEntry *)pe startPaused:(BOOL)paused
{
- (void)playEntry:(PlaylistEntry *)pe startPaused:(BOOL)paused {
[self playEntry:pe startPaused:paused andSeekTo:[NSNumber numberWithDouble:0.0]];
}
- (void)playEntry:(PlaylistEntry *)pe startPaused:(BOOL)paused andSeekTo:(id)offset
{
- (void)playEntry:(PlaylistEntry *)pe startPaused:(BOOL)paused andSeekTo:(id)offset {
if(playbackStatus != CogStatusStopped && playbackStatus != CogStatusStopping)
[self stop:self];
@ -242,24 +217,21 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[audioPlayer play:[pe URL] withUserInfo:pe withRGInfo:makeRGInfo(pe) startPaused:paused andSeekTo:[offset doubleValue]];
}
- (IBAction)next:(id)sender
{
- (IBAction)next:(id)sender {
if([playlistController next] == NO)
return;
[self playEntry:[playlistController currentEntry]];
}
- (IBAction)prev:(id)sender
{
- (IBAction)prev:(id)sender {
if([playlistController prev] == NO)
return;
[self playEntry:[playlistController currentEntry]];
}
- (void)updatePosition:(id)sender
{
- (void)updatePosition:(id)sender {
double pos = [audioPlayer amountPlayed];
[self setPosition:pos];
@ -267,8 +239,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[[playlistController currentEntry] setCurrentPosition:pos];
}
- (IBAction)seek:(id)sender
{
- (IBAction)seek:(id)sender {
double time = [sender doubleValue];
[audioPlayer seekToTime:time];
@ -280,8 +251,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[[playlistController currentEntry] setCurrentPosition:time];
}
- (IBAction)seek:(id)sender toTime:(NSTimeInterval)position
{
- (IBAction)seek:(id)sender toTime:(NSTimeInterval)position {
double time = (double)(position);
lastPosition = -10;
@ -293,8 +263,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[[playlistController currentEntry] setCurrentPosition:time];
}
- (IBAction)spam:(id)sender
{
- (IBAction)spam:(id)sender {
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
[pboard clearContents];
@ -302,34 +271,27 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[pboard writeObjects:@[[[playlistController currentEntry] spam]]];
}
- (IBAction)eventSeekForward:(id)sender
{
- (IBAction)eventSeekForward:(id)sender {
[self seekForward:DEFAULT_SEEK];
}
- (void)seekForward:(double)amount
{
- (void)seekForward:(double)amount {
double seekTo = [audioPlayer amountPlayed] + amount;
if (seekTo > [[[playlistController currentEntry] length] doubleValue])
{
if(seekTo > [[[playlistController currentEntry] length] doubleValue]) {
[self next:self];
}
else
{
} else {
lastPosition = -10;
[audioPlayer seekToTime:seekTo];
[self setPosition:seekTo];
}
}
- (IBAction)eventSeekBackward:(id)sender
{
- (IBAction)eventSeekBackward:(id)sender {
[self seekBackward:DEFAULT_SEEK];
}
- (void)seekBackward:(double)amount
{
- (void)seekBackward:(double)amount {
double seekTo = [audioPlayer amountPlayed] - amount;
if(seekTo < 0)
@ -355,8 +317,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[playbackButtons setImage:img forSegment:1];
}
*/
- (IBAction)changeVolume:(id)sender
{
- (IBAction)changeVolume:(id)sender {
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
@ -370,8 +331,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
/* selector for NSTimer - gets passed the Timer object itself
and the appropriate userInfo, which in this case is an NSNumber
containing the current volume before we start fading. */
- (void)audioFadeDown:(NSTimer *)audioTimer
{
- (void)audioFadeDown:(NSTimer *)audioTimer {
double volume = [audioPlayer volume];
double originalVolume = [[audioTimer userInfo] doubleValue];
double down = originalVolume / 10;
@ -381,8 +341,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
if(volume > 0.0001) // YAY! Roundoff error!
{
[audioPlayer volumeDown:down];
}
else // volume is at 0 or below, we are ready to release the timer and move on
} else // volume is at 0 or below, we are ready to release the timer and move on
{
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
@ -394,25 +353,21 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
fading = NO;
}
}
- (void)audioFadeUp:(NSTimer *)audioTimer
{
- (void)audioFadeUp:(NSTimer *)audioTimer {
double volume = [audioPlayer volume];
double originalVolume = [[audioTimer userInfo] doubleValue];
double up = originalVolume / 10;
DLog(@"VOLUME IS %lf", volume);
if (originalVolume - volume > 0.0001)
{
if(originalVolume - volume > 0.0001) {
if((volume + up) > originalVolume)
[audioPlayer volumeUp:(originalVolume - volume)];
else
[audioPlayer volumeUp:up];
}
else // volume is at or near original level, we are ready to release the timer and move on
} else // volume is at or near original level, we are ready to release the timer and move on
{
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
@ -423,11 +378,9 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
fading = NO;
}
}
- (IBAction)fade:(id)sender
{
- (IBAction)fade:(id)sender {
double time = 0.1;
// we can not allow multiple fade timers to be registered
@ -445,9 +398,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
userInfo:originalVolume
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:fadeTimer forMode:NSRunLoopCommonModes];
}
else
{
} else {
[audioPlayer setVolume:0];
fadeTimer = [NSTimer timerWithTimeInterval:time
target:self
@ -459,8 +410,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
}
}
- (IBAction)skipToNextAlbum:(id)sender
{
- (IBAction)skipToNextAlbum:(id)sender {
BOOL found = NO;
NSInteger index = [[playlistController currentEntry] index];
@ -471,8 +421,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
PlaylistEntry *pe;
for (i = 1; i < [[playlistController arrangedObjects] count]; i++)
{
for(i = 1; i < [[playlistController arrangedObjects] count]; i++) {
pe = [playlistController entryAtIndex:index + i];
if(pe == nil)
break;
@ -481,27 +430,23 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
// check for untagged files, and just play the first untagged one
// we come across
if (curAlbum == nil)
{
if(curAlbum == nil) {
found = YES;
break;
}
if ([curAlbum caseInsensitiveCompare:origAlbum] != NSOrderedSame)
{
if([curAlbum caseInsensitiveCompare:origAlbum] != NSOrderedSame) {
found = YES;
break;
}
}
if (found)
{
if(found) {
[self playEntryAtIndex:i + index];
}
}
- (IBAction)skipToPreviousAlbum:(id)sender
{
- (IBAction)skipToPreviousAlbum:(id)sender {
BOOL found = NO;
BOOL foundAlbum = NO;
@ -513,48 +458,39 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
PlaylistEntry *pe;
for (i = 1; i < [[playlistController arrangedObjects] count]; i++)
{
for(i = 1; i < [[playlistController arrangedObjects] count]; i++) {
pe = [playlistController entryAtIndex:index - i];
if(pe == nil)
break;
curAlbum = [pe album];
if (curAlbum == nil)
{
if(curAlbum == nil) {
found = YES;
break;
}
if ([curAlbum caseInsensitiveCompare:origAlbum] != NSOrderedSame)
{
if (foundAlbum == NO)
{
if([curAlbum caseInsensitiveCompare:origAlbum] != NSOrderedSame) {
if(foundAlbum == NO) {
foundAlbum = YES;
// now we need to move up to the first song in the album, so we'll
// go till we either find index 0, or the first song in the album
origAlbum = curAlbum;
continue;
}
else
{
} else {
found = YES; // terminate loop
break;
}
}
}
if (found || foundAlbum)
{
if(found || foundAlbum) {
if(foundAlbum == YES)
i--;
[self playEntryAtIndex:index - i];
}
}
- (IBAction)volumeDown:(id)sender
{
- (IBAction)volumeDown:(id)sender {
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
@ -562,11 +498,9 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[volumeSlider setDoubleValue:logarithmicToLinear(newVolume, MAX_VOLUME)];
[[NSUserDefaults standardUserDefaults] setDouble:[audioPlayer volume] forKey:@"volume"];
}
- (IBAction)volumeUp:(id)sender
{
- (IBAction)volumeUp:(id)sender {
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
@ -577,8 +511,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[[NSUserDefaults standardUserDefaults] setDouble:[audioPlayer volume] forKey:@"volume"];
}
- (void)eqAlloc
{
- (void)eqAlloc {
// Show a stopped equalizer as a stub
OSStatus err;
AudioComponentDescription desc;
@ -605,25 +538,20 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
AudioUnitInitialize(_eq);
}
- (void)eqDealloc
{
- (void)eqDealloc {
AudioUnitUninitialize(_eq);
AudioComponentInstanceDispose(_eq);
_eq = nil;
_eqStubbed = NO;
}
- (IBAction)showEq:(id)sender
{
if (_eq)
{
- (IBAction)showEq:(id)sender {
if(_eq) {
if(_equi && [_equi isOpen])
[_equi bringToFront];
else
_equi = [[AUPluginUI alloc] initWithSampler:_eq bringToFront:YES orWindowNumber:0];
}
else
{
} else {
[self eqAlloc];
_eqWasOpen = YES;
[self audioPlayer:nil displayEqualizer:_eq];
@ -631,10 +559,8 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
}
}
- (void)audioPlayer:(AudioPlayer *)player displayEqualizer:(AudioUnit)eq
{
if (_equi)
{
- (void)audioPlayer:(AudioPlayer *)player displayEqualizer:(AudioUnit)eq {
if(_equi) {
_eqWasOpen = [_equi isOpen];
_equi = nil;
}
@ -646,8 +572,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
size = sizeof(classData);
err = AudioUnitGetProperty(_eq, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &classData, &size);
if (err == noErr)
{
if(err == noErr) {
CFPreferencesSetAppValue(CFSTR("GraphEQ_Preset"), classData, kCFPreferencesCurrentApplication);
CFRelease(classData);
}
@ -668,8 +593,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
CFNumberRef cfnum;
classData = CFPreferencesCopyAppValue(CFSTR("GraphEQ_Preset"), kCFPreferencesCurrentApplication);
if (classData)
{
if(classData) {
dict = (CFDictionaryRef)classData;
cfnum = (CFNumberRef)(CFDictionaryGetValue(dict, CFSTR("type")));
@ -690,61 +614,52 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
equalizerLoadPreset(eq);
}
if (_eqWasOpen)
{
if(_eqWasOpen) {
NSWindow *window = appController.miniMode ? appController.miniWindow : appController.mainWindow;
_equi = [[AUPluginUI alloc] initWithSampler:_eq bringToFront:NO orWindowNumber:window.windowNumber];
_eqWasOpen = NO;
}
}
- (void)audioPlayer:(AudioPlayer *)player refreshEqualizer:(AudioUnit)eq
{
- (void)audioPlayer:(AudioPlayer *)player refreshEqualizer:(AudioUnit)eq {
equalizerLoadPreset(eq);
}
- (void)audioPlayer:(AudioPlayer *)player removeEqualizer:(AudioUnit)eq
{
if (eq == _eq)
{
- (void)audioPlayer:(AudioPlayer *)player removeEqualizer:(AudioUnit)eq {
if(eq == _eq) {
OSStatus err;
CFPropertyListRef classData;
UInt32 size;
size = sizeof(classData);
err = AudioUnitGetProperty(eq, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &classData, &size);
if (err == noErr)
{
if(err == noErr) {
CFPreferencesSetAppValue(CFSTR("GraphEQ_Preset"), classData, kCFPreferencesCurrentApplication);
CFRelease(classData);
}
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
if (_equi)
{
if(_equi) {
_eqWasOpen = [_equi isOpen];
}
_equi = nil;
[self eqDealloc];
if (_eqWasOpen)
{
if(_eqWasOpen) {
[self showEq:nil];
}
}
}
- (void)audioPlayer:(AudioPlayer *)player willEndStream:(id)userInfo
{
- (void)audioPlayer:(AudioPlayer *)player willEndStream:(id)userInfo {
PlaylistEntry *curEntry = (PlaylistEntry *)userInfo;
PlaylistEntry *pe;
if(curEntry.stopAfter)
pe = nil;
else
{
else {
pe = [playlistController getNextEntry:curEntry];
if(pe && [pe metadataLoaded] != YES) {
NSArray *entries = @[pe];
@ -758,8 +673,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[player setNextStream:nil];
}
- (void)audioPlayer:(AudioPlayer *)player didBeginStream:(id)userInfo
{
- (void)audioPlayer:(AudioPlayer *)player didBeginStream:(id)userInfo {
PlaylistEntry *pe = (PlaylistEntry *)userInfo;
[playlistController setCurrentEntry:pe];
@ -776,32 +690,25 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[[NSNotificationCenter defaultCenter] postNotificationName:CogPlaybackDidBeginNotficiation object:pe];
}
- (void)audioPlayer:(AudioPlayer *)player didChangeStatus:(NSNumber *)s userInfo:(id)userInfo
{
- (void)audioPlayer:(AudioPlayer *)player didChangeStatus:(NSNumber *)s userInfo:(id)userInfo {
int status = [s intValue];
if (status == CogStatusStopped || status == CogStatusPaused)
{
if(status == CogStatusStopped || status == CogStatusPaused) {
[self removeHDCD:nil];
if (positionTimer)
{
if(positionTimer) {
[positionTimer invalidate];
positionTimer = NULL;
}
if (status == CogStatusStopped)
{
if(status == CogStatusStopped) {
[self setPosition:0];
[self setSeekable:NO]; // the player stopped, disable the slider
[[NSNotificationCenter defaultCenter] postNotificationName:CogPlaybackDidStopNotficiation object:nil];
}
else // paused
} else // paused
{
[[NSNotificationCenter defaultCenter] postNotificationName:CogPlaybackDidPauseNotficiation object:nil];
}
}
else if (status == CogStatusPlaying)
{
} else if(status == CogStatusPlaying) {
if(!positionTimer) {
positionTimer = [NSTimer timerWithTimeInterval:0.2 target:self selector:@selector(updatePosition:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:positionTimer forMode:NSRunLoopCommonModes];
@ -813,8 +720,7 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
if(status == CogStatusStopped) {
[playlistController setCurrentEntry:nil];
[self setSeekable:NO]; // the player stopped, disable the slider
}
else {
} else {
[self setSeekable:YES];
}
switch(status) {
@ -843,31 +749,26 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[self sendMetaData];
}
- (void)audioPlayer:(AudioPlayer *)player sustainHDCD:(id)userInfo
{
- (void)audioPlayer:(AudioPlayer *)player sustainHDCD:(id)userInfo {
MainWindow *mainWindow = (MainWindow *)appController.mainWindow;
[mainWindow showHDCDLogo:YES];
MiniWindow *miniWindow = (MiniWindow *)appController.miniWindow;
[miniWindow showHDCDLogo:YES];
}
- (void)removeHDCD:(id)sender
{
- (void)removeHDCD:(id)sender {
MainWindow *mainWindow = (MainWindow *)appController.mainWindow;
[mainWindow showHDCDLogo:NO];
MiniWindow *miniWindow = (MiniWindow *)appController.miniWindow;
[miniWindow showHDCDLogo:NO];
}
- (void)playlistDidChange:(PlaylistController *)p
{
- (void)playlistDidChange:(PlaylistController *)p {
[audioPlayer resetNextStreams];
}
- (void)setPosition:(double)p
{
if (p > lastPosition && (p - lastPosition) >= 10.0)
{
- (void)setPosition:(double)p {
if(p > lastPosition && (p - lastPosition) >= 10.0) {
PlaylistEntry *pe = [playlistController currentEntry];
NSInteger lastTrackPlaying = [pe index];
@ -886,18 +787,15 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[[playlistController currentEntry] setCurrentPosition:p];
}
- (double)position
{
- (double)position {
return position;
}
- (void)setSeekable:(BOOL)s
{
- (void)setSeekable:(BOOL)s {
seekable = s;
}
- (BOOL)seekable
{
- (BOOL)seekable {
return seekable && [[playlistController currentEntry] seekable];
}
@ -918,7 +816,8 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
// can't do && with @available
if(@available(macOS 10.13.2, *)) {
CGSize artworkSize = CGSizeMake(500, 500);
MPMediaItemArtwork *mpArtwork = [[MPMediaItemArtwork alloc] initWithBoundsSize:artworkSize requestHandler:^NSImage * _Nonnull(CGSize size) {
MPMediaItemArtwork *mpArtwork = [[MPMediaItemArtwork alloc] initWithBoundsSize:artworkSize
requestHandler:^NSImage *_Nonnull(CGSize size) {
return [entry albumArt];
}];
[songInfo setObject:mpArtwork forKey:MPMediaItemPropertyArtwork];
@ -955,7 +854,4 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
[defaultCenter setNowPlayingInfo:songInfo];
}
@end

View file

@ -20,7 +20,9 @@ NSString *TrackLength = @"Total Time";
NSString *TrackPath = @"Location";
NSString *TrackState = @"Player State";
typedef NS_ENUM(NSInteger, TrackStatus) { TrackPlaying, TrackPaused, TrackStopped };
typedef NS_ENUM(NSInteger, TrackStatus) { TrackPlaying,
TrackPaused,
TrackStopped };
@implementation PlaybackEventController {
AudioScrobbler *scrobbler;
@ -375,9 +377,7 @@ typedef NS_ENUM(NSInteger, TrackStatus) { TrackPlaying, TrackPaused, TrackStoppe
break;
case NSUserNotificationActivationTypeContentsClicked: {
NSWindow *window = [[NSUserDefaults standardUserDefaults] boolForKey:@"miniMode"]
? miniWindow
: mainWindow;
NSWindow *window = [[NSUserDefaults standardUserDefaults] boolForKey:@"miniMode"] ? miniWindow : mainWindow;
[NSApp activateIgnoringOtherApps:YES];
[window makeKeyAndOrderFront:self];

View file

@ -10,7 +10,6 @@
#import <CogAudio/Plugin.h>
@interface AudioContainer : NSObject {
}
+ (NSArray *)urlsForContainerURL:(NSURL *)url;

View file

@ -12,8 +12,7 @@
@implementation AudioContainer
+ (NSArray *) urlsForContainerURL:(NSURL *)url
{
+ (NSArray *)urlsForContainerURL:(NSURL *)url {
@autoreleasepool {
return [[PluginController sharedPluginController] urlsForContainerURL:url];
}

View file

@ -12,13 +12,11 @@
@implementation AudioDecoder
+ (id<CogDecoder>) audioDecoderForSource:(id <CogSource>)source
{
+ (id<CogDecoder>)audioDecoderForSource:(id<CogSource>)source {
return [[PluginController sharedPluginController] audioDecoderForSource:source skipCue:NO];
}
+ (id<CogDecoder>) audioDecoderForSource:(id <CogSource>)source skipCue:(BOOL)skip
{
+ (id<CogDecoder>)audioDecoderForSource:(id<CogSource>)source skipCue:(BOOL)skip {
return [[PluginController sharedPluginController] audioDecoderForSource:source skipCue:skip];
}

View file

@ -8,9 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface AudioMetadataReader : NSObject {
}
+ (NSDictionary *)metadataForURL:(NSURL *)url;

View file

@ -11,15 +11,13 @@
@implementation AudioMetadataReader
+ (NSDictionary *)metadataForURL:(NSURL *)url
{
+ (NSDictionary *)metadataForURL:(NSURL *)url {
@autoreleasepool {
return [[PluginController sharedPluginController] metadataForURL:url skipCue:NO];
}
}
+ (NSDictionary *)metadataForURL:(NSURL *)url skipCue:(BOOL)skip
{
+ (NSDictionary *)metadataForURL:(NSURL *)url skipCue:(BOOL)skip {
@autoreleasepool {
return [[PluginController sharedPluginController] metadataForURL:url skipCue:skip];
}

View file

@ -8,9 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface AudioMetadataWriter : NSObject {
}
+ (int)putMetadataInURL:(NSURL *)url;

View file

@ -10,8 +10,7 @@
#import "PluginController.h"
@implementation AudioMetadataWriter
+ (int)putMetadataInURL:(NSURL *)url
{
+ (int)putMetadataInURL:(NSURL *)url {
return [[PluginController sharedPluginController] putMetadataInURL:url];
}
@end

View file

@ -10,10 +10,10 @@
#import <CogAudio/Semaphore.h>
#import <CoreAudio/CoreAudio.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudio.h>
#import <CoreAudio/CoreAudioTypes.h>
#import <stdatomic.h>
@ -21,8 +21,7 @@
@class BufferChain;
@class OutputNode;
@interface AudioPlayer : NSObject
{
@interface AudioPlayer : NSObject {
BufferChain *bufferChain;
OutputNode *output;
@ -124,4 +123,3 @@
- (void)audioPlayer:(AudioPlayer *)player sustainHDCD:(id)userInfo;
@end

View file

@ -8,21 +8,18 @@
#import "AudioPlayer.h"
#import "BufferChain.h"
#import "OutputNode.h"
#import "Status.h"
#import "Helper.h"
#import "OutputNode.h"
#import "PluginController.h"
#import "Status.h"
#import "Logging.h"
@implementation AudioPlayer
- (id)init
{
- (id)init {
self = [super init];
if (self)
{
if(self) {
output = NULL;
bufferChain = nil;
outputLaunched = NO;
@ -39,8 +36,7 @@
return self;
}
- (void)setDelegate:(id)d
{
- (void)setDelegate:(id)d {
delegate = d;
}
@ -48,23 +44,19 @@
return delegate;
}
- (void)play:(NSURL *)url
{
- (void)play:(NSURL *)url {
[self play:url withUserInfo:nil withRGInfo:nil startPaused:NO andSeekTo:0.0];
}
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi
{
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi {
[self play:url withUserInfo:userInfo withRGInfo:rgi startPaused:NO andSeekTo:0.0];
}
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused
{
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused {
[self play:url withUserInfo:userInfo withRGInfo:rgi startPaused:paused andSeekTo:0.0];
}
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused andSeekTo:(double)time
{
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused andSeekTo:(double)time {
ALog(@"Opening file for playback: %@ at seek offset %f%@", url, time, (paused) ? @", starting paused" : @"");
[self waitUntilCallbacksExit];
@ -76,14 +68,12 @@
[output setup];
[output setVolume:volume];
@synchronized(chainQueue) {
for (id anObject in chainQueue)
{
for(id anObject in chainQueue) {
[anObject setShouldContinue:NO];
}
[chainQueue removeAllObjects];
endOfInputReached = NO;
if (bufferChain)
{
if(bufferChain) {
[bufferChain setShouldContinue:NO];
bufferChain = nil;
@ -93,15 +83,13 @@
bufferChain = [[BufferChain alloc] initWithController:self];
[self notifyStreamChanged:userInfo];
while (![bufferChain open:url withOutputFormat:[output format] withRGInfo:rgi])
{
while(![bufferChain open:url withOutputFormat:[output format] withRGInfo:rgi]) {
bufferChain = nil;
[self requestNextStream:userInfo];
url = nextStream;
if (url == nil)
{
if(url == nil) {
return;
}
@ -115,8 +103,7 @@
[bufferChain setUserInfo:userInfo];
if (time > 0.0)
{
if(time > 0.0) {
[output seek:time];
[bufferChain seek:time];
}
@ -133,38 +120,32 @@
[self setPlaybackStatus:CogStatusPaused waitUntilDone:YES];
}
- (void)stop
{
- (void)stop {
// Set shouldoContinue to NO on all things
[self setShouldContinue:NO];
[self setPlaybackStatus:CogStatusStopped waitUntilDone:YES];
@synchronized(chainQueue) {
for (id anObject in chainQueue)
{
for(id anObject in chainQueue) {
[anObject setShouldContinue:NO];
}
[chainQueue removeAllObjects];
endOfInputReached = NO;
if (bufferChain)
{
if(bufferChain) {
bufferChain = nil;
}
}
output = nil;
}
- (void)pause
{
- (void)pause {
[output pause];
[self setPlaybackStatus:CogStatusPaused waitUntilDone:YES];
}
- (void)resume
{
if (startedPaused)
{
- (void)resume {
if(startedPaused) {
startedPaused = NO;
if(initialBufferFilled)
[self launchOutputThread];
@ -175,10 +156,8 @@
[self setPlaybackStatus:CogStatusPlaying waitUntilDone:YES];
}
- (void)seekToTime:(double)time
{
if (endOfInputReached)
{
- (void)seekToTime:(double)time {
if(endOfInputReached) {
// This is a dirty hack in case the playback has finished with the track
// that the user thinks they're seeking into
CogStatus status = (CogStatus)currentPlaybackStatus;
@ -195,36 +174,29 @@
[self stop];
[self play:url withUserInfo:userInfo withRGInfo:rgi startPaused:(status == CogStatusPaused) andSeekTo:time];
}
else
{
} else {
// Still decoding the current file, safe to seek within it
[output seek:time];
[bufferChain seek:time];
}
}
- (void)setVolume:(double)v
{
- (void)setVolume:(double)v {
volume = v;
[output setVolume:v];
}
- (double)volume
{
- (double)volume {
return volume;
}
// This is called by the delegate DURING a requestNextStream request.
- (void)setNextStream:(NSURL *)url
{
- (void)setNextStream:(NSURL *)url {
[self setNextStream:url withUserInfo:nil withRGInfo:nil];
}
- (void)setNextStream:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi
{
- (void)setNextStream:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi {
nextStream = url;
nextStreamUserInfo = userInfo;
@ -233,8 +205,7 @@
}
// Called when the playlist changed before we actually started playing a requested stream. We will re-request.
- (void)resetNextStreams
{
- (void)resetNextStreams {
[self waitUntilCallbacksExit];
@synchronized(chainQueue) {
@ -249,8 +220,7 @@
}
}
- (void)setShouldContinue:(BOOL)s
{
- (void)setShouldContinue:(BOOL)s {
shouldContinue = s;
if(bufferChain)
@ -260,13 +230,11 @@
[output setShouldContinue:s];
}
- (double)amountPlayed
{
- (double)amountPlayed {
return [output amountPlayed];
}
- (void)launchOutputThread
{
- (void)launchOutputThread {
initialBufferFilled = YES;
if(outputLaunched == NO && startedPaused == NO) {
[self setPlaybackStatus:CogStatusPlaying];
@ -275,33 +243,27 @@
}
}
- (void)requestNextStream:(id)userInfo
{
- (void)requestNextStream:(id)userInfo {
[self sendDelegateMethod:@selector(audioPlayer:willEndStream:) withObject:userInfo waitUntilDone:YES];
}
- (void)notifyStreamChanged:(id)userInfo
{
- (void)notifyStreamChanged:(id)userInfo {
[self sendDelegateMethod:@selector(audioPlayer:didBeginStream:) withObject:userInfo waitUntilDone:YES];
}
- (void)beginEqualizer:(AudioUnit)eq
{
- (void)beginEqualizer:(AudioUnit)eq {
[self sendDelegateMethod:@selector(audioPlayer:displayEqualizer:) withVoid:eq waitUntilDone:YES];
}
- (void)refreshEqualizer:(AudioUnit)eq
{
- (void)refreshEqualizer:(AudioUnit)eq {
[self sendDelegateMethod:@selector(audioPlayer:refreshEqualizer:) withVoid:eq waitUntilDone:YES];
}
- (void)endEqualizer:(AudioUnit)eq
{
- (void)endEqualizer:(AudioUnit)eq {
[self sendDelegateMethod:@selector(audioPlayer:removeEqualizer:) withVoid:eq waitUntilDone:YES];
}
- (void)addChainToQueue:(BufferChain *)newChain
{
- (void)addChainToQueue:(BufferChain *)newChain {
[newChain setUserInfo:nextStreamUserInfo];
[newChain setShouldContinue:YES];
@ -322,10 +284,8 @@
@synchronized(chainQueue) {
// No point in constructing new chain for the next playlist entry
// if there's already one at the head of chainQueue... r-r-right?
for (BufferChain *chain in chainQueue)
{
if ([chain isRunning])
{
for(BufferChain *chain in chainQueue) {
if([chain isRunning]) {
atomic_fetch_sub(&refCount, 1);
return YES;
}
@ -346,8 +306,7 @@
}
}
while (duration >= 30.0 && shouldContinue)
{
while(duration >= 30.0 && shouldContinue) {
[semaphore wait];
if(atomic_load_explicit(&resettingNow, memory_order_relaxed)) {
atomic_fetch_sub(&refCount, 1);
@ -385,8 +344,7 @@
BOOL pathsEqual = NO;
if ([nextStream isFileURL] && [[lastChain streamURL] isFileURL])
{
if([nextStream isFileURL] && [[lastChain streamURL] isFileURL]) {
NSMutableString *unixPathNext = [[nextStream path] mutableCopy];
NSMutableString *unixPathPrev = [[[lastChain streamURL] path] mutableCopy];
@ -394,15 +352,8 @@
pathsEqual = YES;
}
if (pathsEqual || ([[nextStream scheme] isEqualToString:[[lastChain streamURL] scheme]]
&& (([nextStream host] == nil &&
[[lastChain streamURL] host] == nil)
|| [[nextStream host] isEqualToString:[[lastChain streamURL] host]])
&& [[nextStream path] isEqualToString:[[lastChain streamURL] path]]))
{
if ([lastChain setTrack:nextStream]
&& [newChain openWithInput:[lastChain inputNode] withOutputFormat:[output format] withRGInfo:nextStreamRGInfo])
{
if(pathsEqual || ([[nextStream scheme] isEqualToString:[[lastChain streamURL] scheme]] && (([nextStream host] == nil && [[lastChain streamURL] host] == nil) || [[nextStream host] isEqualToString:[[lastChain streamURL] host]]) && [[nextStream path] isEqualToString:[[lastChain streamURL] path]])) {
if([lastChain setTrack:nextStream] && [newChain openWithInput:[lastChain inputNode] withOutputFormat:[output format] withRGInfo:nextStreamRGInfo]) {
[newChain setStreamURL:nextStream];
[newChain setUserInfo:nextStreamUserInfo];
@ -418,10 +369,8 @@
lastChain = nil;
while (shouldContinue && ![newChain open:nextStream withOutputFormat:[output format] withRGInfo:nextStreamRGInfo])
{
if (nextStream == nil)
{
while(shouldContinue && ![newChain open:nextStream withOutputFormat:[output format] withRGInfo:nextStreamRGInfo]) {
if(nextStream == nil) {
newChain = nil;
atomic_fetch_sub(&refCount, 1);
return YES;
@ -453,8 +402,7 @@
return YES;
}
- (void)endOfInputPlayed
{
- (void)endOfInputPlayed {
// Once we get here:
// - the buffer chain for the next playlist entry (started in endOfInputReached) have been working for some time
// already, so that there is some decoded and converted data to play
@ -463,8 +411,7 @@
@synchronized(chainQueue) {
endOfInputReached = NO;
if ([chainQueue count] <= 0)
{
if([chainQueue count] <= 0) {
// End of playlist
[self stop];
@ -486,16 +433,14 @@
[output setEndOfStream:NO];
}
- (BOOL)chainQueueHasTracks
{
- (BOOL)chainQueueHasTracks {
@synchronized(chainQueue) {
return [chainQueue count] > 0;
}
return NO;
}
- (void)sendDelegateMethod:(SEL)selector withVoid:(void*)obj waitUntilDone:(BOOL)wait
{
- (void)sendDelegateMethod:(SEL)selector withVoid:(void *)obj waitUntilDone:(BOOL)wait {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[delegate methodSignatureForSelector:selector]];
[invocation setTarget:delegate];
[invocation setSelector:selector];
@ -506,8 +451,7 @@
[invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:wait];
}
- (void)sendDelegateMethod:(SEL)selector withObject:(id)obj waitUntilDone:(BOOL)wait
{
- (void)sendDelegateMethod:(SEL)selector withObject:(id)obj waitUntilDone:(BOOL)wait {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[delegate methodSignatureForSelector:selector]];
[invocation setTarget:delegate];
[invocation setSelector:selector];
@ -518,8 +462,7 @@
[invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:wait];
}
- (void)sendDelegateMethod:(SEL)selector withObject:(id)obj withObject:(id)obj2 waitUntilDone:(BOOL)wait
{
- (void)sendDelegateMethod:(SEL)selector withObject:(id)obj withObject:(id)obj2 waitUntilDone:(BOOL)wait {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[delegate methodSignatureForSelector:selector]];
[invocation setTarget:delegate];
[invocation setSelector:selector];
@ -531,41 +474,33 @@
[invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:wait];
}
- (void)setPlaybackStatus:(int)status waitUntilDone:(BOOL)wait
{
- (void)setPlaybackStatus:(int)status waitUntilDone:(BOOL)wait {
currentPlaybackStatus = status;
[self sendDelegateMethod:@selector(audioPlayer:didChangeStatus:userInfo:) withObject:[NSNumber numberWithInt:status] withObject:[bufferChain userInfo] waitUntilDone:wait];
}
- (void)sustainHDCD
{
- (void)sustainHDCD {
[self sendDelegateMethod:@selector(audioPlayer:sustainHDCD:) withObject:[bufferChain userInfo] waitUntilDone:NO];
}
- (void)setPlaybackStatus:(int)status
{
- (void)setPlaybackStatus:(int)status {
[self setPlaybackStatus:status waitUntilDone:NO];
}
- (BufferChain *)bufferChain
{
- (BufferChain *)bufferChain {
return bufferChain;
}
- (OutputNode *) output
{
- (OutputNode *)output {
return output;
}
+ (NSArray *)containerTypes
{
+ (NSArray *)containerTypes {
return [[[PluginController sharedPluginController] containers] allKeys];
}
+ (NSArray *)fileTypes
{
+ (NSArray *)fileTypes {
PluginController *pluginController = [PluginController sharedPluginController];
NSArray *containerTypes = [[pluginController containers] allKeys];
@ -583,15 +518,13 @@
return [types allObjects];
}
+ (NSArray *)schemes
{
+ (NSArray *)schemes {
PluginController *pluginController = [PluginController sharedPluginController];
return [[pluginController sources] allKeys];
}
- (double)volumeUp:(double)amount
{
- (double)volumeUp:(double)amount {
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
@ -606,8 +539,7 @@
return newVolume;
}
- (double)volumeDown:(double)amount
{
- (double)volumeDown:(double)amount {
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
@ -621,8 +553,7 @@
return newVolume;
}
- (void)waitUntilCallbacksExit
{
- (void)waitUntilCallbacksExit {
// This sucks! And since the thread that's inside the function can be calling
// event dispatches, we have to pump the message queue if we're on the main
// thread. Damn.
@ -640,5 +571,4 @@
}
}
@end

View file

@ -8,9 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface AudioPropertiesReader : NSObject {
}
+ (NSDictionary *)propertiesForURL:(NSURL *)url;

View file

@ -13,8 +13,7 @@
@implementation AudioPropertiesReader
+ (NSDictionary *)propertiesForURL:(NSURL *)url
{
+ (NSDictionary *)propertiesForURL:(NSURL *)url {
@autoreleasepool {
return [[PluginController sharedPluginController] propertiesForURL:url];
}

View file

@ -8,11 +8,9 @@
#import "AudioSource.h"
@implementation AudioSource
+ (id<CogSource>) audioSourceForURL:(NSURL *)url
{
+ (id<CogSource>)audioSourceForURL:(NSURL *)url {
return [[PluginController sharedPluginController] audioSourceForURL:url];
}

View file

@ -8,8 +8,8 @@
#ifndef AudioChunk_h
#define AudioChunk_h
#import <Foundation/Foundation.h>
#import <CoreAudio/CoreAudio.h>
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN

View file

@ -8,9 +8,9 @@
#import <Cocoa/Cocoa.h>
#import "InputNode.h"
#import "ConverterNode.h"
#import "AudioPlayer.h"
#import "ConverterNode.h"
#import "InputNode.h"
@interface BufferChain : NSObject {
InputNode *inputNode;

View file

@ -7,19 +7,17 @@
//
#import "BufferChain.h"
#import "OutputNode.h"
#import "AudioSource.h"
#import "CoreAudioUtils.h"
#import "OutputNode.h"
#import "Logging.h"
@implementation BufferChain
- (id)initWithController:(id)c
{
- (id)initWithController:(id)c {
self = [super init];
if (self)
{
if(self) {
controller = c;
streamURL = nil;
userInfo = nil;
@ -32,8 +30,7 @@
return self;
}
- (void)buildChain
{
- (void)buildChain {
inputNode = nil;
converterNode = nil;
@ -43,16 +40,14 @@
finalNode = converterNode;
}
- (BOOL)open:(NSURL *)url withOutputFormat:(AudioStreamBasicDescription)outputFormat withRGInfo:(NSDictionary *)rgi
{
- (BOOL)open:(NSURL *)url withOutputFormat:(AudioStreamBasicDescription)outputFormat withRGInfo:(NSDictionary *)rgi {
[self setStreamURL:url];
[self buildChain];
id<CogSource> source = [AudioSource audioSourceForURL:url];
DLog(@"Opening: %@", url);
if (!source || ![source open:url])
{
if(!source || ![source open:url]) {
DLog(@"Couldn't open source...");
url = [NSURL URLWithString:@"silence://10"];
source = [AudioSource audioSourceForURL:url];
@ -81,8 +76,7 @@
return YES;
}
- (BOOL)openWithInput:(InputNode *)i withOutputFormat:(AudioStreamBasicDescription)outputFormat withRGInfo:(NSDictionary *)rgi
{
- (BOOL)openWithInput:(InputNode *)i withOutputFormat:(AudioStreamBasicDescription)outputFormat withRGInfo:(NSDictionary *)rgi {
DLog(@"New buffer chain!");
[self buildChain];
@ -134,37 +128,31 @@
return YES;
}
- (void)launchThreads
{
- (void)launchThreads {
DLog(@"Properties: %@", [inputNode properties]);
[inputNode launchThread];
[converterNode launchThread];
}
- (void)setUserInfo:(id)i
{
- (void)setUserInfo:(id)i {
userInfo = i;
}
- (id)userInfo
{
- (id)userInfo {
return userInfo;
}
- (void)setRGInfo:(NSDictionary *)rgi
{
- (void)setRGInfo:(NSDictionary *)rgi {
rgInfo = rgi;
[converterNode setRGInfo:rgi];
}
- (NSDictionary *)rgInfo
{
- (NSDictionary *)rgInfo {
return rgInfo;
}
- (void)dealloc
{
- (void)dealloc {
[inputNode setShouldContinue:NO];
[[inputNode exitAtTheEndOfTheStream] signal];
[[inputNode semaphore] signal];
@ -173,88 +161,71 @@
DLog(@"Bufferchain dealloc");
}
- (void)seek:(double)time
{
- (void)seek:(double)time {
long frame = (long)round(time * [[[inputNode properties] objectForKey:@"sampleRate"] floatValue]);
[inputNode seek:frame];
}
- (BOOL)endOfInputReached
{
- (BOOL)endOfInputReached {
return [controller endOfInputReached:self];
}
- (BOOL)setTrack: (NSURL *)track
{
- (BOOL)setTrack:(NSURL *)track {
return [inputNode setTrack:track];
}
- (void)initialBufferFilled:(id)sender
{
- (void)initialBufferFilled:(id)sender {
DLog(@"INITIAL BUFFER FILLED");
[controller launchOutputThread];
}
- (void)inputFormatDidChange:(AudioStreamBasicDescription)format
{
- (void)inputFormatDidChange:(AudioStreamBasicDescription)format {
DLog(@"FORMAT DID CHANGE!");
}
- (InputNode *)inputNode
{
- (InputNode *)inputNode {
return inputNode;
}
- (id)finalNode
{
- (id)finalNode {
return finalNode;
}
- (NSURL *)streamURL
{
- (NSURL *)streamURL {
return streamURL;
}
- (void)setStreamURL:(NSURL *)url
{
- (void)setStreamURL:(NSURL *)url {
streamURL = url;
}
- (void)setShouldContinue:(BOOL)s
{
- (void)setShouldContinue:(BOOL)s {
[inputNode setShouldContinue:s];
[converterNode setShouldContinue:s];
}
- (BOOL)isRunning
{
- (BOOL)isRunning {
InputNode *node = [self inputNode];
if (nil != node && [node shouldContinue] && ![node endOfStream])
{
if(nil != node && [node shouldContinue] && ![node endOfStream]) {
return YES;
}
return NO;
}
- (id)controller
{
- (id)controller {
return controller;
}
- (ConverterNode *)converter
{
- (ConverterNode *)converter {
return converterNode;
}
- (AudioStreamBasicDescription)inputFormat
{
- (AudioStreamBasicDescription)inputFormat {
return inputFormat;
}
- (double)secondsBuffered
{
- (double)secondsBuffered {
double duration = 0.0;
OutputNode *outputNode = (OutputNode *)[controller output];
duration += [outputNode secondsBuffered];
@ -267,8 +238,7 @@
return duration;
}
- (void)sustainHDCD
{
- (void)sustainHDCD {
OutputNode *outputNode = (OutputNode *)[controller output];
[outputNode sustainHDCD];
[controller sustainHDCD];

View file

@ -5,8 +5,8 @@
// Created by Christopher Snowhill on 2/5/22.
//
#import <Foundation/Foundation.h>
#import <CoreAudio/CoreAudio.h>
#import <Foundation/Foundation.h>
#import "AudioChunk.h"

View file

@ -8,9 +8,9 @@
#import <Cocoa/Cocoa.h>
#import <CoreAudio/AudioHardware.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <CoreAudio/AudioHardware.h>
#import <soxr.h>

View file

@ -18,8 +18,7 @@
#import "hdcd_decode2.h"
void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
{
void PrintStreamDesc(AudioStreamBasicDescription *inDesc) {
if(!inDesc) {
DLog(@"Can't print a NULL desc!\n");
return;
@ -40,11 +39,9 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
@synthesize inputFormat;
- (id)initWithController:(id)c previous:(id)p
{
- (id)initWithController:(id)c previous:(id)p {
self = [super initWithController:c previous:p];
if (self)
{
if(self) {
rgInfo = nil;
soxr = 0;
@ -77,10 +74,8 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
return self;
}
void scale_by_volume(float * buffer, size_t count, float volume)
{
if ( volume != 1.0 )
{
void scale_by_volume(float *buffer, size_t count, float volume) {
if(volume != 1.0) {
vDSP_vsmul(buffer, 1, &volume, buffer, 1, count);
}
}
@ -94,8 +89,7 @@ void scale_by_volume(float * buffer, size_t count, float volume)
*/
#define dsd2pcm_FILTER_COEFFS_COUNT 64
static const float dsd2pcm_FILTER_COEFFS[64] =
{
static const float dsd2pcm_FILTER_COEFFS[64] = {
0.09712411121659f, 0.09613438994044f, 0.09417884216316f, 0.09130441727307f,
0.08757947648990f, 0.08309142055179f, 0.07794369263673f, 0.07225228745463f,
0.06614191680338f, 0.05974199351302f, 0.05318259916599f, 0.04659059631228f,
@ -138,8 +132,7 @@ struct dsd2pcm_state {
static void dsd2pcm_free(void *);
static void dsd2pcm_reset(void *);
static void * dsd2pcm_alloc()
{
static void *dsd2pcm_alloc() {
struct dsd2pcm_state *state = (struct dsd2pcm_state *)calloc(1, sizeof(struct dsd2pcm_state));
if(!state)
@ -155,16 +148,12 @@ static void * dsd2pcm_alloc()
double *temp = (double *)calloc(sizeof(double), 0x100);
if(!temp)
goto fail;
for ( int part=0, sofs=0, dofs=0; part < FILT_LOOKUP_PARTS; )
{
for(int part = 0, sofs = 0, dofs = 0; part < FILT_LOOKUP_PARTS;) {
memset(temp, 0, 0x100 * sizeof(double));
for ( int bit=0, bitmask=0x80; bit<8 && sofs+bit < dsd2pcm_FILTER_COEFFS_COUNT; )
{
for(int bit = 0, bitmask = 0x80; bit < 8 && sofs + bit < dsd2pcm_FILTER_COEFFS_COUNT;) {
double coeff = dsd2pcm_FILTER_COEFFS[sofs + bit];
for ( int bite=0; bite < 0x100; bite++ )
{
if ( ( bite & bitmask ) == 0 )
{
for(int bite = 0; bite < 0x100; bite++) {
if((bite & bitmask) == 0) {
temp[bite] -= coeff;
} else {
temp[bite] += coeff;
@ -213,11 +202,9 @@ fail:
return NULL;
}
static void * dsd2pcm_dup(void * _state)
{
static void *dsd2pcm_dup(void *_state) {
struct dsd2pcm_state *state = (struct dsd2pcm_state *)_state;
if (state)
{
if(state) {
struct dsd2pcm_state *newstate = (struct dsd2pcm_state *)calloc(1, sizeof(struct dsd2pcm_state));
if(newstate) {
newstate->FILT_LOOKUP_PARTS = state->FILT_LOOKUP_PARTS;
@ -254,11 +241,9 @@ static void * dsd2pcm_dup(void * _state)
return NULL;
}
static void dsd2pcm_free(void * _state)
{
static void dsd2pcm_free(void *_state) {
struct dsd2pcm_state *state = (struct dsd2pcm_state *)_state;
if (state)
{
if(state) {
free(state->fifo);
free(state->REVERSE_BITS);
free(state->FILT_LOOKUP_TABLE);
@ -266,8 +251,7 @@ static void dsd2pcm_free(void * _state)
}
}
static void dsd2pcm_reset(void * _state)
{
static void dsd2pcm_reset(void *_state) {
struct dsd2pcm_state *state = (struct dsd2pcm_state *)_state;
const int FILT_LOOKUP_PARTS = state->FILT_LOOKUP_PARTS;
int *fifo = state->fifo;
@ -278,15 +262,15 @@ static void dsd2pcm_reset(void * _state)
state->fpos = FILT_LOOKUP_PARTS;
}
static int dsd2pcm_latency(void * _state)
{
static int dsd2pcm_latency(void *_state) {
struct dsd2pcm_state *state = (struct dsd2pcm_state *)_state;
if (state) return state->FIFO_LENGTH;
else return 0;
if(state)
return state->FIFO_LENGTH;
else
return 0;
}
static void dsd2pcm_process(void * _state, const uint8_t * src, size_t sofs, size_t sinc, float * dest, size_t dofs, size_t dinc, size_t len)
{
static void dsd2pcm_process(void *_state, const uint8_t *src, size_t sofs, size_t sinc, float *dest, size_t dofs, size_t dinc, size_t len) {
struct dsd2pcm_state *state = (struct dsd2pcm_state *)_state;
int bite1, bite2, temp;
float sample;
@ -296,15 +280,13 @@ static void dsd2pcm_process(void * _state, const uint8_t * src, size_t sofs, siz
const int FILT_LOOKUP_PARTS = state->FILT_LOOKUP_PARTS;
const int FIFO_OFS_MASK = state->FIFO_OFS_MASK;
int fpos = state->fpos;
while ( len > 0 )
{
while(len > 0) {
fifo[fpos] = REVERSE_BITS[fifo[fpos]] & 0xFF;
fifo[(fpos + FILT_LOOKUP_PARTS) & FIFO_OFS_MASK] = src[sofs] & 0xFF;
sofs += sinc;
temp = (fpos + 1) & FIFO_OFS_MASK;
sample = 0;
for ( int k=0, lofs=0; k < FILT_LOOKUP_PARTS; )
{
for(int k = 0, lofs = 0; k < FILT_LOOKUP_PARTS;) {
bite1 = fifo[(fpos - k) & FIFO_OFS_MASK];
bite2 = fifo[(temp + k) & FIFO_OFS_MASK];
sample += FILT_LOOKUP_TABLE[lofs + bite1] + FILT_LOOKUP_TABLE[lofs + bite2];
@ -319,92 +301,72 @@ static void dsd2pcm_process(void * _state, const uint8_t * src, size_t sofs, siz
state->fpos = fpos;
}
static void convert_dsd_to_f32(float *output, const uint8_t *input, size_t count, size_t channels, void ** dsd2pcm)
{
for (size_t channel = 0; channel < channels; ++channel)
{
static void convert_dsd_to_f32(float *output, const uint8_t *input, size_t count, size_t channels, void **dsd2pcm) {
for(size_t channel = 0; channel < channels; ++channel) {
dsd2pcm_process(dsd2pcm[channel], input, channel, channels, output, channel, channels, count);
}
}
static void convert_u8_to_s16(int16_t *output, const uint8_t *input, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
static void convert_u8_to_s16(int16_t *output, const uint8_t *input, size_t count) {
for(size_t i = 0; i < count; ++i) {
uint16_t sample = (input[i] << 8) | input[i];
sample ^= 0x8080;
output[i] = (int16_t)(sample);
}
}
static void convert_s8_to_s16(int16_t *output, const uint8_t *input, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
static void convert_s8_to_s16(int16_t *output, const uint8_t *input, size_t count) {
for(size_t i = 0; i < count; ++i) {
uint16_t sample = (input[i] << 8) | input[i];
output[i] = (int16_t)(sample);
}
}
static void convert_u16_to_s16(int16_t *buffer, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
static void convert_u16_to_s16(int16_t *buffer, size_t count) {
for(size_t i = 0; i < count; ++i) {
buffer[i] ^= 0x8000;
}
}
static void convert_s16_to_hdcd_input(int32_t *output, const int16_t *input, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
static void convert_s16_to_hdcd_input(int32_t *output, const int16_t *input, size_t count) {
for(size_t i = 0; i < count; ++i) {
output[i] = input[i];
}
}
static void convert_s24_to_s32(int32_t *output, const uint8_t *input, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
static void convert_s24_to_s32(int32_t *output, const uint8_t *input, size_t count) {
for(size_t i = 0; i < count; ++i) {
int32_t sample = (input[i * 3] << 8) | (input[i * 3 + 1] << 16) | (input[i * 3 + 2] << 24);
output[i] = sample;
}
}
static void convert_u24_to_s32(int32_t *output, const uint8_t *input, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
static void convert_u24_to_s32(int32_t *output, const uint8_t *input, size_t count) {
for(size_t i = 0; i < count; ++i) {
int32_t sample = (input[i * 3] << 8) | (input[i * 3 + 1] << 16) | (input[i * 3 + 2] << 24);
output[i] = sample ^ 0x80000000;
}
}
static void convert_u32_to_s32(int32_t *buffer, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
static void convert_u32_to_s32(int32_t *buffer, size_t count) {
for(size_t i = 0; i < count; ++i) {
buffer[i] ^= 0x80000000;
}
}
static void convert_f64_to_f32(float *output, const double *input, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
static void convert_f64_to_f32(float *output, const double *input, size_t count) {
for(size_t i = 0; i < count; ++i) {
output[i] = (float)(input[i]);
}
}
static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes)
{
static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes) {
size_t i;
uint8_t temp;
bitsPerSample = (bitsPerSample + 7) / 8;
switch(bitsPerSample) {
case 2:
for (i = 0; i < bytes; i += 2)
{
for(i = 0; i < bytes; i += 2) {
temp = buffer[1];
buffer[1] = buffer[0];
buffer[0] = temp;
@ -413,8 +375,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
break;
case 3:
for (i = 0; i < bytes; i += 3)
{
for(i = 0; i < bytes; i += 3) {
temp = buffer[2];
buffer[2] = buffer[0];
buffer[0] = temp;
@ -423,8 +384,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
break;
case 4:
for (i = 0; i < bytes; i += 4)
{
for(i = 0; i < bytes; i += 4) {
temp = buffer[3];
buffer[3] = buffer[0];
buffer[0] = temp;
@ -436,8 +396,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
break;
case 8:
for (i = 0; i < bytes; i += 8)
{
for(i = 0; i < bytes; i += 8) {
temp = buffer[7];
buffer[7] = buffer[0];
buffer[0] = temp;
@ -456,26 +415,20 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
}
}
-(void)process
{
- (void)process {
char writeBuf[CHUNK_SIZE];
// Removed endOfStream check from here, since we want to be able to flush the converter
// when the end of stream is reached. Convert function instead processes what it can,
// and returns 0 samples when it has nothing more to process at the end of stream.
while ([self shouldContinue] == YES)
{
while([self shouldContinue] == YES) {
int amountConverted = [self convert:writeBuf amount:CHUNK_SIZE];
if (!amountConverted)
{
if (paused)
{
if(!amountConverted) {
if(paused) {
while(paused)
usleep(500);
continue;
}
else if (refillNode)
{
} else if(refillNode) {
// refill node just ended, file resumes
[self setPreviousNode:originalPreviousNode];
[self setEndOfStream:NO];
@ -484,15 +437,14 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
[self cleanUp];
[self setupWithInputFormat:rememberedInputFormat outputFormat:outputFormat isLossless:rememberedLossless];
continue;
}
else break;
} else
break;
}
[self writeData:writeBuf amount:amountConverted];
}
}
- (int)convert:(void *)dest amount:(int)amount
{
- (int)convert:(void *)dest amount:(int)amount {
UInt32 ioNumberPackets;
int amountReadFromFC;
int amountRead = 0;
@ -504,8 +456,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
convertEntered = YES;
tryagain:
if (stopping || [self shouldContinue] == NO)
{
if(stopping || [self shouldContinue] == NO) {
convertEntered = NO;
return amountRead;
}
@ -525,8 +476,7 @@ tryagain:
ioNumberPackets = PRIME_LEN_;
// We want to upscale this count if the ratio is below zero
if (sampleRatio < 1.0)
{
if(sampleRatio < 1.0) {
ioNumberPackets = ((uint32_t)(ioNumberPackets / sampleRatio) + 15) & ~15;
}
@ -545,8 +495,7 @@ tryagain:
ssize_t bytesReadFromInput = 0;
while (bytesReadFromInput < amountToWrite && !stopping && [self shouldContinue] == YES && [self endOfStream] == NO)
{
while(bytesReadFromInput < amountToWrite && !stopping && [self shouldContinue] == YES && [self endOfStream] == NO) {
AudioChunk *chunk = [self readChunk:((amountToWrite - bytesReadFromInput) / inputFormat.mBytesPerPacket)];
AudioStreamBasicDescription inf = [chunk format];
size_t frameCount = [chunk frameCount];
@ -556,8 +505,7 @@ tryagain:
memcpy(inputBuffer + bytesReadFromInput + amountToSkip, [samples bytes], bytesRead);
}
bytesReadFromInput += bytesRead;
if (!frameCount)
{
if(!frameCount) {
if(refillNode)
[self setEndOfStream:YES];
else
@ -567,10 +515,8 @@ tryagain:
// Pad end of track with input format silence
if (stopping || [self shouldContinue] == NO || [self endOfStream] == YES)
{
if (!skipResampler && !is_postextrapolated_)
{
if(stopping || [self shouldContinue] == NO || [self endOfStream] == YES) {
if(!skipResampler && !is_postextrapolated_) {
if(dsd2pcm) {
amountToSkip = dsd2pcmLatency * inputFormat.mBytesPerPacket;
memset(inputBuffer + bytesReadFromInput, 0x55, amountToSkip);
@ -578,8 +524,7 @@ tryagain:
amountToSkip = 0;
}
is_postextrapolated_ = 1;
}
else if (!is_postextrapolated_ && dsd2pcm) {
} else if(!is_postextrapolated_ && dsd2pcm) {
is_postextrapolated_ = 3;
}
}
@ -597,14 +542,12 @@ tryagain:
}
if(bytesReadFromInput &&
(inputFormat.mFormatFlags & kAudioFormatFlagIsBigEndian))
{
(inputFormat.mFormatFlags & kAudioFormatFlagIsBigEndian)) {
// Time for endian swap!
convert_be_to_le(inputBuffer, inputFormat.mBitsPerChannel, bytesReadFromInput);
}
if (bytesReadFromInput && isFloat && inputFormat.mBitsPerChannel == 64)
{
if(bytesReadFromInput && isFloat && inputFormat.mBitsPerChannel == 64) {
// Time for precision loss from weird inputs
samplesRead = bytesReadFromInput / sizeof(double);
convert_f64_to_f32(inputBuffer + bytesReadFromInput, inputBuffer, samplesRead);
@ -612,8 +555,7 @@ tryagain:
bytesReadFromInput = samplesRead * sizeof(float);
}
if (bytesReadFromInput && !isFloat)
{
if(bytesReadFromInput && !isFloat) {
float gain = 1.0;
size_t bitsPerSample = inputFormat.mBitsPerChannel;
if(bitsPerSample == 1) {
@ -623,8 +565,7 @@ tryagain:
bitsPerSample = 32;
bytesReadFromInput = samplesRead * inputFormat.mChannelsPerFrame * sizeof(float);
isFloat = YES;
}
else if (bitsPerSample <= 8) {
} else if(bitsPerSample <= 8) {
samplesRead = bytesReadFromInput;
if(!isUnsigned)
convert_s8_to_s16(inputBuffer + bytesReadFromInput, inputBuffer, samplesRead);
@ -650,8 +591,7 @@ tryagain:
bitsPerSample = 32;
bytesReadFromInput = samplesRead * 4;
isUnsigned = NO;
}
else if (bitsPerSample <= 16) {
} else if(bitsPerSample <= 16) {
samplesRead = bytesReadFromInput / 2;
if(isUnsigned)
convert_u16_to_s16(inputBuffer, samplesRead);
@ -662,8 +602,7 @@ tryagain:
bytesReadFromInput = samplesRead * sizeof(float);
isUnsigned = NO;
isFloat = YES;
}
else if (bitsPerSample <= 24) {
} else if(bitsPerSample <= 24) {
samplesRead = bytesReadFromInput / 3;
if(isUnsigned)
convert_u24_to_s32(inputBuffer + bytesReadFromInput, inputBuffer, samplesRead);
@ -689,8 +628,7 @@ tryagain:
}
// Extrapolate start
if (!skipResampler && !is_preextrapolated_)
{
if(!skipResampler && !is_preextrapolated_) {
size_t samples_in_buffer = bytesReadFromInput / floatFormat.mBytesPerPacket;
size_t prime = min(samples_in_buffer, PRIME_LEN_);
size_t newSize = N_samples_to_add_ * floatFormat.mBytesPerPacket;
@ -705,8 +643,7 @@ tryagain:
bytesToSkip = dsd2pcmLatency * floatFormat.mBytesPerPacket;
if(bytesReadFromInput >= bytesToSkip) {
bytesReadFromInput -= bytesToSkip;
}
else {
} else {
bytesToSkip = 0;
}
}
@ -718,14 +655,12 @@ tryagain:
latencyEaten = N_samples_to_drop_;
if(dsd2pcm) latencyEaten += dsdLatencyEaten;
is_preextrapolated_ = 2;
}
else if (dsd2pcm && !is_preextrapolated_) {
} else if(dsd2pcm && !is_preextrapolated_) {
latencyEaten = dsd2pcmLatency;
is_preextrapolated_ = 3;
}
if (is_postextrapolated_ == 1)
{
if(is_postextrapolated_ == 1) {
size_t samples_in_buffer = bytesReadFromInput / floatFormat.mBytesPerPacket;
if(dsd2pcm) {
@ -751,13 +686,11 @@ tryagain:
latencyEatenPost = N_samples_to_drop_;
if(latencyEatenPost > samplesLatency) {
latencyEatenPost -= samplesLatency;
}
else {
} else {
latencyEatenPost = 0;
}
is_postextrapolated_ = 2;
}
else if (is_postextrapolated_ == 3) { // skip end of DSD output
} else if(is_postextrapolated_ == 3) { // skip end of DSD output
latencyEatenPost = dsd2pcmLatency;
}
@ -766,8 +699,7 @@ tryagain:
inpOffset = 0;
}
if (inpOffset != inpSize && floatOffset == floatSize)
{
if(inpOffset != inpSize && floatOffset == floatSize) {
size_t inputSamples = (inpSize - inpOffset) / floatFormat.mBytesPerPacket;
ioNumberPackets = (UInt32)inputSamples;
@ -781,8 +713,7 @@ tryagain:
if(!floatBuffer || floatBufferSize < newSize)
floatBuffer = realloc(floatBuffer, floatBufferSize = newSize * 3);
if (stopping)
{
if(stopping) {
convertEntered = NO;
return 0;
}
@ -790,27 +721,21 @@ tryagain:
size_t inputDone = 0;
size_t outputDone = 0;
if (!skipResampler)
{
if(!skipResampler) {
ioNumberPackets += soxr_delay(soxr);
soxr_process(soxr, (float *)(((uint8_t *)inputBuffer) + inpOffset), inputSamples, &inputDone, floatBuffer, ioNumberPackets, &outputDone);
if (latencyEatenPost)
{
if(latencyEatenPost) {
// Post file flush
size_t idone = 0, odone = 0;
do
{
do {
soxr_process(soxr, NULL, 0, &idone, floatBuffer + outputDone * floatFormat.mBytesPerPacket, ioNumberPackets - outputDone, &odone);
outputDone += odone;
} while(odone > 0);
}
while (odone > 0);
}
}
else
{
} else {
memcpy(floatBuffer, (((uint8_t *)inputBuffer) + inpOffset), inputSamples * floatFormat.mBytesPerPacket);
inputDone = inputSamples;
outputDone = inputSamples;
@ -818,28 +743,19 @@ tryagain:
inpOffset += inputDone * floatFormat.mBytesPerPacket;
if (latencyEaten)
{
if (outputDone > latencyEaten)
{
if(latencyEaten) {
if(outputDone > latencyEaten) {
outputDone -= latencyEaten;
memmove(floatBuffer, floatBuffer + latencyEaten * floatFormat.mBytesPerPacket, outputDone * floatFormat.mBytesPerPacket);
latencyEaten = 0;
}
else
{
} else {
latencyEaten -= outputDone;
outputDone = 0;
}
}
else if (latencyEatenPost)
{
if (outputDone > latencyEatenPost)
{
} else if(latencyEatenPost) {
if(outputDone > latencyEatenPost) {
outputDone -= latencyEatenPost;
}
else
{
} else {
outputDone = 0;
}
latencyEatenPost = 0;
@ -874,8 +790,7 @@ tryagain:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
context:(void *)context {
DLog(@"SOMETHING CHANGED!");
if([keyPath isEqualToString:@"values.volumeScaling"]) {
// User reset the volume scaling option
@ -883,15 +798,12 @@ tryagain:
}
}
static float db_to_scale(float db)
{
static float db_to_scale(float db) {
return pow(10.0, db / 20);
}
- (void)refreshVolumeScaling
{
if (rgInfo == nil)
{
- (void)refreshVolumeScaling {
if(rgInfo == nil) {
volumeScale = 1.0;
return;
}
@ -931,9 +843,7 @@ static float db_to_scale(float db)
volumeScale = scale;
}
- (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf outputFormat:(AudioStreamBasicDescription)outf isLossless:(BOOL)lossless
{
- (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf outputFormat:(AudioStreamBasicDescription)outf isLossless:(BOOL)lossless {
// Make the converter
inputFormat = inf;
outputFormat = outf;
@ -944,8 +854,7 @@ static float db_to_scale(float db)
// These are the only sample formats we support translating
BOOL isFloat = !!(inputFormat.mFormatFlags & kAudioFormatFlagIsFloat);
if ((!isFloat && !(inputFormat.mBitsPerChannel >= 1 && inputFormat.mBitsPerChannel <= 32))
|| (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64)))
if((!isFloat && !(inputFormat.mBitsPerChannel >= 1 && inputFormat.mBitsPerChannel <= 32)) || (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64)))
return NO;
// These are really placeholders, as we're doing everything internally now
@ -971,8 +880,7 @@ static float db_to_scale(float db)
dsd2pcm = calloc(dsd2pcmCount, sizeof(void *));
dsd2pcm[0] = dsd2pcm_alloc();
dsd2pcmLatency = dsd2pcm_latency(dsd2pcm[0]);
for (size_t i = 1; i < dsd2pcmCount; ++i)
{
for(size_t i = 1; i < dsd2pcmCount; ++i) {
dsd2pcm[i] = dsd2pcm_dup(dsd2pcm[0]);
}
}
@ -995,8 +903,7 @@ static float db_to_scale(float db)
sampleRatio = (double)outputFormat.mSampleRate / (double)floatFormat.mSampleRate;
if (!skipResampler)
{
if(!skipResampler) {
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, 0);
soxr_io_spec_t io_spec = soxr_io_spec(SOXR_FLOAT32_I, SOXR_FLOAT32_I);
soxr_runtime_spec_t runtime_spec = soxr_runtime_spec(0);
@ -1038,8 +945,7 @@ static float db_to_scale(float db)
return YES;
}
- (void)dealloc
{
- (void)dealloc {
DLog(@"Decoder dealloc");
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.volumeScaling"];
@ -1048,23 +954,19 @@ static float db_to_scale(float db)
[self cleanUp];
}
- (void)setOutputFormat:(AudioStreamBasicDescription)format
{
- (void)setOutputFormat:(AudioStreamBasicDescription)format {
DLog(@"SETTING OUTPUT FORMAT!");
previousOutputFormat = outputFormat;
outputFormat = format;
outputFormatChanged = YES;
}
- (void)inputFormatDidChange:(AudioStreamBasicDescription)format
{
- (void)inputFormatDidChange:(AudioStreamBasicDescription)format {
DLog(@"FORMAT CHANGED");
paused = YES;
[self cleanUp];
if(outputFormatChanged && ![buffer isEmpty] &&
memcmp(&outputFormat, &previousOutputFormat, sizeof(outputFormat)) != 0)
{
memcmp(&outputFormat, &previousOutputFormat, sizeof(outputFormat)) != 0) {
// Transfer previously buffered data, remember input format
rememberedInputFormat = format;
originalPreviousNode = previousNode;
@ -1073,71 +975,58 @@ static float db_to_scale(float db)
[refillNode setFormat:previousOutputFormat];
for (;;)
{
for(;;) {
AudioChunk *chunk = [buffer removeSamples:16384];
size_t frameCount = [chunk frameCount];
if(frameCount) {
NSData *samples = [chunk removeSamples:frameCount];
[refillNode writeData:[samples bytes] amount:frameCount];
}
else
} else
break;
}
[self setupWithInputFormat:previousOutputFormat outputFormat:outputFormat isLossless:rememberedLossless];
}
else
{
} else {
[self setupWithInputFormat:format outputFormat:outputFormat isLossless:rememberedLossless];
}
}
- (void)setRGInfo:(NSDictionary *)rgi
{
- (void)setRGInfo:(NSDictionary *)rgi {
DLog(@"Setting ReplayGain info");
rgInfo = rgi;
[self refreshVolumeScaling];
}
- (void)cleanUp
{
- (void)cleanUp {
stopping = YES;
while (convertEntered)
{
while(convertEntered) {
usleep(500);
}
if(hFilter) {
hFilter = nil;
}
if (hdcd_decoder)
{
if(hdcd_decoder) {
free(hdcd_decoder);
hdcd_decoder = NULL;
}
if (soxr)
{
if(soxr) {
soxr_delete(soxr);
soxr = NULL;
}
if (dsd2pcm && dsd2pcmCount)
{
for (size_t i = 0; i < dsd2pcmCount; ++i)
{
if(dsd2pcm && dsd2pcmCount) {
for(size_t i = 0; i < dsd2pcmCount; ++i) {
dsd2pcm_free(dsd2pcm[i]);
dsd2pcm[i] = NULL;
}
free(dsd2pcm);
dsd2pcm = NULL;
}
if (extrapolateBuffer)
{
if(extrapolateBuffer) {
free(extrapolateBuffer);
extrapolateBuffer = NULL;
extrapolateBufferSize = 0;
}
if (floatBuffer)
{
if(floatBuffer) {
free(floatBuffer);
floatBuffer = NULL;
floatBufferSize = 0;
@ -1151,8 +1040,7 @@ static float db_to_scale(float db)
floatSize = 0;
}
- (double) secondsBuffered
{
- (double)secondsBuffered {
return [buffer listDuration];
}

View file

@ -6,8 +6,8 @@
// Copyright 2022 __LoSnoCo__. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreAudio/CoreAudio.h>
#import <Foundation/Foundation.h>
#import "HeadphoneFilter.h"
@ -23,4 +23,3 @@
- (void)process:(const void *)inBuffer frameCount:(size_t)frames output:(void *)outBuffer;
@end

View file

@ -13,42 +13,56 @@
static const float STEREO_DOWNMIX[8 - 2][8][2] = {
/*3.0*/
{
{0.5858F,0.0F},{0.0F,0.5858F},{0.4142F,0.4142F}
},
{ 0.5858F, 0.0F },
{ 0.0F, 0.5858F },
{ 0.4142F, 0.4142F } },
/*quadrophonic*/
{
{0.4226F,0.0F},{0.0F,0.4226F},{0.366F,0.2114F},{0.2114F,0.336F}
},
{ 0.4226F, 0.0F },
{ 0.0F, 0.4226F },
{ 0.366F, 0.2114F },
{ 0.2114F, 0.336F } },
/*5.0*/
{
{0.651F,0.0F},{0.0F,0.651F},{0.46F,0.46F},{0.5636F,0.3254F},
{0.3254F,0.5636F}
},
{ 0.651F, 0.0F },
{ 0.0F, 0.651F },
{ 0.46F, 0.46F },
{ 0.5636F, 0.3254F },
{ 0.3254F, 0.5636F } },
/*5.1*/
{
{0.529F,0.0F},{0.0F,0.529F},{0.3741F,0.3741F},{0.3741F,0.3741F},{0.4582F,0.2645F},
{0.2645F,0.4582F}
},
{ 0.529F, 0.0F },
{ 0.0F, 0.529F },
{ 0.3741F, 0.3741F },
{ 0.3741F, 0.3741F },
{ 0.4582F, 0.2645F },
{ 0.2645F, 0.4582F } },
/*6.1*/
{
{0.4553F,0.0F},{0.0F,0.4553F},{0.322F,0.322F},{0.322F,0.322F},{0.2788F,0.2788F},
{0.3943F,0.2277F},{0.2277F,0.3943F}
},
{ 0.4553F, 0.0F },
{ 0.0F, 0.4553F },
{ 0.322F, 0.322F },
{ 0.322F, 0.322F },
{ 0.2788F, 0.2788F },
{ 0.3943F, 0.2277F },
{ 0.2277F, 0.3943F } },
/*7.1*/
{
{0.3886F,0.0F},{0.0F,0.3886F},{0.2748F,0.2748F},{0.2748F,0.2748F},{0.3366F,0.1943F},
{0.1943F,0.3366F},{0.3366F,0.1943F},{0.1943F,0.3366F}
}
{ 0.3886F, 0.0F },
{ 0.0F, 0.3886F },
{ 0.2748F, 0.2748F },
{ 0.2748F, 0.2748F },
{ 0.3366F, 0.1943F },
{ 0.1943F, 0.3366F },
{ 0.3366F, 0.1943F },
{ 0.1943F, 0.3366F } }
};
static void downmix_to_stereo(const float * inBuffer, int channels, float * outBuffer, size_t count)
{
static void downmix_to_stereo(const float *inBuffer, int channels, float *outBuffer, size_t count) {
if(channels >= 3 && channels <= 8)
for (size_t i = 0; i < count; ++i)
{
for(size_t i = 0; i < count; ++i) {
float left = 0, right = 0;
for (int j = 0; j < channels; ++j)
{
for(int j = 0; j < channels; ++j) {
left += inBuffer[i * channels + j] * STEREO_DOWNMIX[channels - 3][j][0];
right += inBuffer[i * channels + j] * STEREO_DOWNMIX[channels - 3][j][1];
}
@ -57,63 +71,48 @@ static void downmix_to_stereo(const float * inBuffer, int channels, float * outB
}
}
static void downmix_to_mono(const float * inBuffer, int channels, float * outBuffer, size_t count)
{
static void downmix_to_mono(const float *inBuffer, int channels, float *outBuffer, size_t count) {
float tempBuffer[count * 2];
if (channels >= 3 && channels <= 8)
{
if(channels >= 3 && channels <= 8) {
downmix_to_stereo(inBuffer, channels, tempBuffer, count);
inBuffer = tempBuffer;
channels = 2;
}
float invchannels = 1.0 / (float)channels;
for (size_t i = 0; i < count; ++i)
{
for(size_t i = 0; i < count; ++i) {
float sample = 0;
for (int j = 0; j < channels; ++j)
{
for(int j = 0; j < channels; ++j) {
sample += inBuffer[i * channels + j];
}
outBuffer[i] = sample * invchannels;
}
}
static void upmix(const float * inBuffer, int inchannels, float * outBuffer, int outchannels, size_t count)
{
for (ssize_t i = 0; i < count; ++i)
{
if (inchannels == 1 && outchannels == 2)
{
static void upmix(const float *inBuffer, int inchannels, float *outBuffer, int outchannels, size_t count) {
for(ssize_t i = 0; i < count; ++i) {
if(inchannels == 1 && outchannels == 2) {
// upmix mono to stereo
float sample = inBuffer[i];
outBuffer[i * 2 + 0] = sample;
outBuffer[i * 2 + 1] = sample;
}
else if (inchannels == 1 && outchannels == 4)
{
} else if(inchannels == 1 && outchannels == 4) {
// upmix mono to quad
float sample = inBuffer[i];
outBuffer[i * 4 + 0] = sample;
outBuffer[i * 4 + 1] = sample;
outBuffer[i * 4 + 2] = 0;
outBuffer[i * 4 + 3] = 0;
}
else if (inchannels == 1 && (outchannels == 3 || outchannels >= 5))
{
} else if(inchannels == 1 && (outchannels == 3 || outchannels >= 5)) {
// upmix mono to center channel
float sample = inBuffer[i];
outBuffer[i * outchannels + 2] = sample;
for (int j = 0; j < 2; ++j)
{
for(int j = 0; j < 2; ++j) {
outBuffer[i * outchannels + j] = 0;
}
for (int j = 3; j < outchannels; ++j)
{
for(int j = 3; j < outchannels; ++j) {
outBuffer[i * outchannels + j] = 0;
}
}
else if (inchannels == 4 && outchannels >= 5)
{
} else if(inchannels == 4 && outchannels >= 5) {
float fl = inBuffer[i * 4 + 0];
float fr = inBuffer[i * 4 + 1];
float bl = inBuffer[i * 4 + 2];
@ -123,17 +122,13 @@ static void upmix(const float * inBuffer, int inchannels, float * outBuffer, int
outBuffer[i * outchannels + 1] = fr;
outBuffer[i * outchannels + skipclfe + 2] = bl;
outBuffer[i * outchannels + skipclfe + 3] = br;
for (int j = 0; j < skipclfe; ++j)
{
for(int j = 0; j < skipclfe; ++j) {
outBuffer[i * outchannels + 2 + j] = 0;
}
for (int j = 4 + skipclfe; j < outchannels; ++j)
{
for(int j = 4 + skipclfe; j < outchannels; ++j) {
outBuffer[i * outchannels + j] = 0;
}
}
else if (inchannels == 5 && outchannels >= 6)
{
} else if(inchannels == 5 && outchannels >= 6) {
float fl = inBuffer[i * 5 + 0];
float fr = inBuffer[i * 5 + 1];
float c = inBuffer[i * 5 + 2];
@ -145,13 +140,10 @@ static void upmix(const float * inBuffer, int inchannels, float * outBuffer, int
outBuffer[i * outchannels + 3] = 0;
outBuffer[i * outchannels + 4] = bl;
outBuffer[i * outchannels + 5] = br;
for (int j = 6; j < outchannels; ++j)
{
for(int j = 6; j < outchannels; ++j) {
outBuffer[i * outchannels + j] = 0;
}
}
else if (inchannels == 7 && outchannels == 8)
{
} else if(inchannels == 7 && outchannels == 8) {
float fl = inBuffer[i * 7 + 0];
float fr = inBuffer[i * 7 + 1];
float c = inBuffer[i * 7 + 2];
@ -167,21 +159,16 @@ static void upmix(const float * inBuffer, int inchannels, float * outBuffer, int
outBuffer[i * 8 + 5] = bc;
outBuffer[i * 8 + 6] = sl;
outBuffer[i * 8 + 7] = sr;
}
else
{
} else {
// upmix N channels to N channels plus silence the empty channels
float samples[inchannels];
for (int j = 0; j < inchannels; ++j)
{
for(int j = 0; j < inchannels; ++j) {
samples[j] = inBuffer[i * inchannels + j];
}
for (int j = 0; j < inchannels; ++j)
{
for(int j = 0; j < inchannels; ++j) {
outBuffer[i * outchannels + j] = samples[j];
}
for (int j = inchannels; j < outchannels; ++j)
{
for(int j = inchannels; j < outchannels; ++j) {
outBuffer[i * outchannels + j] = 0;
}
}
@ -263,8 +250,7 @@ static void upmix(const float * inBuffer, int inchannels, float * outBuffer, int
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
context:(void *)context {
DLog(@"SOMETHING CHANGED!");
if([keyPath isEqualToString:@"values.headphoneVirtualization"] ||
[keyPath isEqualToString:@"values.hrirPath"]) {
@ -281,23 +267,15 @@ static void upmix(const float * inBuffer, int inchannels, float * outBuffer, int
}
}
if ( inputFormat.mChannelsPerFrame > 2 && outputFormat.mChannelsPerFrame == 2 )
{
if(inputFormat.mChannelsPerFrame > 2 && outputFormat.mChannelsPerFrame == 2) {
downmix_to_stereo((const float *)inBuffer, inputFormat.mChannelsPerFrame, (float *)outBuffer, frames);
}
else if ( inputFormat.mChannelsPerFrame > 1 && outputFormat.mChannelsPerFrame == 1 )
{
} else if(inputFormat.mChannelsPerFrame > 1 && outputFormat.mChannelsPerFrame == 1) {
downmix_to_mono((const float *)inBuffer, inputFormat.mChannelsPerFrame, (float *)outBuffer, frames);
}
else if ( inputFormat.mChannelsPerFrame < outputFormat.mChannelsPerFrame )
{
} else if(inputFormat.mChannelsPerFrame < outputFormat.mChannelsPerFrame) {
upmix((const float *)inBuffer, inputFormat.mChannelsPerFrame, (float *)outBuffer, outputFormat.mChannelsPerFrame, frames);
}
else if ( inputFormat.mChannelsPerFrame == outputFormat.mChannelsPerFrame )
{
} else if(inputFormat.mChannelsPerFrame == outputFormat.mChannelsPerFrame) {
memcpy(outBuffer, inBuffer, frames * outputFormat.mBytesPerPacket);
}
}
@end

View file

@ -8,8 +8,8 @@
#ifndef HeadphoneFilter_h
#define HeadphoneFilter_h
#import <Cocoa/Cocoa.h>
#import <Accelerate/Accelerate.h>
#import <Cocoa/Cocoa.h>
@interface HeadphoneFilter : NSObject {
FFTSetup fftSetup;

View file

@ -6,11 +6,11 @@
//
#import "HeadphoneFilter.h"
#import "AudioSource.h"
#import "AudioDecoder.h"
#import "AudioSource.h"
#import <soxr.h>
#import <mm_malloc.h>
#import <soxr.h>
#import "lpc.h"
#import "util.h"
@ -73,8 +73,7 @@ static const int8_t speakers_to_hesuvi_14[8][2][8] = {
return NO;
}
if (![decoder open:source])
{
if(![decoder open:source]) {
decoder = nil;
[source close];
source = nil;
@ -119,8 +118,7 @@ static const int8_t speakers_to_hesuvi_14[8][2][8] = {
return nil;
}
if (![decoder open:source])
{
if(![decoder open:source]) {
decoder = nil;
[source close];
source = nil;
@ -242,7 +240,10 @@ static const int8_t speakers_to_hesuvi_14[8][2][8] = {
fftSize = sampleCount + bufferSize;
int pow = 1;
while (fftSize > 2) { pow++; fftSize /= 2; }
while(fftSize > 2) {
pow++;
fftSize /= 2;
}
fftSize = 2 << pow;
float *deinterleavedImpulseBuffer = (float *)_mm_malloc(fftSize * sizeof(float) * impulseChannels, 16);
@ -322,8 +323,7 @@ static const int8_t speakers_to_hesuvi_14[8][2][8] = {
if(impulseChannels == 7) {
leftInChannel = speakers_to_hesuvi_7[channels - 1][0][i];
rightInChannel = speakers_to_hesuvi_7[channels - 1][1][i];
}
else {
} else {
leftInChannel = speakers_to_hesuvi_14[channels - 1][0][i];
rightInChannel = speakers_to_hesuvi_14[channels - 1][1][i];
}
@ -342,8 +342,7 @@ static const int8_t speakers_to_hesuvi_14[8][2][8] = {
vDSP_ctoz((DSPComplex *)temp, 2, &impulse_responses[i * 2 + 0], 1, fftSizeOver2);
vDSP_ctoz((DSPComplex *)temp, 2, &impulse_responses[i * 2 + 1], 1, fftSizeOver2);
}
else {
} else {
temp = (float *)malloc(sizeof(float) * fftSize * 2);
if(!temp) {
_mm_free(deinterleavedImpulseBuffer);
@ -361,8 +360,7 @@ static const int8_t speakers_to_hesuvi_14[8][2][8] = {
}
free(temp);
}
else {
} else {
vDSP_ctoz((DSPComplex *)(deinterleavedImpulseBuffer + leftInChannel * fftSize), 2, &impulse_responses[i * 2 + 0], 1, fftSizeOver2);
vDSP_ctoz((DSPComplex *)(deinterleavedImpulseBuffer + rightInChannel * fftSize), 2, &impulse_responses[i * 2 + 1], 1, fftSizeOver2);
}

View file

@ -8,9 +8,9 @@
#import <Cocoa/Cocoa.h>
#import <CoreAudio/AudioHardware.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <CoreAudio/AudioHardware.h>
#import "AudioDecoder.h"
#import "Node.h"

View file

@ -7,19 +7,17 @@
//
#import "InputNode.h"
#import "BufferChain.h"
#import "Plugin.h"
#import "CoreAudioUtils.h"
#import "AudioPlayer.h"
#import "BufferChain.h"
#import "CoreAudioUtils.h"
#import "OutputNode.h"
#import "Plugin.h"
#import "Logging.h"
@implementation InputNode
@synthesize exitAtTheEndOfTheStream;
- (id)initWithController:(id)c previous:(id)p {
self = [super initWithController:c previous:p];
if(self) {
@ -29,9 +27,7 @@
return self;
}
- (BOOL)openWithSource:(id<CogSource>)source
{
- (BOOL)openWithSource:(id<CogSource>)source {
decoder = [AudioDecoder audioDecoderForSource:source];
if(decoder == nil)
@ -39,8 +35,7 @@
[self registerObservers];
if (![decoder open:source])
{
if(![decoder open:source]) {
ALog(@"Couldn't open decoder...");
return NO;
}
@ -60,8 +55,7 @@
return YES;
}
- (BOOL)openWithDecoder:(id<CogDecoder>) d
{
- (BOOL)openWithDecoder:(id<CogDecoder>)d {
DLog(@"Opening with old decoder: %@", d);
decoder = d;
@ -83,9 +77,7 @@
return YES;
}
- (void)registerObservers
{
- (void)registerObservers {
DLog(@"REGISTERING OBSERVERS");
[decoder addObserver:self
forKeyPath:@"properties"
@ -103,8 +95,7 @@
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
context:(void *)context {
DLog(@"SOMETHING CHANGED!");
if([keyPath isEqual:@"properties"]) {
DLog(@"Input format changed");
@ -112,24 +103,20 @@
NSDictionary *properties = [decoder properties];
nodeFormat = propertiesToASBD(properties);
nodeLossless = [[properties valueForKey:@"encoding"] isEqualToString:@"lossless"];
}
else if ([keyPath isEqual:@"metadata"]) {
} else if([keyPath isEqual:@"metadata"]) {
// Inform something of metadata change
}
}
- (void)process
{
- (void)process {
int amountInBuffer = 0;
void *inputBuffer = malloc(CHUNK_SIZE);
BOOL shouldClose = YES;
BOOL seekError = NO;
while ([self shouldContinue] == YES && [self endOfStream] == NO)
{
if (shouldSeek == YES)
{
while([self shouldContinue] == YES && [self endOfStream] == NO) {
if(shouldSeek == YES) {
ConverterNode *converter = [[[controller controller] bufferChain] converter];
DLog(@"SEEKING! Resetting Buffer");
@ -153,14 +140,11 @@
int framesToRead = (CHUNK_SIZE - amountInBuffer) / bytesPerFrame;
int framesRead = [decoder readAudio:((char *)inputBuffer) + amountInBuffer frames:framesToRead];
if (framesRead > 0 && !seekError)
{
if(framesRead > 0 && !seekError) {
amountInBuffer += (framesRead * bytesPerFrame);
[self writeData:inputBuffer amount:amountInBuffer];
amountInBuffer = 0;
}
else
{
} else {
if(initialBufferFilled == NO) {
[controller initialBufferFilled:self];
}
@ -174,15 +158,12 @@
// wait before exiting, as we might still get seeking request
DLog("InputNode: Before wait")
[exitAtTheEndOfTheStream waitIndefinitely];
DLog("InputNode: After wait, should seek = %d", shouldSeek)
if (shouldSeek)
{
DLog("InputNode: After wait, should seek = %d", shouldSeek) if(shouldSeek) {
endOfStream = NO;
shouldClose = NO;
continue;
}
else
{
else {
break;
}
}
@ -199,21 +180,18 @@
DLog("Input node thread stopping");
}
- (void)seek:(long)frame
{
- (void)seek:(long)frame {
seekFrame = frame;
shouldSeek = YES;
DLog(@"Should seek!");
[semaphore signal];
if (endOfStream)
{
if(endOfStream) {
[exitAtTheEndOfTheStream signal];
}
}
- (BOOL)setTrack:(NSURL *)track
{
- (BOOL)setTrack:(NSURL *)track {
if([decoder respondsToSelector:@selector(setTrack:)] && [decoder setTrack:track]) {
DLog(@"SET TRACK!");
@ -223,41 +201,34 @@
return NO;
}
- (void)removeObservers
{
if (observersAdded)
{
- (void)removeObservers {
if(observersAdded) {
[decoder removeObserver:self forKeyPath:@"properties"];
[decoder removeObserver:self forKeyPath:@"metadata"];
observersAdded = NO;
}
}
- (void)setShouldContinue:(BOOL)s
{
- (void)setShouldContinue:(BOOL)s {
[super setShouldContinue:s];
if(!s)
[self removeObservers];
}
- (void)dealloc
{
- (void)dealloc {
DLog(@"Input Node dealloc");
[self removeObservers];
}
- (NSDictionary *) properties
{
- (NSDictionary *)properties {
return [decoder properties];
}
- (id<CogDecoder>) decoder
{
- (id<CogDecoder>)decoder {
return decoder;
}
- (double) secondsBuffered
{
- (double)secondsBuffered {
return [buffer listDuration];
}

View file

@ -6,9 +6,9 @@
// Copyright 2006 Vincent Spader. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "ChunkList.h"
#import "Semaphore.h"
#import <Cocoa/Cocoa.h>
#define BUFFER_SIZE 1024 * 1024
#define CHUNK_SIZE 16 * 1024

View file

@ -8,16 +8,14 @@
#import "Node.h"
#import "Logging.h"
#import "BufferChain.h"
#import "Logging.h"
@implementation Node
- (id)initWithController:(id)c previous:(id)p
{
- (id)initWithController:(id)c previous:(id)p {
self = [super init];
if (self)
{
if(self) {
buffer = [[ChunkList alloc] initWithMaximumDuration:3.0];
semaphore = [[Semaphore alloc] init];
@ -37,18 +35,15 @@
return self;
}
- (AudioStreamBasicDescription)nodeFormat
{
- (AudioStreamBasicDescription)nodeFormat {
return nodeFormat;
}
- (BOOL)nodeLossless
{
- (BOOL)nodeLossless {
return nodeLossless;
}
- (void)writeData:(const void *)ptr amount:(size_t)amount
{
- (void)writeData:(const void *)ptr amount:(size_t)amount {
[accessLock lock];
AudioChunk *chunk = [[AudioChunk alloc] init];
@ -59,8 +54,7 @@
const double chunkDuration = [chunk duration];
double durationLeft = [buffer maxDuration] - [buffer listDuration];
while (shouldContinue == YES && chunkDuration > durationLeft)
{
while(shouldContinue == YES && chunkDuration > durationLeft) {
if(durationLeft < chunkDuration) {
if(initialBufferFilled == NO) {
initialBufferFilled = YES;
@ -84,23 +78,19 @@
}
// Should be overwriten by subclass.
- (void)process
{
- (void)process {
}
- (void)threadEntry:(id)arg
{
- (void)threadEntry:(id)arg {
@autoreleasepool {
[self process];
}
}
- (AudioChunk *)readChunk:(size_t)maxFrames
{
- (AudioChunk *)readChunk:(size_t)maxFrames {
[accessLock lock];
if ([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES)
{
if([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES) {
endOfStream = YES;
[accessLock unlock];
return [[AudioChunk alloc] init];
@ -119,46 +109,38 @@
[accessLock unlock];
if ([ret frameCount])
{
if([ret frameCount]) {
[[previousNode semaphore] signal];
}
return ret;
}
- (void)launchThread
{
- (void)launchThread {
[NSThread detachNewThreadSelector:@selector(threadEntry:) toTarget:self withObject:nil];
}
- (void)setPreviousNode:(id)p
{
- (void)setPreviousNode:(id)p {
previousNode = p;
}
- (id)previousNode
{
- (id)previousNode {
return previousNode;
}
- (BOOL)shouldContinue
{
- (BOOL)shouldContinue {
return shouldContinue;
}
- (void)setShouldContinue:(BOOL)s
{
- (void)setShouldContinue:(BOOL)s {
shouldContinue = s;
}
- (ChunkList *)buffer
{
- (ChunkList *)buffer {
return buffer;
}
- (void)resetBuffer
{
- (void)resetBuffer {
shouldReset = YES; // Will reset on next write.
if(previousNode == nil) {
[accessLock lock];
@ -167,35 +149,28 @@
}
}
- (Semaphore *)semaphore
{
- (Semaphore *)semaphore {
return semaphore;
}
- (BOOL)endOfStream
{
- (BOOL)endOfStream {
return endOfStream;
}
- (void)setEndOfStream:(BOOL)e
{
- (void)setEndOfStream:(BOOL)e {
endOfStream = e;
}
- (void)setShouldReset:(BOOL)s
{
- (void)setShouldReset:(BOOL)s {
shouldReset = s;
}
- (BOOL)shouldReset
{
- (BOOL)shouldReset {
return shouldReset;
}
// Buffering nodes should implement this
- (double)secondsBuffered
{
- (double)secondsBuffered {
return 0.0;
}
@end

View file

@ -8,9 +8,9 @@
#import <Cocoa/Cocoa.h>
#import <CoreAudio/AudioHardware.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <CoreAudio/AudioHardware.h>
#import "Node.h"
#import "OutputCoreAudio.h"

View file

@ -7,16 +7,15 @@
//
#import "OutputNode.h"
#import "OutputCoreAudio.h"
#import "AudioPlayer.h"
#import "BufferChain.h"
#import "OutputCoreAudio.h"
#import "Logging.h"
@implementation OutputNode
- (void)setup
{
- (void)setup {
amountPlayed = 0.0;
sampleRatio = 0.0;
@ -28,59 +27,49 @@
[output setup];
}
- (void)seek:(double)time
{
- (void)seek:(double)time {
// [output pause];
[self resetBuffer];
amountPlayed = time;
}
- (void)process
{
- (void)process {
paused = NO;
[output start];
}
- (void)pause
{
- (void)pause {
paused = YES;
[output pause];
}
- (void)resume
{
- (void)resume {
paused = NO;
[output resume];
}
- (void)incrementAmountPlayed:(double)seconds
{
- (void)incrementAmountPlayed:(double)seconds {
amountPlayed += seconds;
}
- (void)resetAmountPlayed
{
- (void)resetAmountPlayed {
amountPlayed = 0;
}
- (void)endOfInputPlayed
{
- (void)endOfInputPlayed {
[controller endOfInputPlayed];
}
- (BOOL)chainQueueHasTracks
{
- (BOOL)chainQueueHasTracks {
return [controller chainQueueHasTracks];
}
- (double)secondsBuffered
{
- (double)secondsBuffered {
return [buffer listDuration];
}
- (AudioChunk *)readChunk:(size_t)amount
{
- (AudioChunk *)readChunk:(size_t)amount {
@autoreleasepool {
[self setPreviousNode:[[controller bufferChain] finalNode]];
@ -94,28 +83,23 @@
}
}
- (double)amountPlayed
{
- (double)amountPlayed {
return amountPlayed;
}
- (AudioStreamBasicDescription) format
{
- (AudioStreamBasicDescription)format {
return format;
}
- (void)setFormat:(AudioStreamBasicDescription *)f
{
- (void)setFormat:(AudioStreamBasicDescription *)f {
format = *f;
// Calculate a ratio and add to double(seconds) instead, as format may change
// double oldSampleRatio = sampleRatio;
sampleRatio = 1.0 / (format.mSampleRate * format.mBytesPerPacket);
BufferChain *bufferChain = [controller bufferChain];
if (bufferChain)
{
if(bufferChain) {
ConverterNode *converter = [bufferChain converter];
if (converter)
{
if(converter) {
// This clears the resampler buffer, but not the input buffer
// We also have to jump the play position ahead accounting for
// the data we are flushing
@ -132,47 +116,39 @@
}
}
- (void)close
{
- (void)close {
[output stop];
output = nil;
}
- (void)setVolume:(double) v
{
- (void)setVolume:(double)v {
[output setVolume:v];
}
- (void)setShouldContinue:(BOOL)s
{
- (void)setShouldContinue:(BOOL)s {
[super setShouldContinue:s];
// if (s == NO)
// [output stop];
}
- (BOOL)isPaused
{
- (BOOL)isPaused {
return paused;
}
- (void)beginEqualizer:(AudioUnit)eq
{
- (void)beginEqualizer:(AudioUnit)eq {
[controller beginEqualizer:eq];
}
- (void)refreshEqualizer:(AudioUnit)eq
{
- (void)refreshEqualizer:(AudioUnit)eq {
[controller refreshEqualizer:eq];
}
- (void)endEqualizer:(AudioUnit)eq
{
- (void)endEqualizer:(AudioUnit)eq {
[controller endEqualizer:eq];
}
- (void)sustainHDCD
{
- (void)sustainHDCD {
[output sustainHDCD];
}

View file

@ -8,9 +8,9 @@
#import <Cocoa/Cocoa.h>
#import <CoreAudio/AudioHardware.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <CoreAudio/AudioHardware.h>
#import "Node.h"
#import "Plugin.h"

View file

@ -6,18 +6,16 @@
// Copyright 2022 __LoSnoCo__. All rights reserved.
//
#import "Plugin.h"
#import "RefillNode.h"
#import "Plugin.h"
#import "Logging.h"
@implementation RefillNode
- (id)initWithController:(id)c previous:(id)p
{
- (id)initWithController:(id)c previous:(id)p {
self = [super init];
if (self)
{
if(self) {
// This special node should be able to handle up to four buffers
buffer = [[ChunkList alloc] initWithMaximumDuration:12.0];
semaphore = [[Semaphore alloc] init];
@ -36,13 +34,11 @@
return self;
}
- (void)dealloc
{
- (void)dealloc {
DLog(@"Refill Node dealloc");
}
- (void)setFormat:(AudioStreamBasicDescription)format
{
- (void)setFormat:(AudioStreamBasicDescription)format {
nodeFormat = format;
}

View file

@ -6,8 +6,8 @@
//
//
#import <Cocoa/Cocoa.h>
#import "Plugin.h"
#import <Cocoa/Cocoa.h>
@interface CogDecoderMulti : NSObject <CogDecoder> {
NSArray *theDecoders;

View file

@ -8,12 +8,10 @@
#import "CogPluginMulti.h"
NSArray * sortClassesByPriority(NSArray * theClasses)
{
NSArray *sortClassesByPriority(NSArray *theClasses) {
NSMutableArray *sortedClasses = [NSMutableArray arrayWithArray:theClasses];
[sortedClasses sortUsingComparator:
^NSComparisonResult(id obj1, id obj2)
{
^NSComparisonResult(id obj1, id obj2) {
NSString *classString1 = (NSString *)obj1;
NSString *classString2 = (NSString *)obj2;
@ -23,27 +21,27 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
float priority1 = [class1 priority];
float priority2 = [class2 priority];
if (priority1 == priority2) return NSOrderedSame;
else if (priority1 > priority2) return NSOrderedAscending;
else return NSOrderedDescending;
if(priority1 == priority2)
return NSOrderedSame;
else if(priority1 > priority2)
return NSOrderedAscending;
else
return NSOrderedDescending;
}];
return sortedClasses;
}
@implementation CogDecoderMulti
+ (NSArray *)mimeTypes
{
+ (NSArray *)mimeTypes {
return nil;
}
+ (NSArray *)fileTypes
{
+ (NSArray *)fileTypes {
return nil;
}
+ (float)priority
{
+ (float)priority {
return -1.0;
}
@ -51,11 +49,9 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
return nil;
}
- (id)initWithDecoders:(NSArray *)decoders
{
- (id)initWithDecoders:(NSArray *)decoders {
self = [super init];
if ( self )
{
if(self) {
theDecoders = sortClassesByPriority(decoders);
theDecoder = nil;
cachedObservers = [[NSMutableArray alloc] init];
@ -63,22 +59,18 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
return self;
}
- (NSDictionary *)properties
{
- (NSDictionary *)properties {
if(theDecoder != nil) return [theDecoder properties];
return nil;
}
- (int)readAudio:(void *)buffer frames:(UInt32)frames
{
- (int)readAudio:(void *)buffer frames:(UInt32)frames {
if(theDecoder != nil) return [theDecoder readAudio:buffer frames:frames];
return 0;
}
- (BOOL)open:(id<CogSource>)source
{
for (NSString *classString in theDecoders)
{
- (BOOL)open:(id<CogSource>)source {
for(NSString *classString in theDecoders) {
Class decoder = NSClassFromString(classString);
theDecoder = [[decoder alloc] init];
for(NSDictionary *obsItem in cachedObservers) {
@ -99,14 +91,12 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
return NO;
}
- (long)seek:(long)frame
{
- (long)seek:(long)frame {
if(theDecoder != nil) return [theDecoder seek:frame];
return -1;
}
- (void)close
{
- (void)close {
if(theDecoder != nil) {
for(NSDictionary *obsItem in cachedObservers) {
[theDecoder removeObserver:[obsItem objectForKey:@"observer"] forKeyPath:[obsItem objectForKey:@"keyPath"]];
@ -117,15 +107,13 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
}
}
- (BOOL)setTrack:(NSURL *)track
{
- (BOOL)setTrack:(NSURL *)track {
if(theDecoder != nil && [theDecoder respondsToSelector:@selector(setTrack:)]) return [theDecoder setTrack:track];
return NO;
}
/* By the current design, the core adds its observers to decoders before they are opened */
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context {
if(context != nil) {
[cachedObservers addObject:[NSDictionary dictionaryWithObjectsAndKeys:observer, @"observer", keyPath, @"keyPath", @(options), @"options", context, @"context", nil]];
} else {
@ -137,8 +125,7 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
}
/* And this is currently called after the decoder is closed */
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
{
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath {
for(NSDictionary *obsItem in cachedObservers) {
if([obsItem objectForKey:@"observer"] == observer && [keyPath isEqualToString:[obsItem objectForKey:@"keyPath"]]) {
[cachedObservers removeObject:obsItem];
@ -150,16 +137,13 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
}
}
@end
@implementation CogContainerMulti
+ (NSArray *)urlsForContainerURL:(NSURL *)url containers:(NSArray *)containers
{
+ (NSArray *)urlsForContainerURL:(NSURL *)url containers:(NSArray *)containers {
NSArray *sortedContainers = sortClassesByPriority(containers);
for (NSString *classString in sortedContainers)
{
for(NSString *classString in sortedContainers) {
Class container = NSClassFromString(classString);
NSArray *urls = [container urlsForContainerURL:url];
if([urls count])
@ -172,11 +156,9 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
@implementation CogMetadataReaderMulti
+ (NSDictionary *)metadataForURL:(NSURL *)url readers:(NSArray *)readers
{
+ (NSDictionary *)metadataForURL:(NSURL *)url readers:(NSArray *)readers {
NSArray *sortedReaders = sortClassesByPriority(readers);
for (NSString *classString in sortedReaders)
{
for(NSString *classString in sortedReaders) {
Class reader = NSClassFromString(classString);
NSDictionary *data = [reader metadataForURL:url];
if([data count])
@ -189,11 +171,9 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
@implementation CogPropertiesReaderMulti
+ (NSDictionary *)propertiesForSource:(id<CogSource>)source readers:(NSArray *)readers
{
+ (NSDictionary *)propertiesForSource:(id<CogSource>)source readers:(NSArray *)readers {
NSArray *sortedReaders = sortClassesByPriority(readers);
for (NSString *classString in sortedReaders)
{
for(NSString *classString in sortedReaders) {
Class reader = NSClassFromString(classString);
NSDictionary *data = [reader propertiesForSource:source];
if([data count])

View file

@ -7,21 +7,19 @@
*
*/
#include <math.h>
#include "Helper.h"
#include <math.h>
// These functions are helpers for the process of converting volume from a linear to logarithmic scale.
// Numbers that goes in to audioPlayer should be logarithmic. Numbers that are displayed to the user should be linear.
// Here's why: http://www.dr-lex.34sp.com/info-stuff/volumecontrols.html
// We are using the approximation of X^4.
// Input/Output values are in percents.
double logarithmicToLinear(double logarithmic, double MAX_VOLUME)
{
double logarithmicToLinear(double logarithmic, double MAX_VOLUME) {
return (MAX_VOLUME == 100.0) ? logarithmic : pow((logarithmic / MAX_VOLUME), 0.25) * 100.0;
}
double linearToLogarithmic(double linear, double MAX_VOLUME)
{
double linearToLogarithmic(double linear, double MAX_VOLUME) {
return (MAX_VOLUME == 100.0) ? linear : (linear / 100.0) * (linear / 100.0) * (linear / 100.0) * (linear / 100.0) * MAX_VOLUME;
}
// End helper volume function thingies. ONWARDS TO GLORY!

View file

@ -9,10 +9,10 @@
#import <AssertMacros.h>
#import <Cocoa/Cocoa.h>
#import <CoreAudio/AudioHardware.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/AudioHardware.h>
#import <CoreAudio/CoreAudioTypes.h>
#import <stdatomic.h>

View file

@ -17,16 +17,13 @@ static NSString *CogPlaybackDidBeginNotficiation = @"CogPlaybackDidBeginNotficia
@implementation OutputCoreAudio
static void fillBuffers(AudioBufferList *ioData, float * inbuffer, size_t count, size_t offset)
{
static void fillBuffers(AudioBufferList *ioData, float *inbuffer, size_t count, size_t offset) {
const size_t channels = ioData->mNumberBuffers;
for (int i = 0; i < channels; ++i)
{
for(int i = 0; i < channels; ++i) {
const size_t maxCount = (ioData->mBuffers[i].mDataByteSize / sizeof(float)) - offset;
float *output = ((float *)ioData->mBuffers[i].mData) + offset;
const float *input = inbuffer + i;
for (size_t j = 0, k = (count > maxCount) ? maxCount : count; j < k; ++j)
{
for(size_t j = 0, k = (count > maxCount) ? maxCount : count; j < k; ++j) {
*output = *input;
output++;
input += channels;
@ -35,28 +32,22 @@ static void fillBuffers(AudioBufferList *ioData, float * inbuffer, size_t count,
}
}
static void clearBuffers(AudioBufferList *ioData, size_t count, size_t offset)
{
for (int i = 0; i < ioData->mNumberBuffers; ++i)
{
static void clearBuffers(AudioBufferList *ioData, size_t count, size_t offset) {
for(int i = 0; i < ioData->mNumberBuffers; ++i) {
memset(ioData->mBuffers[i].mData + offset * sizeof(float), 0, count * sizeof(float));
ioData->mBuffers[i].mNumberChannels = 1;
}
}
static void scaleBuffersByVolume(AudioBufferList *ioData, float volume)
{
if (volume != 1.0)
{
for (int i = 0; i < ioData->mNumberBuffers; ++i)
{
static void scaleBuffersByVolume(AudioBufferList *ioData, float volume) {
if(volume != 1.0) {
for(int i = 0; i < ioData->mNumberBuffers; ++i) {
scale_by_volume((float *)ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize / sizeof(float), volume);
}
}
}
static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData )
{
static OSStatus renderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) {
OutputCoreAudio *_self = (__bridge OutputCoreAudio *)inRefCon;
const int channels = _self->deviceFormat.mChannelsPerFrame;
@ -66,8 +57,7 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
amountToRead = inNumberFrames * bytesPerPacket;
if (_self->stopping == YES || [_self->outputController shouldContinue] == NO)
{
if(_self->stopping == YES || [_self->outputController shouldContinue] == NO) {
// Chain is dead, fill out the serial number pointer forever with silence
clearBuffers(ioData, amountToRead / bytesPerPacket, 0);
atomic_fetch_add(&_self->bytesRendered, amountToRead);
@ -75,8 +65,7 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
return 0;
}
if ([[_self->outputController buffer] isEmpty] && ![_self->outputController chainQueueHasTracks])
{
if([[_self->outputController buffer] isEmpty] && ![_self->outputController chainQueueHasTracks]) {
// Hit end of last track, pad with silence until queue event stops us
clearBuffers(ioData, amountToRead / bytesPerPacket, 0);
atomic_fetch_add(&_self->bytesRendered, amountToRead);
@ -111,8 +100,7 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
// Try repeatedly! Buffer wraps can cause a slight data shortage, as can
// unexpected track changes.
while ((amountRead < amountToRead) && [_self->outputController shouldContinue] == YES)
{
while((amountRead < amountToRead) && [_self->outputController shouldContinue] == YES) {
chunk = [[_self->outputController buffer] removeSamples:((amountToRead - amountRead) / bytesPerPacket)];
frameCount = [chunk frameCount];
format = [chunk format];
@ -133,8 +121,7 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
amountRead += frameCount * bytesPerPacket;
[_self->writeSemaphore signal];
}
else {
} else {
[_self->readSemaphore timedWait:500];
}
}
@ -144,8 +131,7 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
if(sustained) {
if(sustained < amountRead) {
atomic_store(&_self->bytesHdcdSustained, 0);
}
else {
} else {
atomic_fetch_sub(&_self->bytesHdcdSustained, amountRead);
}
volumeScale = 0.5;
@ -153,8 +139,7 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
scaleBuffersByVolume(ioData, _self->volume * volumeScale);
if (amountRead < amountToRead)
{
if(amountRead < amountToRead) {
// Either underrun, or no data at all. Caller output tends to just
// buffer loop if it doesn't get anything, so always produce a full
// buffer, and silence anything we couldn't supply.
@ -164,11 +149,9 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
return 0;
};
- (id)initWithController:(OutputNode *)c
{
- (id)initWithController:(OutputNode *)c {
self = [super init];
if (self)
{
if(self) {
outputController = c;
_au = nil;
_eq = NULL;
@ -197,35 +180,29 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
}
static OSStatus
default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData)
{
default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData) {
OutputCoreAudio *this = (__bridge OutputCoreAudio *)inUserData;
return [this setOutputDeviceByID:-1];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([keyPath isEqualToString:@"values.outputDevice"]) {
NSDictionary *device = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"outputDevice"];
[self setOutputDeviceWithDeviceDict:device];
}
else if ([keyPath isEqualToString:@"values.GraphicEQenable"]) {
} else if([keyPath isEqualToString:@"values.GraphicEQenable"]) {
BOOL enabled = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"GraphicEQenable"] boolValue];
[self setEqualizerEnabled:enabled];
}
}
- (void)signalEndOfStream
{
- (void)signalEndOfStream {
[outputController resetAmountPlayed];
[outputController endOfInputPlayed];
}
- (void)threadEntry:(id)arg
{
- (void)threadEntry:(id)arg {
running = YES;
started = NO;
stopNext = NO;
@ -254,8 +231,8 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
delayedEventsPopped = YES;
[self signalEndOfStream];
[delayedEvents removeObjectAtIndex:0];
}
else break;
} else
break;
}
if(stopping)
@ -274,8 +251,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
if(frameCount) {
[readSemaphore signal];
continue;
}
else if ([outputController shouldContinue] == NO)
} else if([outputController shouldContinue] == NO)
break;
else if([[outputController buffer] isFull]) {
if(!started) {
@ -285,22 +261,18 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
[_au startHardwareAndReturnError:&err];
}
}
}
else {
} else {
// End of input possibly reached
if (delayedEventsPopped && [outputController endOfStream] == YES)
{
if(delayedEventsPopped && [outputController endOfStream] == YES) {
double secondsBuffered = [[outputController buffer] listDuration];
size_t _bytesRendered = atomic_load_explicit(&bytesRendered, memory_order_relaxed);
secondsBuffered += (double)_bytesRendered / (double)(deviceFormat.mBytesPerPacket * deviceFormat.mSampleRate);
if ([outputController chainQueueHasTracks])
{
if([outputController chainQueueHasTracks]) {
if(secondsBuffered <= 0.005)
secondsBuffered = 0.0;
else
secondsBuffered -= 0.005;
}
else {
} else {
stopNext = YES;
break;
}
@ -323,8 +295,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
[self stop];
}
- (OSStatus)setOutputDeviceByID:(AudioDeviceID)deviceID
{
- (OSStatus)setOutputDeviceByID:(AudioDeviceID)deviceID {
OSStatus err;
BOOL defaultDevice = NO;
AudioObjectPropertyAddress theAddress = {
@ -368,8 +339,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &defaultDeviceAddress, default_device_changed, (__bridge void *_Nullable)(self));
listenerapplied = YES;
}
}
else {
} else {
err = noErr;
}
@ -382,8 +352,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
return err;
}
- (BOOL)setOutputDeviceWithDeviceDict:(NSDictionary *)deviceDict
{
- (BOOL)setOutputDeviceWithDeviceDict:(NSDictionary *)deviceDict {
NSNumber *deviceIDNum = [deviceDict objectForKey:@"deviceID"];
AudioDeviceID outputDeviceID = [deviceIDNum unsignedIntValue] ?: -1;
@ -416,7 +385,6 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
}
if(err != noErr) {
ALog(@"No output device could be found, your random error code is %d. Have a nice day!", err);
return NO;
@ -427,8 +395,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
// The following is largely a copy pasta of -awakeFromNib from "OutputsArrayController.m".
// TODO: Share the code. (How to do this across xcodeproj?)
- (void)enumerateAudioOutputsUsingBlock:(void (NS_NOESCAPE ^ _Nonnull)(NSString *deviceName, AudioDeviceID deviceID, AudioDeviceID systemDefaultID, BOOL *stop))block
{
- (void)enumerateAudioOutputsUsingBlock:(void(NS_NOESCAPE ^ _Nonnull)(NSString *deviceName, AudioDeviceID deviceID, AudioDeviceID systemDefaultID, BOOL *stop))block {
UInt32 propsize;
AudioObjectPropertyAddress theAddress = {
.mSelector = kAudioHardwarePropertyDevices,
@ -489,12 +456,10 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
free(devids);
}
- (BOOL)updateDeviceFormat
{
- (BOOL)updateDeviceFormat {
AVAudioFormat *format = _au.outputBusses[0].format;
if (!_deviceFormat || ![_deviceFormat isEqual:format])
{
if(!_deviceFormat || ![_deviceFormat isEqual:format]) {
NSError *err;
AVAudioFormat *renderFormat;
@ -571,8 +536,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
return YES;
}
- (BOOL)setup
{
- (BOOL)setup {
if(_au)
[self stop];
@ -609,8 +573,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
[[[NSUserDefaultsController sharedUserDefaultsController] defaults] removeObjectForKey:@"outputDevice"];
}
}
else {
} else {
[self setOutputDeviceWithDeviceDict:nil];
}
@ -640,8 +603,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
__block FILE *logFile = _logFile;
#endif
_au.outputProvider = ^AUAudioUnitStatus(AudioUnitRenderActionFlags * _Nonnull actionFlags, const AudioTimeStamp * _Nonnull timestamp, AUAudioFrameCount frameCount, NSInteger inputBusNumber, AudioBufferList * _Nonnull inputData)
{
_au.outputProvider = ^AUAudioUnitStatus(AudioUnitRenderActionFlags *_Nonnull actionFlags, const AudioTimeStamp *_Nonnull timestamp, AUAudioFrameCount frameCount, NSInteger inputBusNumber, AudioBufferList *_Nonnull inputData) {
// This expects multiple buffers, so:
int i;
const int channels = format->mChannelsPerFrame;
@ -733,13 +695,11 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
return (err == nil);
}
- (void)setVolume:(double)v
{
- (void)setVolume:(double)v {
volume = v * 0.01f;
}
- (void)setEqualizerEnabled:(BOOL)enabled
{
- (void)setEqualizerEnabled:(BOOL)enabled {
if(enabled && !eqEnabled) {
if(_eq) {
AudioUnitReset(_eq, kAudioUnitScope_Input, 0);
@ -751,13 +711,11 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
eqEnabled = enabled;
}
- (void)start
{
- (void)start {
[self threadEntry:nil];
}
- (void)stop
{
- (void)stop {
stopInvoked = YES;
if(observersapplied) {
observersapplied = NO;
@ -794,25 +752,21 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
_au = nil;
}
if(running)
while (!stopped)
{
while(!stopped) {
stopping = YES;
[readSemaphore signal];
[writeSemaphore timedWait:5000];
}
if (_eq)
{
if(_eq) {
// This takes the EQ and frees it after disposing of any present UIs
[outputController endEqualizer:_eq];
_eq = NULL;
}
if (downmixer)
{
if(downmixer) {
downmixer = nil;
}
#ifdef OUTPUT_LOG
if (_logFile)
{
if(_logFile) {
fclose(_logFile);
_logFile = NULL;
}
@ -820,29 +774,25 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
outputController = nil;
}
- (void)dealloc
{
- (void)dealloc {
if(!stopInvoked)
[self stop];
}
- (void)pause
{
- (void)pause {
paused = YES;
if(started)
[_au stopHardware];
}
- (void)resume
{
- (void)resume {
NSError *err;
[_au startHardwareAndReturnError:&err];
paused = NO;
started = YES;
}
- (void)sustainHDCD
{
- (void)sustainHDCD {
atomic_store(&bytesHdcdSustained, deviceFormat.mSampleRate * 10 * sizeof(float) * 2);
}

View file

@ -95,6 +95,3 @@
- (int)putMetadataInURL:(NSURL *)url;
@end

View file

@ -5,8 +5,7 @@
#import "Plugin.h"
// Singletonish
@interface PluginController : NSObject <CogPluginController>
{
@interface PluginController : NSObject <CogPluginController> {
NSMutableDictionary *sources;
NSMutableDictionary *containers;
NSMutableDictionary *metadataReaders;

View file

@ -1,6 +1,6 @@
#import "PluginController.h"
#import "Plugin.h"
#import "CogPluginMulti.h"
#import "Plugin.h"
#import "Logging.h"
@ -22,8 +22,7 @@
static PluginController *sharedPluginController = nil;
+ (id<CogPluginController>)sharedPluginController
{
+ (id<CogPluginController>)sharedPluginController {
@synchronized(self) {
if(sharedPluginController == nil) {
sharedPluginController = [[self alloc] init];
@ -33,7 +32,6 @@ static PluginController *sharedPluginController = nil;
return sharedPluginController;
}
- (id)init {
self = [super init];
if(self) {
@ -54,8 +52,7 @@ static PluginController *sharedPluginController = nil;
return self;
}
- (void)setup
{
- (void)setup {
if(self.configured == NO) {
self.configured = YES;
@ -66,23 +63,19 @@ static PluginController *sharedPluginController = nil;
}
}
- (void)bundleDidLoad:(NSNotification *)notification
{
- (void)bundleDidLoad:(NSNotification *)notification {
NSArray *classNames = [[notification userInfo] objectForKey:@"NSLoadedClasses"];
for (NSString *className in classNames)
{
for(NSString *className in classNames) {
Class bundleClass = NSClassFromString(className);
if([bundleClass conformsToProtocol:@protocol(CogVersionCheck)]) {
DLog(@"Component has version check: %@", className);
if (![bundleClass shouldLoadForOSVersion:[[NSProcessInfo processInfo] operatingSystemVersion]])
{
if(![bundleClass shouldLoadForOSVersion:[[NSProcessInfo processInfo] operatingSystemVersion]]) {
DLog(@"Plugin fails OS version check, ignoring");
return;
}
}
}
for (NSString *className in classNames)
{
for(NSString *className in classNames) {
DLog(@"Class loaded: %@", className);
Class bundleClass = NSClassFromString(className);
if([bundleClass conformsToProtocol:@protocol(CogContainer)]) {
@ -103,26 +96,21 @@ static PluginController *sharedPluginController = nil;
}
}
- (void)loadPluginsAtPath:(NSString *)path
{
- (void)loadPluginsAtPath:(NSString *)path {
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
for (NSString *pname in dirContents)
{
for(NSString *pname in dirContents) {
NSString *ppath;
ppath = [NSString pathWithComponents:@[path, pname]];
if ([[pname pathExtension] isEqualToString:@"bundle"])
{
if([[pname pathExtension] isEqualToString:@"bundle"]) {
NSBundle *b = [NSBundle bundleWithPath:ppath];
[b load];
}
}
}
- (void)loadPlugins
{
- (void)loadPlugins {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *basePath = [[paths firstObject] stringByAppendingPathComponent:@"Cog"];
@ -130,131 +118,106 @@ static PluginController *sharedPluginController = nil;
[self loadPluginsAtPath:[basePath stringByAppendingPathComponent:@"Plugins"]];
}
- (void)setupContainer:(NSString *)className
{
- (void)setupContainer:(NSString *)className {
Class container = NSClassFromString(className);
if(container && [container respondsToSelector:@selector(fileTypes)]) {
for (id fileType in [container fileTypes])
{
for(id fileType in [container fileTypes]) {
NSString *ext = [fileType lowercaseString];
NSMutableArray *containerSet;
if (![containers objectForKey:ext])
{
if(![containers objectForKey:ext]) {
containerSet = [[NSMutableArray alloc] init];
[containers setObject:containerSet forKey:ext];
}
else
} else
containerSet = [containers objectForKey:ext];
[containerSet addObject:className];
}
}
}
- (void)setupDecoder:(NSString *)className
{
- (void)setupDecoder:(NSString *)className {
Class decoder = NSClassFromString(className);
if(decoder && [decoder respondsToSelector:@selector(fileTypes)]) {
for (id fileType in [decoder fileTypes])
{
for(id fileType in [decoder fileTypes]) {
NSString *ext = [fileType lowercaseString];
NSMutableArray *decoders;
if (![decodersByExtension objectForKey:ext])
{
if(![decodersByExtension objectForKey:ext]) {
decoders = [[NSMutableArray alloc] init];
[decodersByExtension setObject:decoders forKey:ext];
}
else
} else
decoders = [decodersByExtension objectForKey:ext];
[decoders addObject:className];
}
}
if(decoder && [decoder respondsToSelector:@selector(mimeTypes)]) {
for (id mimeType in [decoder mimeTypes])
{
for(id mimeType in [decoder mimeTypes]) {
NSString *mimetype = [mimeType lowercaseString];
NSMutableArray *decoders;
if (![decodersByMimeType objectForKey:mimetype])
{
if(![decodersByMimeType objectForKey:mimetype]) {
decoders = [[NSMutableArray alloc] init];
[decodersByMimeType setObject:decoders forKey:mimetype];
}
else
} else
decoders = [decodersByMimeType objectForKey:mimetype];
[decoders addObject:className];
}
}
}
- (void)setupMetadataReader:(NSString *)className
{
- (void)setupMetadataReader:(NSString *)className {
Class metadataReader = NSClassFromString(className);
if(metadataReader && [metadataReader respondsToSelector:@selector(fileTypes)]) {
for (id fileType in [metadataReader fileTypes])
{
for(id fileType in [metadataReader fileTypes]) {
NSString *ext = [fileType lowercaseString];
NSMutableArray *readers;
if (![metadataReaders objectForKey:ext])
{
if(![metadataReaders objectForKey:ext]) {
readers = [[NSMutableArray alloc] init];
[metadataReaders setObject:readers forKey:ext];
}
else
} else
readers = [metadataReaders objectForKey:ext];
[readers addObject:className];
}
}
}
- (void)setupPropertiesReader:(NSString *)className
{
- (void)setupPropertiesReader:(NSString *)className {
Class propertiesReader = NSClassFromString(className);
if(propertiesReader && [propertiesReader respondsToSelector:@selector(fileTypes)]) {
for (id fileType in [propertiesReader fileTypes])
{
for(id fileType in [propertiesReader fileTypes]) {
NSString *ext = [fileType lowercaseString];
NSMutableArray *readers;
if (![propertiesReadersByExtension objectForKey:ext])
{
if(![propertiesReadersByExtension objectForKey:ext]) {
readers = [[NSMutableArray alloc] init];
[propertiesReadersByExtension setObject:readers forKey:ext];
}
else
} else
readers = [propertiesReadersByExtension objectForKey:ext];
[readers addObject:className];
}
}
if(propertiesReader && [propertiesReader respondsToSelector:@selector(mimeTypes)]) {
for (id mimeType in [propertiesReader mimeTypes])
{
for(id mimeType in [propertiesReader mimeTypes]) {
NSString *mimetype = [mimeType lowercaseString];
NSMutableArray *readers;
if (![propertiesReadersByMimeType objectForKey:mimetype])
{
if(![propertiesReadersByMimeType objectForKey:mimetype]) {
readers = [[NSMutableArray alloc] init];
[propertiesReadersByMimeType setObject:readers forKey:mimetype];
}
else
} else
readers = [propertiesReadersByMimeType objectForKey:mimetype];
[readers addObject:className];
}
}
}
- (void)setupSource:(NSString *)className
{
- (void)setupSource:(NSString *)className {
Class source = NSClassFromString(className);
if(source && [source respondsToSelector:@selector(schemes)]) {
for (id scheme in [source schemes])
{
for(id scheme in [source schemes]) {
[sources setObject:className forKey:scheme];
}
}
}
- (void)printPluginInfo
{
- (void)printPluginInfo {
ALog(@"Sources: %@", self.sources);
ALog(@"Containers: %@", self.containers);
ALog(@"Metadata Readers: %@", self.metadataReaders);
@ -420,8 +383,7 @@ static PluginController *sharedPluginController = nil;
#endif
}
- (id<CogSource>) audioSourceForURL:(NSURL *)url
{
- (id<CogSource>)audioSourceForURL:(NSURL *)url {
NSString *scheme = [url scheme];
Class source = NSClassFromString([sources objectForKey:scheme]);
@ -429,20 +391,17 @@ static PluginController *sharedPluginController = nil;
return [[source alloc] init];
}
- (NSArray *) urlsForContainerURL:(NSURL *)url
{
- (NSArray *)urlsForContainerURL:(NSURL *)url {
NSString *ext = [url pathExtension];
NSArray *containerSet = [containers objectForKey:[ext lowercaseString]];
NSString *classString;
if(containerSet) {
if([containerSet count] > 1) {
return [CogContainerMulti urlsForContainerURL:url containers:containerSet];
}
else {
} else {
classString = [containerSet objectAtIndex:0];
}
}
else {
} else {
return nil;
}
@ -452,18 +411,15 @@ static PluginController *sharedPluginController = nil;
}
// Note: Source is assumed to already be opened.
- (id<CogDecoder>) audioDecoderForSource:(id <CogSource>)source skipCue:(BOOL)skip
{
- (id<CogDecoder>)audioDecoderForSource:(id<CogSource>)source skipCue:(BOOL)skip {
NSString *ext = [[source url] pathExtension];
NSArray *decoders = [decodersByExtension objectForKey:[ext lowercaseString]];
NSString *classString;
if(decoders) {
if([decoders count] > 1) {
if (skip)
{
if(skip) {
NSMutableArray *_decoders = [decoders mutableCopy];
for (int i = 0; i < [_decoders count];)
{
for(int i = 0; i < [_decoders count];) {
if([[_decoders objectAtIndex:i] isEqualToString:@"CueSheetDecoder"])
[_decoders removeObjectAtIndex:i];
else
@ -472,22 +428,18 @@ static PluginController *sharedPluginController = nil;
return [[CogDecoderMulti alloc] initWithDecoders:_decoders];
}
return [[CogDecoderMulti alloc] initWithDecoders:decoders];
}
else {
} else {
classString = [decoders objectAtIndex:0];
}
}
else {
} else {
decoders = [decodersByMimeType objectForKey:[[source mimeType] lowercaseString]];
if(decoders) {
if([decoders count] > 1) {
return [[CogDecoderMulti alloc] initWithDecoders:decoders];
}
else {
} else {
classString = [decoders objectAtIndex:0];
}
}
else {
} else {
classString = @"SilenceDecoder";
}
}
@ -497,8 +449,7 @@ static PluginController *sharedPluginController = nil;
return [[decoder alloc] init];
}
- (NSDictionary *)metadataForURL:(NSURL *)url skipCue:(BOOL)skip
{
- (NSDictionary *)metadataForURL:(NSURL *)url skipCue:(BOOL)skip {
NSString *urlScheme = [url scheme];
if([urlScheme isEqualToString:@"http"] ||
[urlScheme isEqualToString:@"https"])
@ -509,11 +460,9 @@ static PluginController *sharedPluginController = nil;
NSString *classString;
if(readers) {
if([readers count] > 1) {
if (skip)
{
if(skip) {
NSMutableArray *_readers = [readers mutableCopy];
for (int i = 0; i < [_readers count];)
{
for(int i = 0; i < [_readers count];) {
if([[_readers objectAtIndex:i] isEqualToString:@"CueSheetMetadataReader"])
[_readers removeObjectAtIndex:i];
else
@ -522,12 +471,10 @@ static PluginController *sharedPluginController = nil;
return [CogMetadataReaderMulti metadataForURL:url readers:_readers];
}
return [CogMetadataReaderMulti metadataForURL:url readers:readers];
}
else {
} else {
classString = [readers objectAtIndex:0];
}
}
else {
} else {
return nil;
}
@ -536,10 +483,8 @@ static PluginController *sharedPluginController = nil;
return [metadataReader metadataForURL:url];
}
// If no properties reader is defined, use the decoder's properties.
- (NSDictionary *)propertiesForURL:(NSURL *)url
{
- (NSDictionary *)propertiesForURL:(NSURL *)url {
NSString *urlScheme = [url scheme];
if([urlScheme isEqualToString:@"http"] ||
[urlScheme isEqualToString:@"https"])
@ -554,34 +499,28 @@ static PluginController *sharedPluginController = nil;
NSArray *readers = [propertiesReadersByExtension objectForKey:[ext lowercaseString]];
NSString *classString = nil;
if (readers)
{
if(readers) {
if([readers count] > 1) {
properties = [CogPropertiesReaderMulti propertiesForSource:source readers:readers];
if(properties != nil && [properties count])
return properties;
}
else {
} else {
classString = [readers objectAtIndex:0];
}
}
else {
} else {
readers = [propertiesReadersByMimeType objectForKey:[[source mimeType] lowercaseString]];
if (readers)
{
if(readers) {
if([readers count] > 1) {
properties = [CogPropertiesReaderMulti propertiesForSource:source readers:readers];
if(properties != nil && [properties count])
return properties;
}
else {
} else {
classString = [readers objectAtIndex:0];
}
}
}
if (classString)
{
if(classString) {
Class propertiesReader = NSClassFromString(classString);
properties = [propertiesReader propertiesForSource:source];
@ -591,8 +530,7 @@ static PluginController *sharedPluginController = nil;
{
id<CogDecoder> decoder = [self audioDecoderForSource:source skipCue:NO];
if (![decoder open:source])
{
if(![decoder open:source]) {
return nil;
}
@ -604,10 +542,8 @@ static PluginController *sharedPluginController = nil;
}
}
- (int)putMetadataInURL:(NSURL *)url
{
- (int)putMetadataInURL:(NSURL *)url {
return 0;
}
@end

View file

@ -8,40 +8,33 @@
#import "Semaphore.h"
@implementation Semaphore
-(id)init
{
- (id)init {
self = [super init];
if (self)
{
if(self) {
semaphore_create(mach_task_self(), &semaphore, SYNC_POLICY_FIFO, 0);
}
return self;
}
-(void)signal
{
- (void)signal {
semaphore_signal_all(semaphore);
}
-(void)timedWait:(int)microseconds
{
- (void)timedWait:(int)microseconds {
mach_timespec_t timeout = { 0, microseconds * 1000UL };
semaphore_timedwait(semaphore, timeout);
}
-(void)wait
{
- (void)wait {
mach_timespec_t t = { 2.0, 0.0 }; // 2 second timeout
semaphore_timedwait(semaphore, t);
}
-(void)waitIndefinitely
{
- (void)waitIndefinitely {
semaphore_wait(semaphore);
}

View file

@ -24,8 +24,7 @@
@class PlaylistEntry;
@interface AudioScrobbler : NSObject
{
@interface AudioScrobbler : NSObject {
NSString *_pluginID;
NSMutableArray *_queue;

View file

@ -34,8 +34,7 @@ NSString * const AudioScrobblerRunLoopMode = @"org.cogx.Cog.AudioScrobbler.Run
// Helpers
// ========================================
static NSString *
escapeForLastFM(NSString *string)
{
escapeForLastFM(NSString *string) {
NSMutableString *result = [string mutableCopy];
[result replaceOccurrencesOfString:@"&"
@ -67,8 +66,7 @@ escapeForLastFM(NSString *string)
@implementation AudioScrobbler
+ (BOOL) isRunning
{
+ (BOOL)isRunning {
NSArray *launchedApps = [[NSWorkspace sharedWorkspace] runningApplications];
BOOL running = NO;
for(NSRunningApplication *app in launchedApps) {
@ -81,14 +79,11 @@ escapeForLastFM(NSString *string)
return running;
}
- (id) init
{
- (id)init {
if((self = [super init])) {
_pluginID = @"cog";
if([[NSUserDefaults standardUserDefaults] boolForKey:@"automaticallyLaunchLastFM"]) {
if(![AudioScrobbler isRunning]) {
[[NSWorkspace sharedWorkspace] launchApplication:@"Last.fm.app"];
}
@ -110,18 +105,17 @@ escapeForLastFM(NSString *string)
return self;
}
- (void) dealloc
{
- (void)dealloc {
if([self keepProcessingAudioScrobblerCommands] || NO == [self audioScrobblerThreadCompleted])
[self shutdown];
_queue = nil;
semaphore_destroy(mach_task_self(), _semaphore); _semaphore = 0;
semaphore_destroy(mach_task_self(), _semaphore);
_semaphore = 0;
}
- (void) start:(PlaylistEntry *)pe
{
- (void)start:(PlaylistEntry *)pe {
[self sendCommand:[NSString stringWithFormat:@"START c=%@&a=%@&t=%@&b=%@&m=%@&l=%i&p=%@\n",
[self pluginID],
escapeForLastFM([pe artist]),
@ -129,27 +123,22 @@ escapeForLastFM(NSString *string)
escapeForLastFM([pe album]),
@"", // TODO: MusicBrainz support
[[pe length] intValue],
escapeForLastFM([[pe URL] path])
]];
escapeForLastFM([[pe URL] path])]];
}
- (void) stop
{
- (void)stop {
[self sendCommand:[NSString stringWithFormat:@"STOP c=%@\n", [self pluginID]]];
}
- (void) pause
{
- (void)pause {
[self sendCommand:[NSString stringWithFormat:@"PAUSE c=%@\n", [self pluginID]]];
}
- (void) resume
{
- (void)resume {
[self sendCommand:[NSString stringWithFormat:@"RESUME c=%@\n", [self pluginID]]];
}
- (void) shutdown
{
- (void)shutdown {
[self setKeepProcessingAudioScrobblerCommands:NO];
semaphore_signal([self semaphore]);
@ -162,54 +151,45 @@ escapeForLastFM(NSString *string)
@implementation AudioScrobbler (Private)
- (NSMutableArray *) queue
{
- (NSMutableArray *)queue {
if(nil == _queue)
_queue = [[NSMutableArray alloc] init];
return _queue;
}
- (NSString *) pluginID
{
- (NSString *)pluginID {
return _pluginID;
}
- (void) sendCommand:(NSString *)command
{
- (void)sendCommand:(NSString *)command {
@synchronized([self queue]) {
[[self queue] addObject:command];
}
semaphore_signal([self semaphore]);
}
- (BOOL) keepProcessingAudioScrobblerCommands
{
- (BOOL)keepProcessingAudioScrobblerCommands {
return _keepProcessingAudioScrobblerCommands;
}
- (void) setKeepProcessingAudioScrobblerCommands:(BOOL)keepProcessingAudioScrobblerCommands
{
- (void)setKeepProcessingAudioScrobblerCommands:(BOOL)keepProcessingAudioScrobblerCommands {
_keepProcessingAudioScrobblerCommands = keepProcessingAudioScrobblerCommands;
}
- (BOOL) audioScrobblerThreadCompleted
{
- (BOOL)audioScrobblerThreadCompleted {
return _audioScrobblerThreadCompleted;
}
- (void) setAudioScrobblerThreadCompleted:(BOOL)audioScrobblerThreadCompleted
{
- (void)setAudioScrobblerThreadCompleted:(BOOL)audioScrobblerThreadCompleted {
_audioScrobblerThreadCompleted = audioScrobblerThreadCompleted;
}
- (semaphore_t) semaphore
{
- (semaphore_t)semaphore {
return _semaphore;
}
- (void) processAudioScrobblerCommands:(id)unused
{
- (void)processAudioScrobblerCommands:(id)unused {
@autoreleasepool {
AudioScrobblerClient *client = [[AudioScrobblerClient alloc] init];
mach_timespec_t timeout = { 5, 0 };
@ -219,7 +199,6 @@ escapeForLastFM(NSString *string)
while([self keepProcessingAudioScrobblerCommands]) {
@autoreleasepool {
// Get the first command to be sent
@synchronized([self queue]) {
if([[self queue] count]) {

View file

@ -22,8 +22,7 @@
#include <netdb.h>
@interface AudioScrobblerClient : NSObject
{
@interface AudioScrobblerClient : NSObject {
int _socket;
BOOL _doPortStepping;
in_port_t _port;

View file

@ -33,8 +33,7 @@
#define kPortsToStep 5
static in_addr_t
addressForHost(NSString *hostname)
{
addressForHost(NSString *hostname) {
NSCParameterAssert(nil != hostname);
in_addr_t address;
@ -61,8 +60,7 @@ addressForHost(NSString *hostname)
@implementation AudioScrobblerClient
- (id) init
{
- (id)init {
if((self = [super init])) {
_socket = -1;
_doPortStepping = YES;
@ -70,8 +68,7 @@ addressForHost(NSString *hostname)
return self;
}
- (BOOL) connectToHost:(NSString *)hostname port:(in_port_t)port
{
- (BOOL)connectToHost:(NSString *)hostname port:(in_port_t)port {
NSParameterAssert(nil != hostname);
in_addr_t remoteAddress = addressForHost(hostname);
@ -82,18 +79,15 @@ addressForHost(NSString *hostname)
return NO;
}
- (BOOL) isConnected
{
- (BOOL)isConnected {
return (-1 != _socket);
}
- (in_port_t) connectedPort
{
- (in_port_t)connectedPort {
return _port;
}
- (void) send:(NSString *)data
{
- (void)send:(NSString *)data {
const char *utf8data = [data UTF8String];
unsigned len = (unsigned int)strlen(utf8data);
unsigned bytesToSend = len;
@ -115,8 +109,7 @@ addressForHost(NSString *hostname)
}
}
- (NSString *) receive
{
- (NSString *)receive {
char buffer[kBufferSize];
int readSize = kBufferSize - 1;
ssize_t bytesRead = 0;
@ -148,8 +141,7 @@ addressForHost(NSString *hostname)
return result;
}
- (void) shutdown
{
- (void)shutdown {
int result;
char buffer[kBufferSize];
ssize_t bytesRead;
@ -170,8 +162,7 @@ addressForHost(NSString *hostname)
if(0 != bytesRead) {
NSString *received = [[NSString alloc] initWithBytes:buffer length:bytesRead encoding:NSUTF8StringEncoding];
ALog(@"Received unexpected bytes during shutdown: %@", received);
}
else
} else
break;
}
@ -187,8 +178,7 @@ addressForHost(NSString *hostname)
@implementation AudioScrobblerClient (Private)
- (BOOL) connectToSocket:(in_addr_t)remoteAddress port:(in_port_t)port
{
- (BOOL)connectToSocket:(in_addr_t)remoteAddress port:(in_port_t)port {
NSParameterAssert(INADDR_NONE != remoteAddress);
_port = port;

View file

@ -6,8 +6,8 @@
// Copyright 2005 Vincent Spader All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "FeedbackSocket.h"
#import <Cocoa/Cocoa.h>
@interface FeedbackController : NSWindowController <FeedbackSocketDelegate> {
IBOutlet NSTextField* fromView;

View file

@ -12,13 +12,11 @@
@implementation FeedbackController
- (id)init
{
- (id)init {
return [super initWithWindowNibName:@"Feedback"];
}
- (IBAction)showWindow:(id)sender
{
- (IBAction)showWindow:(id)sender {
[fromView setStringValue:@""];
[subjectView setStringValue:@""];
[messageView setString:@""];
@ -26,16 +24,13 @@
[super showWindow:sender];
}
- (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
if ([(NSNumber *)CFBridgingRelease(contextInfo) boolValue]== YES)
{
- (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo {
if([(NSNumber *)CFBridgingRelease(contextInfo) boolValue] == YES) {
[[self window] close];
}
}
- (void)feedbackDidNotSend:(FeedbackSocket *)feedback
{
- (void)feedbackDidNotSend:(FeedbackSocket *)feedback {
ALog(@"Error sending feedback");
[sendingIndicator stopAnimation:self];
@ -47,8 +42,7 @@
[alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:(void *)CFBridgingRetain([NSNumber numberWithBool:NO])];
}
- (void)feedbackDidSend:(FeedbackSocket *)feedback
{
- (void)feedbackDidSend:(FeedbackSocket *)feedback {
[sendingIndicator stopAnimation:self];
NSAlert *alert = [[NSAlert alloc] init];
@ -58,9 +52,7 @@
[alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:(void *)CFBridgingRetain([NSNumber numberWithBool:YES])];
}
- (IBAction)sendFeedback:(id)sender
{
- (IBAction)sendFeedback:(id)sender {
[sendingIndicator startAnimation:self];
// Using this so that if its a bad connection, it doesnt sit there looking stupid..or should it
@ -72,8 +64,7 @@
[feedbackSocket sendFeedback:[fromView stringValue] subject:[subjectView stringValue] message:[messageView string] version:version];
}
- (IBAction)cancel:(id)sender
{
- (IBAction)cancel:(id)sender {
[[self window] close];
}

View file

@ -12,13 +12,11 @@
@implementation FeedbackSocket
NSString *encodeForURL(NSString *s)
{
NSString *encodeForURL(NSString *s) {
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)s, NULL, NULL, kCFStringEncodingUTF8));
}
- (void)sendFeedbackThread:(id)sender
{
- (void)sendFeedbackThread:(id)sender {
@autoreleasepool {
NSString *f = encodeForURL(from);
NSString *s = encodeForURL(subject);
@ -41,21 +39,16 @@ NSString *encodeForURL(NSString *s)
NSData *resultData = [NSURLConnection sendSynchronousRequest:post returningResponse:&response error:&error];
NSString *resultString = [[NSString alloc] initWithData:resultData encoding:NSASCIIStringEncoding];
// DLog(@"RESULT: %@", resultString);
if ([resultString caseInsensitiveCompare:@"SUCCESS"] == NSOrderedSame)
{
if([resultString caseInsensitiveCompare:@"SUCCESS"] == NSOrderedSame) {
[self performSelectorOnMainThread:@selector(returnSuccess:) withObject:nil waitUntilDone:NO];
}
else
{
} else {
[self performSelectorOnMainThread:@selector(returnFailure:) withObject:nil waitUntilDone:NO];
}
}
}
- (void)sendFeedback: (NSString *)f subject:(NSString *)s message:(NSString *)m version:(NSString *)v
{
if ([f isEqualToString:@""])
{
- (void)sendFeedback:(NSString *)f subject:(NSString *)s message:(NSString *)m version:(NSString *)v {
if([f isEqualToString:@""]) {
f = @"Anonymous";
}
[self setFrom:f];
@ -66,43 +59,35 @@ NSString *encodeForURL(NSString *s)
[NSThread detachNewThreadSelector:@selector(sendFeedbackThread:) toTarget:self withObject:nil];
}
- (void)returnSuccess:(id)userInfo
{
- (void)returnSuccess:(id)userInfo {
if([delegate respondsToSelector:@selector(feedbackDidSend:)]) {
[delegate feedbackDidSend:self];
}
}
- (void)returnFailure:(id)userInfo
{
- (void)returnFailure:(id)userInfo {
if([delegate respondsToSelector:@selector(feedbackDidNotSend:)]) {
[delegate feedbackDidNotSend:self];
}
}
-(void)setDelegate:(id<FeedbackSocketDelegate>)d
{
- (void)setDelegate:(id<FeedbackSocketDelegate>)d {
delegate = d;
}
- (void)setFrom:(NSString *)f
{
- (void)setFrom:(NSString *)f {
from = f;
}
- (void)setSubject:(NSString *)s
{
- (void)setSubject:(NSString *)s {
subject = s;
}
- (void)setMessage:(NSString *)m
{
- (void)setMessage:(NSString *)m {
message = m;
}
- (void)setVersion:(NSString *)v
{
- (void)setVersion:(NSString *)v {
version = v;
}

View file

@ -11,8 +11,6 @@
#import "PathNode.h"
@interface ContainedNode : PathNode {
}
@end

View file

@ -9,36 +9,31 @@
#import "ContainedNode.h"
#import "CogAudio/AudioMetadataReader.h"
@implementation ContainedNode
- (BOOL)isLeaf
{
- (BOOL)isLeaf {
return YES;
}
- (void)setURL:(NSURL *)u
{
- (void)setURL:(NSURL *)u {
[super setURL:u];
if ([u fragment])
{
if([u fragment]) {
NSDictionary *metadata = [AudioMetadataReader metadataForURL:u];
NSString *title = nil;
NSString *artist = nil;
if (metadata)
{
if(metadata) {
title = [metadata valueForKey:@"title"];
artist = [metadata valueForKey:@"artist"];
}
if (title && [title length])
{
if (artist && [artist length]) { display = [[u fragment] stringByAppendingFormat:@": %@ - %@", artist, title];}
else { display = [[u fragment] stringByAppendingFormat:@": %@", title]; }
if(title && [title length]) {
if(artist && [artist length]) {
display = [[u fragment] stringByAppendingFormat:@": %@ - %@", artist, title];
} else {
display = [[u fragment] stringByAppendingFormat:@": %@", title];
}
else
{
} else {
display = [u fragment];
}
}

View file

@ -11,7 +11,6 @@
#import "PathNode.h"
@interface ContainerNode : PathNode {
}
@end

View file

@ -15,18 +15,15 @@
@implementation ContainerNode
- (BOOL)isLeaf
{
- (BOOL)isLeaf {
return NO;
}
- (void)updatePath
{
- (void)updatePath {
NSArray *urls = [AudioContainer urlsForContainerURL:url];
NSMutableArray *paths = [[NSMutableArray alloc] init];
for (NSURL *u in urls)
{
for(NSURL *u in urls) {
ContainedNode *node = [[ContainedNode alloc] initWithDataSource:dataSource url:u];
DLog(@"Node: %@", u);
[paths addObject:node];

View file

@ -6,11 +6,10 @@
// Copyright 2006 Vincent Spader. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "PathNode.h"
#import <Cocoa/Cocoa.h>
@interface DirectoryNode : PathNode
{
@interface DirectoryNode : PathNode {
}
@end

View file

@ -15,20 +15,20 @@
@implementation DirectoryNode
- (BOOL)isLeaf
{
- (BOOL)isLeaf {
return NO;
}
- (void)updatePath
{
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:url includingPropertiesForKeys:@[NSURLNameKey, NSURLIsDirectoryKey] options:(NSDirectoryEnumerationSkipsSubdirectoryDescendants | NSDirectoryEnumerationSkipsPackageDescendants | NSDirectoryEnumerationSkipsHiddenFiles) errorHandler:^BOOL(NSURL *url, NSError *error) {
- (void)updatePath {
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:url
includingPropertiesForKeys:@[NSURLNameKey, NSURLIsDirectoryKey]
options:(NSDirectoryEnumerationSkipsSubdirectoryDescendants | NSDirectoryEnumerationSkipsPackageDescendants | NSDirectoryEnumerationSkipsHiddenFiles)
errorHandler:^BOOL(NSURL *url, NSError *error) {
return NO;
}];
NSMutableArray *fullPaths = [[NSMutableArray alloc] init];
for (NSURL * theUrl in enumerator)
{
for(NSURL *theUrl in enumerator) {
[fullPaths addObject:[theUrl path]];
}

View file

@ -6,11 +6,10 @@
// Copyright 2006 Vincent Spader. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "ImageTextCell.h"
#import <Cocoa/Cocoa.h>
@interface FileIconCell : ImageTextCell {
}
@end

View file

@ -11,13 +11,11 @@
@implementation FileIconCell
- (void)setObjectValue:(PathNode *)o
{
- (void)setObjectValue:(PathNode *)o {
if([o respondsToSelector:@selector(icon)] && [o respondsToSelector:@selector(display)]) {
[super setObjectValue:[o display]];
[super setImage:[o icon]];
}
else {
} else {
[super setObjectValue:(id)o];
}
}

View file

@ -6,12 +6,10 @@
// Copyright 2006 Vincent Spader. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "PathNode.h"
#import <Cocoa/Cocoa.h>
@interface FileNode : PathNode
{
@interface FileNode : PathNode {
}
@end

View file

@ -10,8 +10,7 @@
@implementation FileNode
- (BOOL)isLeaf
{
- (BOOL)isLeaf {
return YES;
}

View file

@ -6,8 +6,8 @@
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "FileTreeDataSource.h"
#import <Cocoa/Cocoa.h>
@class SideViewController;
@interface FileTreeController : NSObject {

View file

@ -6,82 +6,69 @@
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "PlaylistController.h"
#import "FileTreeController.h"
#import "PlaylistController.h"
#import "SideViewController.h"
@implementation FileTreeController
- (IBAction)addToPlaylist:(id)sender
{
- (IBAction)addToPlaylist:(id)sender {
[self doAddToPlaylist:sender origin:URLOriginInternal];
}
- (void)doAddToPlaylist:(id)sender origin:(URLOrigin)origin
{
- (void)doAddToPlaylist:(id)sender origin:(URLOrigin)origin {
NSUInteger index;
NSIndexSet *selectedIndexes = [outlineView selectedRowIndexes];
NSMutableArray *urls = [[NSMutableArray alloc] init];
for(index = [selectedIndexes firstIndex];
index != NSNotFound; index = [selectedIndexes indexGreaterThanIndex: index])
{
index != NSNotFound; index = [selectedIndexes indexGreaterThanIndex:index]) {
[urls addObject:[[outlineView itemAtRow:index] URL]];
}
[controller doAddToPlaylist:urls origin:origin];
}
- (void)addToPlaylistExternal:(id)sender
{
- (void)addToPlaylistExternal:(id)sender {
[self doAddToPlaylist:sender origin:URLOriginExternal];
}
- (IBAction)setAsPlaylist:(id)sender
{
- (IBAction)setAsPlaylist:(id)sender {
[controller clear:sender];
[self addToPlaylist:sender];
}
- (IBAction)playPauseResume:(NSObject *)id
{
- (IBAction)playPauseResume:(NSObject *)id {
[controller playPauseResume:id];
}
- (IBAction)showEntryInFinder:(id)sender
{
- (IBAction)showEntryInFinder:(id)sender {
NSUInteger index;
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSIndexSet *selectedIndexes = [outlineView selectedRowIndexes];
for(index = [selectedIndexes firstIndex];
index != NSNotFound; index = [selectedIndexes indexGreaterThanIndex: index])
{
index != NSNotFound; index = [selectedIndexes indexGreaterThanIndex:index]) {
NSURL *url = [[outlineView itemAtRow:index] URL];
[ws selectFile:[url path] inFileViewerRootedAtPath:[url path]];
}
}
- (IBAction)setAsRoot:(id)sender
{
- (IBAction)setAsRoot:(id)sender {
NSUInteger index = [[outlineView selectedRowIndexes] firstIndex];
if (index != NSNotFound)
{
if(index != NSNotFound) {
[dataSource changeURL:[[outlineView itemAtRow:index] URL]];
}
}
-(BOOL)validateMenuItem:(NSMenuItem*)menuItem
{
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
SEL action = [menuItem action];
if([outlineView numberOfSelectedRows] == 0)
return NO;
if (action == @selector(setAsRoot:))
{
if(action == @selector(setAsRoot:)) {
BOOL isDir;
NSInteger row = [outlineView selectedRow];

View file

@ -93,8 +93,7 @@ static NSURL *defaultMusicDirectory(void) {
NSString *relativePath = [[path stringByReplacingOccurrencesOfString:[[[self rootURL] path] stringByAppendingString:@"/"]
withString:@""
options:NSAnchoredSearch
range:NSMakeRange(0, [path length])
] stringByStandardizingPath];
range:NSMakeRange(0, [path length])] stringByStandardizingPath];
PathNode *node = rootNode;
DLog(@"Root | Relative | Path: %@ | %@ | %@", [[self rootURL] path], relativePath, path);
for(NSString *c in [relativePath pathComponents]) {
@ -153,8 +152,7 @@ static NSURL *defaultMusicDirectory(void) {
NSPasteboardItem *paste = [[NSPasteboardItem alloc] init];
if(@available(macOS 10.13, *)) {
[paste setData:[[item URL] dataRepresentation] forType:NSPasteboardTypeFileURL];
}
else {
} else {
[paste setPropertyList:@[[item URL]] forType:NSFilenamesPboardType];
}
return paste;

View file

@ -8,7 +8,6 @@
#import <Cocoa/Cocoa.h>
@interface FileTreeOutlineView : NSOutlineView {
}

View file

@ -6,37 +6,31 @@
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "FileTreeController.h"
#import "FileTreeOutlineView.h"
#import "FileTreeController.h"
#import "FileTreeViewController.h"
#import "PlaybackController.h"
@implementation FileTreeOutlineView
- (void)awakeFromNib
{
- (void)awakeFromNib {
[self setDoubleAction:@selector(addToPlaylistExternal:)];
[self setTarget:[self delegate]];
}
- (void)keyDown:(NSEvent *)e
{
- (void)keyDown:(NSEvent *)e {
unsigned int modifiers = [e modifierFlags] & (NSEventModifierFlagCommand | NSEventModifierFlagShift | NSEventModifierFlagControl | NSEventModifierFlagOption);
NSString *characters = [e characters];
unichar c;
if ([characters length] == 1)
{
if([characters length] == 1) {
c = [characters characterAtIndex:0];
if (modifiers == 0 && (c == NSEnterCharacter || c == NSCarriageReturnCharacter))
{
if(modifiers == 0 && (c == NSEnterCharacter || c == NSCarriageReturnCharacter)) {
[(FileTreeController *)[self delegate] addToPlaylistExternal:self];
return;
}
else if (modifiers == 0 && c == ' ')
{
} else if(modifiers == 0 && c == ' ') {
[(FileTreeController *)[self delegate] playPauseResume:self];
return;
}
@ -48,8 +42,7 @@
}
// enables right-click selection for "Show in Finder" contextual menu
-(NSMenu*)menuForEvent:(NSEvent*)event
{
- (NSMenu *)menuForEvent:(NSEvent *)event {
// Find which row is under the cursor
[[self window] makeFirstResponder:self];
NSPoint menuPoint = [self convertPoint:[event locationInWindow] fromView:nil];
@ -61,12 +54,9 @@
multiple items to be selected), otherwise selects the row under the mouse */
BOOL currentRowIsSelected = [[self selectedRowIndexes] containsIndex:iRow];
if (iRow == -1)
{
if(iRow == -1) {
[self deselectAll:self];
}
else if (!currentRowIsSelected)
{
} else if(!currentRowIsSelected) {
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:iRow] byExtendingSelection:NO];
}

View file

@ -6,8 +6,8 @@
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "SideViewController.h"
#import <Cocoa/Cocoa.h>
@class PlaylistLoader;
@class PlaybackController;

View file

@ -7,44 +7,37 @@
//
#import "FileTreeViewController.h"
#import "PlaylistLoader.h"
#import "PlaybackController.h"
#import "PlaylistLoader.h"
@implementation FileTreeViewController
- (id)init
{
- (id)init {
return [super initWithNibName:@"FileTree" bundle:[NSBundle mainBundle]];
}
- (void)addToPlaylistInternal:(NSArray *)urls
{
- (void)addToPlaylistInternal:(NSArray *)urls {
[self doAddToPlaylist:urls origin:URLOriginInternal];
}
- (void)addToPlaylistExternal:(NSArray *)urls
{
- (void)addToPlaylistExternal:(NSArray *)urls {
[self doAddToPlaylist:urls origin:URLOriginExternal];
}
- (void)doAddToPlaylist:(NSArray *)urls origin:(URLOrigin)origin
{
- (void)doAddToPlaylist:(NSArray *)urls origin:(URLOrigin)origin {
[playlistLoader willInsertURLs:urls origin:origin];
[playlistLoader didInsertURLs:[playlistLoader addURLs:urls sort:YES] origin:origin];
}
- (void)clear:(id)sender
{
- (void)clear:(id)sender {
[playlistLoader clear:sender];
}
- (void)playPauseResume:(NSObject *)id
{
- (void)playPauseResume:(NSObject *)id {
[playbackController playPauseResume:id];
}
- (FileTreeOutlineView*)outlineView
{
- (FileTreeOutlineView *)outlineView {
return fileTreeOutlineView;
}

View file

@ -10,8 +10,7 @@
@class FileTreeDataSource;
@interface PathNode : NSObject
{
@interface PathNode : NSObject {
FileTreeDataSource *dataSource;
NSURL *url;
@ -41,5 +40,4 @@
- (void)updatePath;
@end

View file

@ -12,10 +12,10 @@
#import "FileTreeDataSource.h"
#import "FileNode.h"
#import "DirectoryNode.h"
#import "SmartFolderNode.h"
#import "ContainerNode.h"
#import "DirectoryNode.h"
#import "FileNode.h"
#import "SmartFolderNode.h"
#import "Logging.h"
@ -23,17 +23,14 @@
// From http://developer.apple.com/documentation/Cocoa/Conceptual/LowLevelFileMgmt/Tasks/ResolvingAliases.html
// Updated 2018-06-28
NSURL *resolveAliases(NSURL *url)
{
NSURL *resolveAliases(NSURL *url) {
CFErrorRef error;
CFDataRef bookmarkRef = CFURLCreateBookmarkDataFromFile(kCFAllocatorDefault, (__bridge CFURLRef)url, &error);
if (bookmarkRef)
{
if(bookmarkRef) {
Boolean isStale;
CFURLRef urlRef = CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, bookmarkRef, kCFURLBookmarkResolutionWithSecurityScope, NULL, NULL, &isStale, &error);
if (urlRef && !isStale)
{
if(urlRef && !isStale) {
return (NSURL *)CFBridgingRelease(urlRef);
}
}
@ -42,12 +39,10 @@ NSURL *resolveAliases(NSURL *url)
return url;
}
- (id)initWithDataSource:(FileTreeDataSource *)ds url:(NSURL *)u
{
- (id)initWithDataSource:(FileTreeDataSource *)ds url:(NSURL *)u {
self = [super init];
if (self)
{
if(self) {
dataSource = ds;
[self setURL:u];
}
@ -55,8 +50,7 @@ NSURL *resolveAliases(NSURL *url)
return self;
}
- (void)setURL:(NSURL *)u
{
- (void)setURL:(NSURL *)u {
url = u;
display = [[NSFileManager defaultManager] displayNameAtPath:[u path]];
@ -66,24 +60,19 @@ NSURL *resolveAliases(NSURL *url)
[icon setSize:NSMakeSize(16.0, 16.0)];
}
- (NSURL *)URL
{
- (NSURL *)URL {
return url;
}
- (void)updatePath
{
- (void)updatePath {
}
- (void)processPaths: (NSArray *)contents
{
- (void)processPaths:(NSArray *)contents {
NSMutableArray *newSubpathsDirs = [[NSMutableArray alloc] init];
NSMutableArray *newSubpaths = [[NSMutableArray alloc] init];
for (NSString *s in contents)
{
if ([s characterAtIndex:0] == '.')
{
for(NSString *s in contents) {
if([s characterAtIndex:0] == '.') {
continue;
}
@ -98,31 +87,22 @@ NSURL *resolveAliases(NSURL *url)
BOOL isDir;
if ([[s pathExtension] caseInsensitiveCompare:@"savedSearch"] == NSOrderedSame)
{
if([[s pathExtension] caseInsensitiveCompare:@"savedSearch"] == NSOrderedSame) {
DLog(@"Smart folder!");
newNode = [[SmartFolderNode alloc] initWithDataSource:dataSource url:u];
isDir = NO;
}
else
{
} else {
[[NSFileManager defaultManager] fileExistsAtPath:[u path] isDirectory:&isDir];
if (!isDir && ![[AudioPlayer fileTypes] containsObject:[[u pathExtension] lowercaseString]])
{
if(!isDir && ![[AudioPlayer fileTypes] containsObject:[[u pathExtension] lowercaseString]]) {
continue;
}
if (isDir)
{
if(isDir) {
newNode = [[DirectoryNode alloc] initWithDataSource:dataSource url:u];
}
else if ([[AudioPlayer containerTypes] containsObject:[[u pathExtension] lowercaseString]])
{
} else if([[AudioPlayer containerTypes] containsObject:[[u pathExtension] lowercaseString]]) {
newNode = [[ContainerNode alloc] initWithDataSource:dataSource url:u];
}
else
{
} else {
newNode = [[FileNode alloc] initWithDataSource:dataSource url:u];
}
}
@ -139,39 +119,31 @@ NSURL *resolveAliases(NSURL *url)
[self setSubpaths:newSubpathsDirs];
}
- (NSArray *)subpaths
{
if (subpaths == nil)
{
- (NSArray *)subpaths {
if(subpaths == nil) {
[self updatePath];
}
return subpaths;
}
- (void)setSubpaths:(NSArray *)s
{
- (void)setSubpaths:(NSArray *)s {
subpaths = s;
}
- (BOOL)isLeaf
{
- (BOOL)isLeaf {
return YES;
}
- (void)setDisplay:(NSString *)s
{
- (void)setDisplay:(NSString *)s {
display = s;
}
- (NSString *)display
{
- (NSString *)display {
return display;
}
- (NSImage *)icon
{
- (NSImage *)icon {
return icon;
}

View file

@ -9,7 +9,6 @@
#import <Cocoa/Cocoa.h>
#include <CoreServices/CoreServices.h>
@interface PathWatcher : NSObject {
FSEventStreamRef stream;
FSEventStreamContext *context;

View file

@ -14,8 +14,7 @@ static void myFSEventCallback(
size_t numEvents,
void *eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
const FSEventStreamEventId eventIds[]) {
int i;
char **paths = eventPaths;
PathWatcher *pathWatcher = (__bridge PathWatcher *)clientCallBackInfo;
@ -29,8 +28,7 @@ static void myFSEventCallback(
@implementation PathWatcher
- (void)cleanUp
{
- (void)cleanUp {
if(stream) {
FSEventStreamStop(stream);
FSEventStreamInvalidate(stream);
@ -43,8 +41,7 @@ static void myFSEventCallback(
}
}
- (void)setPath:(NSString *)path
{
- (void)setPath:(NSString *)path {
[self cleanUp];
// Create FSEvent stream
@ -71,19 +68,15 @@ static void myFSEventCallback(
FSEventStreamStart(stream);
}
- (void)setDelegate:(id)d
{
- (void)setDelegate:(id)d {
delegate = d;
}
- (id)delegate
{
- (id)delegate {
return delegate;
}
- (void) dealloc
{
- (void)dealloc {
[self cleanUp];
}
@end

View file

@ -15,13 +15,11 @@
@implementation SmartFolderNode
- (BOOL)isLeaf
{
- (BOOL)isLeaf {
return NO;
}
- (void)updatePath
{
- (void)updatePath {
NSDictionary *doc = [NSDictionary dictionaryWithContentsOfFile:[url path]];
NSString *rawQuery = [doc objectForKey:@"RawQuery"];
NSArray *searchPaths = [[doc objectForKey:@"SearchCriteria"] objectForKey:@"CurrentFolderPath"];
@ -41,23 +39,19 @@
// Note: This is asynchronous!
}
- (void)setSubpaths:(id)s
{
- (void)setSubpaths:(id)s {
subpaths = s;
}
- (unsigned int)countOfSubpaths
{
- (unsigned int)countOfSubpaths {
return (unsigned int)[[self subpaths] count];
}
- (PathNode *)objectInSubpathsAtIndex:(unsigned int)index
{
- (PathNode *)objectInSubpathsAtIndex:(unsigned int)index {
return [[self subpaths] objectAtIndex:index];
}
- (void)queryFinished:(NSNotification *)notification
{
- (void)queryFinished:(NSNotification *)notification {
DLog(@"Query finished!");
MDQueryRef query = (__bridge MDQueryRef)[notification object];
@ -67,8 +61,7 @@
int c = (int)MDQueryGetResultCount(query);
int i;
for (i = 0; i < c; i++)
{
for(i = 0; i < c; i++) {
MDItemRef item = (MDItemRef)MDQueryGetResultAtIndex(query, i);
NSString *itemPath = (NSString *)CFBridgingRelease(MDItemCopyAttribute(item, kMDItemPath));
@ -85,17 +78,13 @@
[dataSource reloadPathNode:self];
}
- (void)queryUpdate:(NSNotification *)notification
{
- (void)queryUpdate:(NSNotification *)notification {
DLog(@"Query update!");
[self queryFinished:notification];
}
- (void)dealloc
{
- (void)dealloc {
CFRelease(_query);
}
@end

View file

@ -8,10 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface BlankZeroFormatter : NSFormatter {
}
@end

View file

@ -8,11 +8,9 @@
#import "BlankZeroFormatter.h"
@implementation BlankZeroFormatter
- (NSString *) stringForObjectValue:(id)object
{
- (NSString *)stringForObjectValue:(id)object {
NSString *result = nil;
int value;
@ -30,8 +28,7 @@
return result;
}
- (BOOL) getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error
{
- (BOOL)getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error {
if(NULL != object) {
*object = [NSNumber numberWithInt:[string intValue]];
@ -41,8 +38,7 @@
return NO;
}
- (NSAttributedString *) attributedStringForObjectValue:(id)object withDefaultAttributes:(NSDictionary *)attributes
{
- (NSAttributedString *)attributedStringForObjectValue:(id)object withDefaultAttributes:(NSDictionary *)attributes {
NSAttributedString *result = nil;
result = [[NSAttributedString alloc] initWithString:[self stringForObjectValue:object] attributes:attributes];

View file

@ -8,9 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface IndexFormatter : NSFormatter {
}
@end

View file

@ -8,11 +8,9 @@
#import "IndexFormatter.h"
@implementation IndexFormatter
- (NSString *) stringForObjectValue:(id)object
{
- (NSString *)stringForObjectValue:(id)object {
NSString *result = nil;
int value;
@ -27,8 +25,7 @@
return result;
}
- (BOOL) getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error
{
- (BOOL)getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error {
if(NULL != object) {
*object = [NSNumber numberWithInt:[string intValue]];
@ -38,8 +35,7 @@
return NO;
}
- (NSAttributedString *) attributedStringForObjectValue:(id)object withDefaultAttributes:(NSDictionary *)attributes
{
- (NSAttributedString *)attributedStringForObjectValue:(id)object withDefaultAttributes:(NSDictionary *)attributes {
NSAttributedString *result = nil;
result = [[NSAttributedString alloc] initWithString:[self stringForObjectValue:object] attributes:attributes];

View file

@ -20,8 +20,7 @@
#import <Cocoa/Cocoa.h>
@interface SecondsFormatter : NSFormatter
{
@interface SecondsFormatter : NSFormatter {
}
@end

View file

@ -22,8 +22,7 @@
@implementation SecondsFormatter
- (NSString *) stringForObjectValue:(id)object
{
- (NSString *)stringForObjectValue:(id)object {
NSString *result = nil;
unsigned value;
unsigned days = 0;
@ -52,22 +51,18 @@
if(0 < days) {
result = [NSString stringWithFormat:@"%u:%.2u:%.2u:%.2u", days, hours, minutes, seconds];
}
else if(0 < hours) {
} else if(0 < hours) {
result = [NSString stringWithFormat:@"%u:%.2u:%.2u", hours, minutes, seconds];
}
else if(0 < minutes) {
} else if(0 < minutes) {
result = [NSString stringWithFormat:@"%u:%.2u", minutes, seconds];
}
else {
} else {
result = [NSString stringWithFormat:@"0:%.2u", seconds];
}
return result;
}
- (BOOL) getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error
{
- (BOOL)getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error {
NSScanner *scanner = nil;
BOOL result = NO;
int value = 0;
@ -76,7 +71,6 @@
scanner = [NSScanner scannerWithString:string];
while(NO == [scanner isAtEnd]) {
// Grab a value
if([scanner scanInt:&value]) {
seconds *= 60;
@ -90,16 +84,14 @@
if(result && NULL != object) {
*object = [NSNumber numberWithUnsignedInt:seconds];
}
else if(NULL != error) {
} else if(NULL != error) {
*error = @"Couldn't convert value to seconds";
}
return result;
}
- (NSAttributedString *) attributedStringForObjectValue:(id)object withDefaultAttributes:(NSDictionary *)attributes
{
- (NSAttributedString *)attributedStringForObjectValue:(id)object withDefaultAttributes:(NSDictionary *)attributes {
NSAttributedString *result = nil;
result = [[NSAttributedString alloc] initWithString:[self stringForObjectValue:object] attributes:attributes];

View file

@ -6,12 +6,10 @@
// Copyright 2009 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "AppController.h"
#import <Cocoa/Cocoa.h>
@interface InfoWindowController : NSWindowController
{
@interface InfoWindowController : NSWindowController {
IBOutlet id playlistSelectionController;
IBOutlet id currentEntryController;
IBOutlet AppController *appController;

View file

@ -7,36 +7,32 @@
//
#import "InfoWindowController.h"
#import "AppController.h"
#import "Logging.h"
#import "MissingAlbumArtTransformer.h"
#import "PlaylistEntry.h"
#import "Logging.h"
#import "AppController.h"
@implementation InfoWindowController
@synthesize valueToDisplay;
+ (void)initialize
{
+ (void)initialize {
NSValueTransformer *missingAlbumArtTransformer = [[MissingAlbumArtTransformer alloc] init];
[NSValueTransformer setValueTransformer:missingAlbumArtTransformer
forName:@"MissingAlbumArtTransformer"];
}
- (id)init
{
- (id)init {
return [super initWithWindowNibName:@"InfoInspector"];
}
- (void)awakeFromNib
{
- (void)awakeFromNib {
[playlistSelectionController addObserver:self forKeyPath:@"selection" options:NSKeyValueObservingOptionNew context:nil];
[currentEntryController addObserver:self forKeyPath:@"content" options:NSKeyValueObservingOptionNew context:nil];
[appController addObserver:self forKeyPath:@"miniMode" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// Avoid "selection" because it creates a proxy that's hard to reason with when we don't need to write.
PlaylistEntry *currentSelection = [[playlistSelectionController selectedObjects] firstObject];
if(currentSelection != NULL) {
@ -46,8 +42,7 @@
}
}
- (IBAction)toggleWindow:(id)sender
{
- (IBAction)toggleWindow:(id)sender {
if([[self window] isVisible])
[[self window] orderOut:self];
else {

View file

@ -8,9 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface MissingAlbumArtTransformer : NSValueTransformer {
}
@end

View file

@ -8,11 +8,14 @@
#import "MissingAlbumArtTransformer.h"
@implementation MissingAlbumArtTransformer
+ (Class)transformedValueClass { return [NSImage class]; }
+ (BOOL)allowsReverseTransformation { return NO; }
+ (Class)transformedValueClass {
return [NSImage class];
}
+ (BOOL)allowsReverseTransformation {
return NO;
}
// Convert from NSImage to NSImage
- (id)transformedValue:(id)value {

0
Playlist/DNDArrayController.h Executable file → Normal file
View file

9
Playlist/DNDArrayController.m Executable file → Normal file
View file

@ -15,8 +15,7 @@ NSString *iTunesDropType = @"com.apple.tv.metadata";
NSPasteboardType fileType;
if(@available(macOS 10.13, *)) {
fileType = NSPasteboardTypeFileURL;
}
else {
} else {
fileType = NSFilenamesPboardType;
}
[self.tableView registerForDraggedTypes:@[CogDNDIndexType,
@ -25,7 +24,6 @@ NSString *iTunesDropType = @"com.apple.tv.metadata";
iTunesDropType]];
}
- (id<NSPasteboardWriting>)tableView:(NSTableView *)tableView
pasteboardWriterForRow:(NSInteger)row {
NSPasteboardItem *item = [[NSPasteboardItem alloc] init];
@ -34,7 +32,6 @@ NSString *iTunesDropType = @"com.apple.tv.metadata";
return item;
}
- (void)tableView:(NSTableView *)tableView
draggingSession:(NSDraggingSession *)session
willBeginAtPoint:(NSPoint)screenPoint
@ -42,7 +39,6 @@ NSString *iTunesDropType = @"com.apple.tv.metadata";
DLog(@"Drag session started with indexes: %@", rowIndexes);
}
- (NSDragOperation)tableView:(NSTableView *)tableView
validateDrop:(id<NSDraggingInfo>)info
proposedRow:(NSInteger)row
@ -60,7 +56,6 @@ NSString *iTunesDropType = @"com.apple.tv.metadata";
return dragOp;
}
- (BOOL)tableView:(NSTableView *)tableView
acceptDrop:(id<NSDraggingInfo>)info
row:(NSInteger)row
@ -91,7 +86,6 @@ NSString *iTunesDropType = @"com.apple.tv.metadata";
return NO;
}
- (void)moveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet
toIndex:(NSUInteger)insertIndex {
__block NSUInteger rangeCount = 0;
@ -174,5 +168,4 @@ NSString *iTunesDropType = @"com.apple.tv.metadata";
}
}
@end

View file

@ -6,9 +6,9 @@
// Copyright 2005 Vincent Spader All rights reserved.
//
#import "DNDArrayController.h"
#import <Cocoa/Cocoa.h>
#import <Foundation/NSUndoManager.h>
#import "DNDArrayController.h"
@class PlaylistLoader;
@class PlaylistEntry;
@ -26,7 +26,9 @@ static inline BOOL IsRepeatOneSet() {
return [[NSUserDefaults standardUserDefaults] integerForKey:@"repeat"] == RepeatModeRepeatOne;
}
typedef enum { ShuffleOff = 0, ShuffleAlbums, ShuffleAll } ShuffleMode;
typedef enum { ShuffleOff = 0,
ShuffleAlbums,
ShuffleAll } ShuffleMode;
typedef NS_ENUM(NSInteger, URLOrigin) {
URLOriginInternal = 0,

View file

@ -11,12 +11,12 @@
#import "PlaylistEntry.h"
#import "PlaylistLoader.h"
#import "RepeatTransformers.h"
#import "SQLiteStore.h"
#import "Shuffle.h"
#import "ShuffleTransformers.h"
#import "SpotlightWindowController.h"
#import "StatusImageTransformer.h"
#import "ToggleQueueTitleTransformer.h"
#import "SQLiteStore.h"
#import "Logging.h"
@ -127,8 +127,7 @@ static NSArray * cellIdentifiers = nil;
[self updatePlaylistIndexes];
[self updateTotalTime];
[self.tableView reloadData];
}
else if ([keyPath isEqualToString:@"values.fontSize"]) {
} else if([keyPath isEqualToString:@"values.fontSize"]) {
[self updateRowSize];
}
}
@ -136,8 +135,7 @@ static NSArray * cellIdentifiers = nil;
static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_block_t block) {
if(dispatch_queue_get_label(queue) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) {
block();
}
else {
} else {
dispatch_sync(queue, block);
}
}
@ -161,7 +159,8 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
}
}
if(updated) {
[[SQLiteStore sharedStore] syncPlaylistEntries:arranged progressCall:^(double progress) {
[[SQLiteStore sharedStore] syncPlaylistEntries:arranged
progressCall:^(double progress) {
[self setProgressBarStatus:progress];
}];
}
@ -319,10 +318,8 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
NSFontDescriptor *fontDesc = [sysFont fontDescriptor];
NSDictionary *fontFeatureSettings = @{ NSFontFeatureTypeIdentifierKey: @(kNumberSpacingType),
NSFontFeatureSelectorIdentifierKey: @(kMonospacedNumbersSelector)
};
NSFontFeatureSelectorIdentifierKey: @(kMonospacedNumbersSelector) };
NSDictionary *fontFeatureAttributes = @{ NSFontFeatureSettingsAttribute: @[fontFeatureSettings] };
@ -373,14 +370,17 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
- (void)moveObjectsFromIndex:(NSUInteger)fromIndex
toArrangedObjectIndexes:(NSIndexSet *)indexSet {
[[[self undoManager] prepareWithInvocationTarget:self]
moveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:fromIndex];
moveObjectsInArrangedObjectsFromIndexes:indexSet
toIndex:fromIndex];
NSString *actionName =
[NSString stringWithFormat:@"Reordering %lu entries", (unsigned long)[indexSet count]];
[[self undoManager] setActionName:actionName];
[super moveObjectsFromIndex:fromIndex toArrangedObjectIndexes:indexSet];
[[SQLiteStore sharedStore] playlistMoveObjectsFromIndex:fromIndex toArrangedObjectIndexes:indexSet progressCall:^(double progress) {
[[SQLiteStore sharedStore] playlistMoveObjectsFromIndex:fromIndex
toArrangedObjectIndexes:indexSet
progressCall:^(double progress) {
[self setProgressBarStatus:progress];
}];
@ -390,14 +390,17 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
- (void)moveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet
toIndex:(NSUInteger)insertIndex {
[[[self undoManager] prepareWithInvocationTarget:self]
moveObjectsFromIndex:insertIndex toArrangedObjectIndexes:indexSet];
moveObjectsFromIndex:insertIndex
toArrangedObjectIndexes:indexSet];
NSString *actionName =
[NSString stringWithFormat:@"Reordering %lu entries", (unsigned long)[indexSet count]];
[[self undoManager] setActionName:actionName];
[super moveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:insertIndex];
[[SQLiteStore sharedStore] playlistMoveObjectsInArrangedObjectsFromIndexes:indexSet toIndex:insertIndex progressCall:^(double progress) {
[[SQLiteStore sharedStore] playlistMoveObjectsInArrangedObjectsFromIndexes:indexSet
toIndex:insertIndex
progressCall:^(double progress) {
[self setProgressBarStatus:progress];
}];
@ -418,8 +421,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
if(@available(macOS 10.13, *)) {
[item setData:[song.URL dataRepresentation] forType:NSPasteboardTypeFileURL];
}
else {
} else {
[item setPropertyList:@[song.URL] forType:NSFilenamesPboardType];
}
@ -439,8 +441,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
NSPasteboardType fileType;
if(@available(macOS 10.13, *)) {
fileType = NSPasteboardTypeFileURL;
}
else {
} else {
fileType = NSFilenamesPboardType;
}
NSArray *supportedTypes =
@ -465,8 +466,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
urls = [NSKeyedUnarchiver unarchivedObjectOfClasses:allowed
fromData:data
error:&error];
}
else {
} else {
urls = [NSUnarchiver unarchiveObjectWithData:data];
}
}
@ -577,7 +577,9 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
[NSString stringWithFormat:@"Adding %lu entries", (unsigned long)[objects count]];
[[self undoManager] setActionName:actionName];
[[SQLiteStore sharedStore] playlistInsertTracks:objects atObjectIndexes:indexes progressCall:^(double progress) {
[[SQLiteStore sharedStore] playlistInsertTracks:objects
atObjectIndexes:indexes
progressCall:^(double progress) {
[self setProgressBarStatus:progress];
}];
@ -631,7 +633,8 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
currentEntry.index = -i - 1;
}
[[SQLiteStore sharedStore] playlistRemoveTracksAtIndexes:unarrangedIndexes progressCall:^(double progress) {
[[SQLiteStore sharedStore] playlistRemoveTracksAtIndexes:unarrangedIndexes
progressCall:^(double progress) {
[self setProgressBarStatus:progress];
}];
@ -1103,12 +1106,14 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
}
*/
- (IBAction)searchByArtist:(id)sender; {
- (IBAction)searchByArtist:(id)sender;
{
PlaylistEntry *entry = [[self arrangedObjects] objectAtIndex:[self selectionIndex]];
[spotlightWindowController searchForArtist:[entry artist]];
}
- (IBAction)searchByAlbum:(id)sender; {
- (IBAction)searchByAlbum:(id)sender;
{
PlaylistEntry *entry = [[self arrangedObjects] objectAtIndex:[self selectionIndex]];
[spotlightWindowController searchForAlbum:[entry album]];
}
@ -1195,8 +1200,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
[refreshSet addIndex:[queueItem index]];
}
for (PlaylistEntry *queueItem in queueList)
{
for(PlaylistEntry *queueItem in queueList) {
[refreshSet addIndex:[queueItem index]];
}
@ -1223,8 +1227,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
[store queueAddItem:[queueItem index]];
}
for (PlaylistEntry *queueItem in queueList)
{
for(PlaylistEntry *queueItem in queueList) {
[refreshSet addIndex:[queueItem index]];
}
@ -1328,7 +1331,8 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
BOOL shouldPlay = modifierPressed; // The default is NO for internal insertions
if(origin == URLOriginExternal) { // For external insertions, we look at the preference
shouldPlay = [behavior isEqualToString:@"clearAndPlay"] ||
[behavior isEqualToString:@"enqueueAndPlay"];;
[behavior isEqualToString:@"enqueueAndPlay"];
;
}
// Auto start playback

View file

@ -67,88 +67,71 @@
// The following read-only keys depend on the values of other properties
+ (NSSet *)keyPathsForValuesAffectingDisplay
{
+ (NSSet *)keyPathsForValuesAffectingDisplay {
return [NSSet setWithObjects:@"artist", @"title", nil];
}
+ (NSSet *)keyPathsForValuesAffectingLength
{
+ (NSSet *)keyPathsForValuesAffectingLength {
return [NSSet setWithObject:@"totalFrames"];
}
+ (NSSet *)keyPathsForValuesAffectingPath
{
+ (NSSet *)keyPathsForValuesAffectingPath {
return [NSSet setWithObject:@"URL"];
}
+ (NSSet *)keyPathsForValuesAffectingFilename
{
+ (NSSet *)keyPathsForValuesAffectingFilename {
return [NSSet setWithObject:@"URL"];
}
+ (NSSet *)keyPathsForValuesAffectingStatus
{
+ (NSSet *)keyPathsForValuesAffectingStatus {
return [NSSet setWithObjects:@"current", @"queued", @"error", @"stopAfter", nil];
}
+ (NSSet *)keyPathsForValuesAffectingStatusMessage
{
+ (NSSet *)keyPathsForValuesAffectingStatusMessage {
return [NSSet setWithObjects:@"current", @"queued", @"queuePosition", @"error", @"errorMessage", @"stopAfter", nil];
}
+ (NSSet *)keyPathsForValuesAffectingSpam
{
+ (NSSet *)keyPathsForValuesAffectingSpam {
return [NSSet setWithObjects:@"albumartist", @"artist", @"title", @"album", @"track", @"disc", @"totalFrames", @"currentPosition", @"bitrate", nil];
}
+ (NSSet *)keyPathsForValuesAffectingTrackText
{
+ (NSSet *)keyPathsForValuesAffectingTrackText {
return [NSSet setWithObjects:@"track", @"disc", nil];
}
+ (NSSet *)keyPathsForValuesAffectingYearText
{
+ (NSSet *)keyPathsForValuesAffectingYearText {
return [NSSet setWithObject:@"year"];
}
+ (NSSet *)keyPathsForValuesAffectingCuesheetPresent
{
+ (NSSet *)keyPathsForValuesAffectingCuesheetPresent {
return [NSSet setWithObject:@"cuesheet"];
}
+ (NSSet *)keyPathsForValuesAffectingPositionText
{
+ (NSSet *)keyPathsForValuesAffectingPositionText {
return [NSSet setWithObject:@"currentPosition"];
}
+ (NSSet *)keyPathsForValuesAffectingLengthText
{
+ (NSSet *)keyPathsForValuesAffectingLengthText {
return [NSSet setWithObject:@"length"];
}
+ (NSSet *)keyPathsForValuesAffectingAlbumArt
{
+ (NSSet *)keyPathsForValuesAffectingAlbumArt {
return [NSSet setWithObject:@"albumArtInternal"];
}
+ (NSSet *)keyPathsForValuesAffectingGainCorrection
{
+ (NSSet *)keyPathsForValuesAffectingGainCorrection {
return [NSSet setWithObjects:@"replayGainAlbumGain", @"replayGainAlbumPeak", @"replayGainTrackGain", @"replayGainTrackPeak", @"volume", nil];
}
+ (NSSet *)keyPathsForValuesAffectingGainInfo
{
+ (NSSet *)keyPathsForValuesAffectingGainInfo {
return [NSSet setWithObjects:@"replayGainAlbumGain", @"replayGainAlbumPeak", @"replayGainTrackGain", @"replayGainTrackPeak", @"volume", nil];
}
- (NSString *)description
{
- (NSString *)description {
return [NSString stringWithFormat:@"PlaylistEntry %li:(%@)", self.index, self.URL];
}
- (id)init
{
- (id)init {
if(self = [super init]) {
self.replayGainAlbumGain = 0;
self.replayGainAlbumPeak = 0;
@ -159,8 +142,7 @@
return self;
}
- (void)dealloc
{
- (void)dealloc {
self.errorMessage = nil;
self.URL = nil;
@ -183,24 +165,20 @@
// Get the URL if the title is blank
@synthesize title;
- (NSString *)title
{
if((title == nil || [title isEqualToString:@""]) && self.URL)
{
- (NSString *)title {
if((title == nil || [title isEqualToString:@""]) && self.URL) {
return [[self.URL path] lastPathComponent];
}
return title;
}
@synthesize rawTitle;
- (NSString *)rawTitle
{
- (NSString *)rawTitle {
return title;
}
@dynamic display;
- (NSString *)display
{
- (NSString *)display {
if((self.artist == NULL) || ([self.artist isEqualToString:@""]))
return self.title;
else {
@ -209,8 +187,7 @@
}
@dynamic spam;
- (NSString *)spam
{
- (NSString *)spam {
BOOL hasBitrate = (self.bitrate != 0);
BOOL hasArtist = (self.artist != nil) && (![self.artist isEqualToString:@""]);
BOOL hasAlbumArtist = (self.albumartist != nil) && (![self.albumartist isEqualToString:@""]);
@ -242,8 +219,7 @@
[elements addObject:@"["];
if(hasCodec) {
[elements addObject:self.codec];
}
else {
} else {
[elements addObject:[extension uppercaseString]];
}
if(hasBitrate) {
@ -257,8 +233,7 @@
if(hasArtist) {
if(hasAlbumArtist) {
[elements addObject:self.albumartist];
}
else {
} else {
[elements addObject:self.artist];
}
[elements addObject:@" - "];
@ -276,8 +251,7 @@
if(hasTitle) {
[elements addObject:title];
}
else {
} else {
[elements addObject:filename];
}
@ -305,116 +279,85 @@
}
@dynamic trackText;
-(NSString *)trackText
{
if ([self.track intValue])
{
if ([self.disc intValue])
{
- (NSString *)trackText {
if([self.track intValue]) {
if([self.disc intValue]) {
return [NSString stringWithFormat:@"%@.%02u", self.disc, [self.track intValue]];
}
else
{
} else {
return [NSString stringWithFormat:@"%02u", [self.track intValue]];
}
}
else
{
} else {
return @"";
}
}
@dynamic yearText;
-(NSString *)yearText
{
if ([self.year intValue])
{
- (NSString *)yearText {
if([self.year intValue]) {
return [NSString stringWithFormat:@"%@", self.year];
}
else
{
} else {
return @"";
}
}
@dynamic cuesheetPresent;
-(NSString *)cuesheetPresent
{
if (cuesheet && [cuesheet length])
{
- (NSString *)cuesheetPresent {
if(cuesheet && [cuesheet length]) {
return @"yes";
}
else
{
} else {
return @"no";
}
}
@dynamic gainCorrection;
- (NSString *)gainCorrection
{
if (replayGainAlbumGain)
{
- (NSString *)gainCorrection {
if(replayGainAlbumGain) {
if(replayGainAlbumPeak)
return @"Album Gain plus Peak";
else
return @"Album Gain";
}
else if (replayGainTrackGain)
{
} else if(replayGainTrackGain) {
if(replayGainTrackPeak)
return @"Track Gain plus Peak";
else
return @"Track Gain";
}
else if (volume && volume != 1)
{
} else if(volume && volume != 1) {
return @"Volume scale";
}
else
{
} else {
return @"None";
}
}
@dynamic gainInfo;
- (NSString *)gainInfo
{
- (NSString *)gainInfo {
NSMutableArray *gainItems = [[NSMutableArray alloc] init];
if (replayGainAlbumGain)
{
if(replayGainAlbumGain) {
[gainItems addObject:[NSString stringWithFormat:@"Album Gain: %+.2f dB", replayGainAlbumGain]];
}
if (replayGainAlbumPeak)
{
if(replayGainAlbumPeak) {
[gainItems addObject:[NSString stringWithFormat:@"Album Peak: %.6f", replayGainAlbumPeak]];
}
if (replayGainTrackGain)
{
if(replayGainTrackGain) {
[gainItems addObject:[NSString stringWithFormat:@"Track Gain: %+.2f dB", replayGainTrackGain]];
}
if (replayGainTrackPeak)
{
if(replayGainTrackPeak) {
[gainItems addObject:[NSString stringWithFormat:@"Track Peak: %.6f", replayGainTrackPeak]];
}
if (volume && volume != 1)
{
if(volume && volume != 1) {
[gainItems addObject:[NSString stringWithFormat:@"Volume Scale: %.2f%C", volume, (unichar)0x00D7]];
}
return [gainItems componentsJoinedByString:@"\n"];
}
@dynamic positionText;
- (NSString *)positionText
{
- (NSString *)positionText {
SecondsFormatter *secondsFormatter = [[SecondsFormatter alloc] init];
NSString *time = [secondsFormatter stringForObjectValue:[NSNumber numberWithFloat:currentPosition]];
return time;
}
@dynamic lengthText;
- (NSString *)lengthText
{
- (NSString *)lengthText {
SecondsFormatter *secondsFormatter = [[SecondsFormatter alloc] init];
NSString *time = [secondsFormatter stringForObjectValue:[self length]];
return time;
@ -423,15 +366,13 @@
@synthesize albumArtInternal;
@dynamic albumArt;
- (NSImage *)albumArt
{
- (NSImage *)albumArt {
if(!albumArtInternal) return nil;
NSString *imageCacheTag = [NSString stringWithFormat:@"%@-%@-%@-%@", album, artist, genre, year];
NSImage *image = [NSImage imageNamed:imageCacheTag];
if (image == nil)
{
if(image == nil) {
image = [[NSImage alloc] initWithData:albumArtInternal];
[image setName:imageCacheTag];
}
@ -439,23 +380,19 @@
return image;
}
- (void)setAlbumArt:(id)data
{
if ([data isKindOfClass:[NSData class]])
{
- (void)setAlbumArt:(id)data {
if([data isKindOfClass:[NSData class]]) {
[self setAlbumArtInternal:data];
}
}
@dynamic length;
- (NSNumber *)length
{
- (NSNumber *)length {
return [NSNumber numberWithDouble:(self.metadataLoaded) ? ((double)self.totalFrames / self.sampleRate) : 0.0];
}
@dynamic path;
- (NSString *)path
{
- (NSString *)path {
if([self.URL isFileURL])
return [[self.URL path] stringByAbbreviatingWithTildeInPath];
else
@ -463,28 +400,19 @@
}
@dynamic filename;
- (NSString *)filename
{
- (NSString *)filename {
return [[self.URL path] lastPathComponent];
}
@dynamic status;
- (NSString *)status
{
if (self.stopAfter)
{
- (NSString *)status {
if(self.stopAfter) {
return @"stopAfter";
}
else if (self.current)
{
} else if(self.current) {
return @"playing";
}
else if (self.queued)
{
} else if(self.queued) {
return @"queued";
}
else if (self.error)
{
} else if(self.error) {
return @"error";
}
@ -492,37 +420,25 @@
}
@dynamic statusMessage;
- (NSString *)statusMessage
{
if (self.stopAfter)
{
- (NSString *)statusMessage {
if(self.stopAfter) {
return @"Stopping once finished...";
}
else if (self.current)
{
} else if(self.current) {
return @"Playing...";
}
else if (self.queued)
{
} else if(self.queued) {
return [NSString stringWithFormat:@"Queued: %li", self.queuePosition + 1];
}
else if (self.error)
{
} else if(self.error) {
return errorMessage;
}
return nil;
}
- (void)setMetadata:(NSDictionary *)metadata
{
if (metadata == nil)
{
- (void)setMetadata:(NSDictionary *)metadata {
if(metadata == nil) {
self.error = YES;
self.errorMessage = @"Unable to retrieve metadata.";
}
else
{
} else {
[self setValuesForKeysWithDictionary:metadata];
}

View file

@ -8,9 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface PlaylistHeaderView : NSTableHeaderView {
}
@end

View file

@ -8,18 +8,15 @@
#import "PlaylistHeaderView.h"
@implementation PlaylistHeaderView
- (void)mouseDown:(NSEvent *)theEvent
{
- (void)mouseDown:(NSEvent *)theEvent {
NSPoint event_location = [theEvent locationInWindow];
NSPoint local_point = [self convertPoint:event_location fromView:nil];
int column = (int)[self columnAtPoint:local_point];
if([theEvent clickCount] == 2 && column != -1) {
// compute whether the clickpoint is a column separator or not
BOOL clickedSeperator = NO;
// handle a click one pixel away at right
@ -45,7 +42,6 @@
// find the longest string display length in that column
float max_width = -1;
for(id row in boundArray) {
[cell setObjectValue:row];
float width = [cell cellSize].width;
@ -53,15 +49,12 @@
max_width = width;
}
// set the new width (plus a 5 pixel extra to avoid "..." string substitution)
[col setWidth:max_width + 5];
}
else
} else
[super mouseDown:theEvent];
}
else
} else
[super mouseDown:theEvent];
}

2
Playlist/PlaylistLoader.h Executable file → Normal file
View file

@ -6,9 +6,9 @@
// Copyright 2007 Vincent Spader All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "PlaylistController.h"
#import "PlaylistView.h"
#import <Cocoa/Cocoa.h>
@class PlaylistController;
@class PlaybackController;

230
Playlist/PlaylistLoader.m Executable file → Normal file
View file

@ -10,17 +10,17 @@
#include <mach/semaphore.h>
#import "PlaylistLoader.h"
#import "AppController.h"
#import "PlaylistController.h"
#import "PlaylistEntry.h"
#import "AppController.h"
#import "PlaylistLoader.h"
#import "NSFileHandle+CreateFile.h"
#import "CogAudio/AudioPlayer.h"
#import "CogAudio/AudioContainer.h"
#import "CogAudio/AudioPropertiesReader.h"
#import "CogAudio/AudioMetadataReader.h"
#import "CogAudio/AudioPlayer.h"
#import "CogAudio/AudioPropertiesReader.h"
#import "XmlContainer.h"
@ -34,11 +34,9 @@
@implementation PlaylistLoader
- (id)init
{
- (id)init {
self = [super init];
if (self)
{
if(self) {
[self initDefaults];
queue = [[NSOperationQueue alloc] init];
@ -48,8 +46,7 @@
return self;
}
- (void)initDefaults
{
- (void)initDefaults {
NSDictionary *defaultsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], @"readCueSheetsInFolders",
nil];
@ -57,39 +54,28 @@
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDictionary];
}
- (BOOL)save:(NSString *)filename
{
- (BOOL)save:(NSString *)filename {
NSString *ext = [filename pathExtension];
if ([ext isEqualToString:@"pls"])
{
if([ext isEqualToString:@"pls"]) {
return [self save:filename asType:kPlaylistPls];
}
else
{
} else {
return [self save:filename asType:kPlaylistM3u];
}
}
- (BOOL)save:(NSString *)filename asType:(PlaylistType)type
{
if (type == kPlaylistM3u)
{
- (BOOL)save:(NSString *)filename asType:(PlaylistType)type {
if(type == kPlaylistM3u) {
return [self saveM3u:filename];
}
else if (type == kPlaylistPls)
{
} else if(type == kPlaylistPls) {
return [self savePls:filename];
}
else if (type == kPlaylistXml)
{
} else if(type == kPlaylistXml) {
return [self saveXml:filename];
}
return NO;
}
- (NSString *)relativePathFrom:(NSString *)filename toURL:(NSURL *)entryURL
{
- (NSString *)relativePathFrom:(NSString *)filename toURL:(NSURL *)entryURL {
NSString *basePath = [[[filename stringByStandardizingPath] stringByDeletingLastPathComponent] stringByAppendingString:@"/"];
if([entryURL isFileURL]) {
@ -97,22 +83,19 @@
NSMutableString *entryPath = [[[entryURL path] stringByStandardizingPath] mutableCopy];
[entryPath replaceOccurrencesOfString:basePath withString:@"" options:(NSAnchoredSearch | NSLiteralSearch | NSCaseInsensitiveSearch) range:NSMakeRange(0, [entryPath length])];
if ([entryURL fragment])
{
if([entryURL fragment]) {
[entryPath appendString:@"#"];
[entryPath appendString:[entryURL fragment]];
}
return entryPath;
}
else {
} else {
// Write [entryURL absoluteString] to file
return [entryURL absoluteString];
}
}
- (BOOL)saveM3u:(NSString *)filename
{
- (BOOL)saveM3u:(NSString *)filename {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filename createFile:YES];
if(!fileHandle) {
ALog(@"Error saving m3u!");
@ -121,8 +104,7 @@
[fileHandle truncateFileAtOffset:0];
[fileHandle writeData:[@"#\n" dataUsingEncoding:NSUTF8StringEncoding]];
for (PlaylistEntry *pe in [playlistController arrangedObjects])
{
for(PlaylistEntry *pe in [playlistController arrangedObjects]) {
NSString *path = [self relativePathFrom:filename toURL:[pe URL]];
[fileHandle writeData:[[path stringByAppendingString:@"\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}
@ -132,8 +114,7 @@
return YES;
}
- (BOOL)savePls:(NSString *)filename
{
- (BOOL)savePls:(NSString *)filename {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filename createFile:YES];
if(!fileHandle) {
return NO;
@ -143,8 +124,7 @@
[fileHandle writeData:[[NSString stringWithFormat:@"[playlist]\nnumberOfEntries=%lu\n\n", (unsigned long)[[playlistController content] count]] dataUsingEncoding:NSUTF8StringEncoding]];
int i = 1;
for (PlaylistEntry *pe in [playlistController arrangedObjects])
{
for(PlaylistEntry *pe in [playlistController arrangedObjects]) {
NSString *path = [self relativePathFrom:filename toURL:[pe URL]];
NSString *entry = [NSString stringWithFormat:@"File%i=%@\n", i, path];
@ -158,8 +138,7 @@
return YES;
}
NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterList)
{
NSMutableDictionary *dictionaryWithPropertiesOfObject(id obj, NSArray *filterList) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
Class class = [obj class];
@ -176,9 +155,7 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
if(classObject) {
id subObj = dictionaryWithPropertiesOfObject([obj valueForKey:key], filterList);
[dict setObject:subObj forKey:key];
}
else
{
} else {
id value = [obj valueForKey:key];
if(value) [dict setObject:value forKey:key];
}
@ -194,8 +171,7 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
return dict;
}
- (BOOL)saveXml:(NSString *)filename
{
- (BOOL)saveXml:(NSString *)filename {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filename createFile:YES];
if(!fileHandle) {
return NO;
@ -208,8 +184,7 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
NSMutableArray *topLevel = [[NSMutableArray alloc] init];
for (PlaylistEntry *pe in [playlistController arrangedObjects])
{
for(PlaylistEntry *pe in [playlistController arrangedObjects]) {
BOOL error = [pe error];
NSMutableDictionary *dict = dictionaryWithPropertiesOfObject(pe, filterList);
@ -218,8 +193,7 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
[dict setObject:path forKey:@"URL"];
NSData *albumArt = [dict objectForKey:@"albumArtInternal"];
if (albumArt)
{
if(albumArt) {
[dict removeObjectForKey:@"albumArtInternal"];
NSString *hash = [albumArt MD5];
if(![albumArtSet objectForKey:hash])
@ -235,8 +209,7 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
NSMutableArray *queueList = [[NSMutableArray alloc] init];
for (PlaylistEntry *pe in [playlistController queueList])
{
for(PlaylistEntry *pe in [playlistController queueList]) {
[queueList addObject:[NSNumber numberWithInteger:pe.index]];
}
@ -253,24 +226,20 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
return YES;
}
- (NSArray *)fileURLsAtPath:(NSString *)path
{
- (NSArray *)fileURLsAtPath:(NSString *)path {
NSFileManager *manager = [NSFileManager defaultManager];
NSMutableArray *urls = [NSMutableArray array];
NSArray *subpaths = [manager subpathsAtPath:path];
for (NSString *subpath in subpaths)
{
for(NSString *subpath in subpaths) {
NSString *absoluteSubpath = [NSString pathWithComponents:@[path, subpath]];
BOOL isDir;
if ( [manager fileExistsAtPath:absoluteSubpath isDirectory:&isDir] && isDir == NO)
{
if([manager fileExistsAtPath:absoluteSubpath isDirectory:&isDir] && isDir == NO) {
if([[absoluteSubpath pathExtension] caseInsensitiveCompare:@"cue"] != NSOrderedSame ||
[[NSUserDefaults standardUserDefaults] boolForKey:@"readCueSheetsInFolders"])
{
[[NSUserDefaults standardUserDefaults] boolForKey:@"readCueSheetsInFolders"]) {
[urls addObject:[NSURL fileURLWithPath:absoluteSubpath]];
}
}
@ -285,8 +254,7 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_block_t block) {
if(dispatch_queue_get_label(queue) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) {
block();
}
else {
} else {
dispatch_sync(queue, block);
}
}
@ -297,8 +265,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
});
}
- (NSArray*)insertURLs:(NSArray *)urls atIndex:(NSInteger)index sort:(BOOL)sort
{
- (NSArray *)insertURLs:(NSArray *)urls atIndex:(NSInteger)index sort:(BOOL)sort {
NSMutableSet *uniqueURLs = [NSMutableSet set];
NSMutableArray *expandedURLs = [NSMutableArray array];
@ -309,8 +276,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
double progress = 0.0;
if (!urls)
{
if(!urls) {
[self setProgressBarStatus:-1];
return @[];
}
@ -323,25 +289,18 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
double progressstep = [urls count] ? 20.0 / (double)([urls count]) : 0;
NSURL *url;
for (url in urls)
{
for(url in urls) {
if([url isFileURL]) {
BOOL isDir;
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir])
{
if (isDir == YES)
{
if([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir]) {
if(isDir == YES) {
// Get subpaths
[expandedURLs addObjectsFromArray:[self fileURLsAtPath:[url path]]];
}
else
{
} else {
[expandedURLs addObject:[NSURL fileURLWithPath:[url path]]];
}
}
}
else
{
} else {
// Non-file URL..
[expandedURLs addObject:url];
}
@ -358,20 +317,16 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
DLog(@"Expanded urls: %@", expandedURLs);
NSArray *sortedURLs;
if (sort == YES)
{
if(sort == YES) {
sortedURLs = [expandedURLs sortedArrayUsingSelector:@selector(finderCompare:)];
// sortedURLs = [expandedURLs sortedArrayUsingSelector:@selector(compareTrackNumbers:)];
}
else
{
} else {
sortedURLs = expandedURLs;
}
progressstep = [sortedURLs count] ? 20.0 / (double)([sortedURLs count]) : 0;
for (url in sortedURLs)
{
for(url in sortedURLs) {
// Container vs non-container url
if([[self acceptableContainerTypes] containsObject:[[url pathExtension] lowercaseString]]) {
NSArray *urls = [AudioContainer urlsForContainerURL:url];
@ -381,18 +336,13 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
// Make sure the container isn't added twice.
[uniqueURLs addObject:url];
}
else {
} else {
/* Fall back on adding the raw file if all container parsers have failed. */
[fileURLs addObject:url];
}
}
else if ([[[url pathExtension] lowercaseString] isEqualToString:@"xml"])
{
} else if([[[url pathExtension] lowercaseString] isEqualToString:@"xml"]) {
xmlData = [XmlContainer entriesForContainerURL:url];
}
else
{
} else {
[fileURLs addObject:url];
}
@ -409,8 +359,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
progressstep = [fileURLs count] ? 20.0 / (double)([fileURLs count]) : 0;
for (url in fileURLs)
{
for(url in fileURLs) {
progress += progressstep;
if(![[AudioPlayer schemes] containsObject:[url scheme]])
@ -422,8 +371,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
if([url isFileURL] && ![[AudioPlayer fileTypes] containsObject:ext])
continue;
if (![uniqueURLs containsObject:url])
{
if(![uniqueURLs containsObject:url]) {
[validURLs addObject:url];
[uniqueURLs addObject:url];
@ -440,8 +388,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
progressstep = [containedURLs count] ? 20.0 / (double)([containedURLs count]) : 0;
for (url in containedURLs)
{
for(url in containedURLs) {
progress += progressstep;
if(![[AudioPlayer schemes] containsObject:[url scheme]])
@ -465,8 +412,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
if(xmlData) count += [[xmlData objectForKey:@"entries"] count];
// no valid URLs, or they use an unsupported URL scheme
if (!count)
{
if(!count) {
[self setProgressBarStatus:-1];
return @[];
}
@ -475,8 +421,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
NSInteger i = 0;
NSMutableArray *entries = [NSMutableArray arrayWithCapacity:count];
for (NSURL *url in validURLs)
{
for(NSURL *url in validURLs) {
PlaylistEntry *pe;
pe = [[PlaylistEntry alloc] init];
@ -494,10 +439,8 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
NSInteger j = index + i;
if (xmlData)
{
for (NSDictionary *entry in [xmlData objectForKey:@"entries"])
{
if(xmlData) {
for(NSDictionary *entry in [xmlData objectForKey:@"entries"]) {
PlaylistEntry *pe;
pe = [[PlaylistEntry alloc] init];
@ -517,13 +460,11 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
[playlistController insertObjects:entries atArrangedObjectIndexes:is];
if (xmlData && [[xmlData objectForKey:@"queue"] count])
{
if(xmlData && [[xmlData objectForKey:@"queue"] count]) {
[playlistController emptyQueueList:self];
i = 0;
for (NSNumber *index in [xmlData objectForKey:@"queue"])
{
for(NSNumber *index in [xmlData objectForKey:@"queue"]) {
NSInteger indexVal = [index intValue] + j;
PlaylistEntry *pe = [entries objectAtIndex:indexVal];
pe.queuePosition = i;
@ -560,8 +501,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
}
}
- (void)loadInfoForEntries:(NSArray *)entries
{
- (void)loadInfoForEntries:(NSArray *)entries {
NSMutableIndexSet *update_indexes = [[NSMutableIndexSet alloc] init];
long i, j;
NSMutableIndexSet *load_info_indexes = [[NSMutableIndexSet alloc] init];
@ -582,8 +522,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
i = 0;
j = 0;
for (PlaylistEntry *pe in entries)
{
for(PlaylistEntry *pe in entries) {
long idx = j++;
if([pe metadataLoaded]) continue;
@ -594,8 +533,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
++i;
}
if (!i)
{
if(!i) {
[playlistController performSelectorOnMainThread:@selector(updateTotalTime) withObject:nil waitUntilDone:NO];
return;
}
@ -607,8 +545,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
__block NSMutableArray *weakArray = outArray;
{
[load_info_indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop)
{
[load_info_indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *_Nonnull stop) {
__block PlaylistEntry *weakPe = [entries objectAtIndex:idx];
NSBlockOperation *op = [[NSBlockOperation alloc] init];
@ -670,8 +607,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
[self setProgressBarStatus:-1];
}
// To be called on main thread only
- (void)syncLoadInfoForEntries:(NSArray *)entries
{
- (void)syncLoadInfoForEntries:(NSArray *)entries {
NSMutableIndexSet *update_indexes = [[NSMutableIndexSet alloc] init];
long i, j;
NSMutableIndexSet *load_info_indexes = [[NSMutableIndexSet alloc] init];
@ -680,8 +616,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
i = 0;
j = 0;
for (PlaylistEntry *pe in entries)
{
for(PlaylistEntry *pe in entries) {
long idx = j++;
if([pe metadataLoaded]) continue;
@ -692,14 +627,12 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
++i;
}
if (!i)
{
if(!i) {
[self->playlistController updateTotalTime];
return;
}
[load_info_indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop)
{
[load_info_indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *_Nonnull stop) {
PlaylistEntry *pe = [entries objectAtIndex:idx];
DLog(@"Loading metadata for %@", pe.URL);
@ -725,23 +658,19 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
}
}
- (void)clear:(id)sender
{
- (void)clear:(id)sender {
[playlistController clear:sender];
}
- (NSArray*)addURLs:(NSArray *)urls sort:(BOOL)sort
{
- (NSArray *)addURLs:(NSArray *)urls sort:(BOOL)sort {
return [self insertURLs:urls atIndex:(int)[[playlistController content] count] sort:sort];
}
- (NSArray*)addURL:(NSURL *)url
{
- (NSArray *)addURL:(NSURL *)url {
return [self insertURLs:@[url] atIndex:(int)[[playlistController content] count] sort:NO];
}
- (NSArray*)addDatabase
{
- (NSArray *)addDatabase {
SQLiteStore *store = [SQLiteStore sharedStore];
int64_t count = [store playlistGetCount];
@ -749,8 +678,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
NSInteger i = 0;
NSMutableArray *entries = [NSMutableArray arrayWithCapacity:count];
for (i = 0; i < count; ++i)
{
for(i = 0; i < count; ++i) {
PlaylistEntry *pe = [store playlistGetCachedItem:i];
pe.queuePosition = -1;
@ -764,14 +692,12 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
count = [store queueGetCount];
if (count)
{
if(count) {
NSMutableIndexSet *refreshSet = [[NSMutableIndexSet alloc] init];
[playlistController emptyQueueListUnsynced];
for (i = 0; i < count; ++i)
{
for(i = 0; i < count; ++i) {
NSInteger indexVal = [store queueGetEntry:i];
PlaylistEntry *pe = [entries objectAtIndex:indexVal];
pe.queuePosition = i;
@ -790,35 +716,29 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
// Clear the selection
[playlistController setSelectionIndexes:[NSIndexSet indexSet]];
if ([entries count])
{
if([entries count]) {
[self performSelectorInBackground:@selector(loadInfoForEntries:) withObject:entries];
}
return entries;
}
- (NSArray *)acceptableFileTypes
{
- (NSArray *)acceptableFileTypes {
return [[self acceptableContainerTypes] arrayByAddingObjectsFromArray:[AudioPlayer fileTypes]];
}
- (NSArray *)acceptablePlaylistTypes
{
- (NSArray *)acceptablePlaylistTypes {
return @[@"m3u", @"pls"];
}
- (NSArray *)acceptableContainerTypes
{
- (NSArray *)acceptableContainerTypes {
return [AudioPlayer containerTypes];
}
- (void)willInsertURLs:(NSArray*)urls origin:(URLOrigin)origin
{
- (void)willInsertURLs:(NSArray *)urls origin:(URLOrigin)origin {
[playlistController willInsertURLs:urls origin:origin];
}
- (void)didInsertURLs:(NSArray*)urls origin:(URLOrigin)origin
{
- (void)didInsertURLs:(NSArray *)urls origin:(URLOrigin)origin {
[playlistController didInsertURLs:urls origin:origin];
}

View file

@ -158,7 +158,9 @@
BOOL modifiersUsed = ([event modifierFlags] & (NSEventModifierFlagShift |
NSEventModifierFlagControl |
NSEventModifierFlagOption |
NSEventModifierFlagCommand)) ? YES : NO;
NSEventModifierFlagCommand)) ?
YES :
NO;
if(modifiersUsed) {
[super keyDown:event];
return;
@ -228,8 +230,7 @@
data = [NSKeyedArchiver archivedDataWithRootObject:selectedURLs
requiringSecureCoding:YES
error:&error];
}
else {
} else {
data = [NSArchiver archivedDataWithRootObject:selectedURLs];
}
@ -275,8 +276,7 @@
NSPasteboardType fileType;
if(@available(macOS 10.13, *)) {
fileType = NSPasteboardTypeFileURL;
}
else {
} else {
fileType = NSFilenamesPboardType;
}
NSArray *supportedTypes = @[CogUrlsPboardType, fileType, iTunesDropType];
@ -311,8 +311,7 @@
urls = [NSKeyedUnarchiver unarchivedObjectOfClasses:allowed
fromData:data
error:&error];
}
else {
} else {
urls = [NSUnarchiver unarchiveObjectWithData:data];
}
}
@ -387,8 +386,7 @@
NSPasteboardType fileType;
if(@available(macOS 10.13, *)) {
fileType = NSPasteboardTypeFileURL;
}
else {
} else {
fileType = NSFilenamesPboardType;
}

View file

@ -8,9 +8,7 @@
#import <Cocoa/Cocoa.h>
@interface Shuffle : NSObject {
}
+ (void)initialize;

View file

@ -12,8 +12,7 @@
@implementation Shuffle
+ (void)initialize
{
+ (void)initialize {
static BOOL initialized = NO;
if(!initialized) {
// Call srandom() exactly once.
@ -22,8 +21,7 @@
}
}
+ (NSMutableArray *)shuffleList:(NSArray *)l
{
+ (NSMutableArray*)shuffleList:(NSArray*)l {
NSArray* randomLongs = [NSArray arrayWithRandomLongs:[l count]];
// randomLongs is an array of random integers, equal in length to l.

View file

@ -8,7 +8,6 @@
#import <Cocoa/Cocoa.h>
@interface StatusImageTransformer : NSValueTransformer {
NSImage *playImage;
NSImage *queueImage;

Some files were not shown because too many files have changed in this diff Show more