diff --git a/AppDelegate.h b/AppDelegate.h index 2800056..fa11cbe 100644 --- a/AppDelegate.h +++ b/AppDelegate.h @@ -17,6 +17,8 @@ @property (weak) IBOutlet NSSlider *endSlider; @property (weak) IBOutlet NSLevelIndicator *currentTimeBar; @property (weak) IBOutlet NSTextField *currentTimeLabel; +@property (weak) IBOutlet NSTextField *currentTrackLabel; + @property (assign) BOOL paused; @property (assign) double startTime; diff --git a/AppDelegate.m b/AppDelegate.m index 185eae3..2e7549c 100644 --- a/AppDelegate.m +++ b/AppDelegate.m @@ -8,6 +8,7 @@ #import "AppDelegate.h" #import +#import "metadataRetriever.h" @implementation AppDelegate @@ -17,6 +18,7 @@ @implementation AppDelegate @synthesize currentTimeLabel; @synthesize currentTimeBar; @synthesize playButton; +@synthesize currentTrackLabel; @synthesize startTime; @synthesize endTime; @@ -57,6 +59,14 @@ - (void)loadMusic:(NSURL *) fileURL { NSSound * m = [NSSound alloc]; music = [m initWithContentsOfURL:fileURL byReference:YES]; double maxValue = [music duration]; + + NSString * trackFilePath = [fileURL absoluteString]; + trackFilePath = [trackFilePath stringByReplacingOccurrencesOfString:@"file://localhost" withString:@""]; + NSArray *metadataArray = [metadataRetriever getMetadataForFile:trackFilePath]; + [currentTrackLabel setStringValue:[NSString stringWithFormat:@"%@\n%@",[metadataArray objectAtIndex:1],[metadataArray objectAtIndex:0]]]; + + + paused = YES; startTime = 0.0; endTime = maxValue; diff --git a/Perpetual.xcodeproj/project.pbxproj b/Perpetual.xcodeproj/project.pbxproj index f6b7018..95aa154 100644 --- a/Perpetual.xcodeproj/project.pbxproj +++ b/Perpetual.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 9395B6AD14EB88A8002999D9 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9395B6AC14EB88A8002999D9 /* QuartzCore.framework */; }; 9395B6B014EB8D91002999D9 /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = 9395B6AF14EB8D91002999D9 /* Podfile */; }; 9A041EBD14EAEBA2009AC43F /* cover.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 9A041EBC14EAEBA2009AC43F /* cover.jpg */; }; + 9A31AA3414EBF3FD00382B2F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A31AA3314EBF3FD00382B2F /* AudioToolbox.framework */; }; + 9A31AA3814EBF49F00382B2F /* metadataRetriever.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A31AA3714EBF49F00382B2F /* metadataRetriever.m */; }; 9AC739D314EAEAB6000A57AD /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AC739D214EAEAB6000A57AD /* Cocoa.framework */; }; 9AC739DD14EAEAB6000A57AD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9AC739DB14EAEAB6000A57AD /* InfoPlist.strings */; }; 9AC739DF14EAEAB6000A57AD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AC739DE14EAEAB6000A57AD /* main.m */; }; @@ -24,6 +26,9 @@ 9395B6AC14EB88A8002999D9 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 9395B6AF14EB8D91002999D9 /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; }; 9A041EBC14EAEBA2009AC43F /* cover.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = cover.jpg; sourceTree = ""; }; + 9A31AA3314EBF3FD00382B2F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 9A31AA3614EBF49F00382B2F /* metadataRetriever.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadataRetriever.h; sourceTree = ""; }; + 9A31AA3714EBF49F00382B2F /* metadataRetriever.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = metadataRetriever.m; sourceTree = ""; }; 9AC739CE14EAEAB6000A57AD /* Perpetual.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Perpetual.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9AC739D214EAEAB6000A57AD /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 9AC739D514EAEAB6000A57AD /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; @@ -45,6 +50,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9A31AA3414EBF3FD00382B2F /* AudioToolbox.framework in Frameworks */, 9395B6AD14EB88A8002999D9 /* QuartzCore.framework in Frameworks */, 9AC739D314EAEAB6000A57AD /* Cocoa.framework in Frameworks */, 351CA58DF08E43309D0C1A7C /* libPods.a in Frameworks */, @@ -57,6 +63,7 @@ 9AC739C314EAEAB6000A57AD = { isa = PBXGroup; children = ( + 9A31AA3314EBF3FD00382B2F /* AudioToolbox.framework */, 9395B6AC14EB88A8002999D9 /* QuartzCore.framework */, 9AC739D814EAEAB6000A57AD /* Perpetual */, 9AC739D114EAEAB6000A57AD /* Frameworks */, @@ -96,6 +103,8 @@ 9AC739D814EAEAB6000A57AD /* Perpetual */ = { isa = PBXGroup; children = ( + 9A31AA3614EBF49F00382B2F /* metadataRetriever.h */, + 9A31AA3714EBF49F00382B2F /* metadataRetriever.m */, 9AC739E414EAEAB6000A57AD /* AppDelegate.h */, 9AC739E514EAEAB6000A57AD /* AppDelegate.m */, 9AC739E714EAEAB6000A57AD /* MainMenu.xib */, @@ -204,6 +213,7 @@ files = ( 9AC739DF14EAEAB6000A57AD /* main.m in Sources */, 9AC739E614EAEAB6000A57AD /* AppDelegate.m in Sources */, + 9A31AA3814EBF49F00382B2F /* metadataRetriever.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Perpetual.xcodeproj/xcuserdata/kallepersson.xcuserdatad/xcschemes/Perpetual.xcscheme b/Perpetual.xcodeproj/xcuserdata/kallepersson.xcuserdatad/xcschemes/Perpetual.xcscheme index 768913e..22e59d2 100644 --- a/Perpetual.xcodeproj/xcuserdata/kallepersson.xcuserdatad/xcschemes/Perpetual.xcscheme +++ b/Perpetual.xcodeproj/xcuserdata/kallepersson.xcuserdatad/xcschemes/Perpetual.xcscheme @@ -56,6 +56,11 @@ + + 1070 - 11D50b + 11D50 1938 1138.32 568.00 @@ -312,6 +312,7 @@ {{-3, 127}, {406, 256}} + _NS:2141 YES @@ -335,6 +336,7 @@ 268 {{8, 82}, {40, 40}} + _NS:687 YES @@ -366,6 +368,7 @@ 268 {{59, 86}, {245, 34}} + _NS:360 {250, 750} @@ -406,6 +409,7 @@ 268 {{319, 95}, {75, 17}} + _NS:3944 YES @@ -425,6 +429,7 @@ 268 {{18, 34}, {366, 16}} + _NS:2200 YES @@ -442,6 +447,7 @@ 268 {{9, 49}, {384, 26}} + _NS:3905 YES @@ -466,6 +472,7 @@ 268 {{9, 9}, {384, 25}} + _NS:3905 YES @@ -488,6 +495,7 @@ {400, 380} + {{0, 0}, {2560, 1440}} @@ -668,6 +676,14 @@ 612 + + + currentTrackLabel + + + + 613 + @@ -1053,9 +1069,96 @@ - 612 + 613 + + + + + AppDelegate + NSObject + + id + id + id + id + id + + + + currentTimeBarSet: + id + + + endSliderSet: + id + + + openFile: + id + + + playButtonClick: + id + + + startSliderSet: + id + + + + NSLevelIndicator + NSTextField + NSTextField + NSSlider + NSButton + NSSlider + INAppStoreWindow + + + + currentTimeBar + NSLevelIndicator + + + currentTimeLabel + NSTextField + + + currentTrackLabel + NSTextField + + + endSlider + NSSlider + + + playButton + NSButton + + + startSlider + NSSlider + + + window + INAppStoreWindow + + + + IBProjectSource + ./Classes/AppDelegate.h + + + + INAppStoreWindow + NSWindow + + IBProjectSource + ./Classes/INAppStoreWindow.h + + + - 0 IBCocoaFramework YES diff --git a/metadataRetriever.h b/metadataRetriever.h new file mode 100644 index 0000000..9a47a66 --- /dev/null +++ b/metadataRetriever.h @@ -0,0 +1,22 @@ +// +// metadataRetriever.h +// SwiftLoad +// +// Created by Nathaniel Symer on 12/20/11. +// Copyright (c) 2011 __MyCompanyName__. All rights reserved. +// + +#import +#import + +@interface metadataRetriever : NSObject + ++ (NSArray *)getMetadataForFile:(NSString *)filePath; + ++ (NSString *)artistForMetadataArray:(NSArray *)array; + ++ (NSString *)songForMetadataArray:(NSArray *)array; + ++ (NSString *)albumForMetadataArray:(NSArray *)array; + +@end diff --git a/metadataRetriever.m b/metadataRetriever.m new file mode 100644 index 0000000..afbe7be --- /dev/null +++ b/metadataRetriever.m @@ -0,0 +1,153 @@ +// +// metadataRetriever.m +// SwiftLoad +// +// Created by Nathaniel Symer on 12/20/11. +// Copyright (c) 2011 __MyCompanyName__. All rights reserved. +// + +#import "metadataRetriever.h" +#import + +@implementation metadataRetriever + ++ (NSArray *)getMetadataForFile:(NSString *)filePath { + + NSURL *fileURL = [NSURL fileURLWithPath:filePath]; + + AudioFileID fileID = nil; + OSStatus err = noErr; + + err = AudioFileOpenURL( (__bridge_retained CFURLRef) fileURL, kAudioFileReadPermission, 0, &fileID ); + if (err != noErr) { + NSLog(@"AudioFileOpenURL failed"); + } + + UInt32 id3DataSize = 0; + char * rawID3Tag = NULL; + + err = AudioFileGetPropertyInfo( fileID, kAudioFilePropertyID3Tag, &id3DataSize, NULL ); + if (err != noErr) { + NSLog(@"AudioFileGetPropertyInfo failed for ID3 tag"); + } + + rawID3Tag = (char *) malloc(id3DataSize); + if (rawID3Tag == NULL) { + NSLog(@"could not allocate %u bytes of memory for ID3 tag", id3DataSize); + } + + err = AudioFileGetProperty(fileID, kAudioFilePropertyID3Tag, &id3DataSize, rawID3Tag); + if (err != noErr) { + NSLog(@"AudioFileGetProperty failed for ID3 tag"); + } + + int ilim = 100; + if (ilim > id3DataSize) { + ilim = id3DataSize; + } + for (int i=0; i < ilim; i++) { + if( rawID3Tag[i] < 32 ) { + printf( "." ); + } else { + printf( "%c", rawID3Tag[i] ); + } + } + + UInt32 id3TagSize = 0; + UInt32 id3TagSizeLength = 0; + err = AudioFormatGetProperty( kAudioFormatProperty_ID3TagSize, + id3DataSize, + rawID3Tag, + &id3TagSizeLength, + &id3TagSize + ); + if( err != noErr ) { + NSLog(@"AudioFormatGetProperty failed for ID3 tag size"); + switch( err ) { + case kAudioFormatUnspecifiedError: + NSLog(@"err: audio format unspecified error" ); + break; + case kAudioFormatUnsupportedPropertyError: + NSLog(@"err: audio format unsupported property error" ); + break; + case kAudioFormatBadPropertySizeError: + NSLog(@"err: audio format bad property size error" ); + break; + case kAudioFormatBadSpecifierSizeError: + NSLog(@"err: audio format bad specifier size error" ); + break; + case kAudioFormatUnsupportedDataFormatError: + NSLog(@"err: audio format unsupported data format error"); + break; + case kAudioFormatUnknownFormatError: + NSLog(@"err: audio format unknown format error"); + break; + default: + NSLog(@"err: some other audio format error"); + break; + } + } + + CFDictionaryRef piDict = nil; + UInt32 piDataSize = sizeof(piDict); + + err = AudioFileGetProperty( fileID, kAudioFilePropertyInfoDictionary, &piDataSize, &piDict ); + if(err != noErr) { + NSLog(@"AudioFileGetProperty failed for property info dictionary"); + } + + + NSString *artistCF = (__bridge_transfer NSString *)CFDictionaryGetValue(piDict, CFSTR(kAFInfoDictionary_Artist)); + NSString *songCF = (__bridge_transfer NSString *)CFDictionaryGetValue(piDict, CFSTR(kAFInfoDictionary_Title)); + NSString *albumCF = (__bridge_transfer NSString *)CFDictionaryGetValue(piDict, CFSTR(kAFInfoDictionary_Album)); + + NSString *artist = [NSString stringWithFormat:@"%@",artistCF]; + NSString *song = [NSString stringWithFormat:@"%@",songCF]; + NSString *album = [NSString stringWithFormat:@"%@",albumCF]; + + NSString *artistNil = [NSString stringWithString:@"---"]; + NSString *songNil = [NSString stringWithString:@"---"]; + NSString *albumNil = [NSString stringWithString:@"---"]; + + BOOL artistIsNil = [artist isEqualToString:@"(null)"]; + BOOL albumIsNil = [album isEqualToString:@"(null)"]; + BOOL songIsNil = [song isEqualToString:@"(null)"]; + + NSMutableArray *initArray = [NSMutableArray arrayWithCapacity:10]; + if (artistIsNil) { + [initArray addObject:artistNil]; + } else { + [initArray addObject:artist]; + } + if (songIsNil) { + [initArray addObject:songNil]; + } else { + [initArray addObject:song]; + } + + if (albumIsNil) { + [initArray addObject:albumNil]; + } else { + [initArray addObject:album]; + } + + free(rawID3Tag); + + NSArray *theArray = [NSArray arrayWithArray:initArray]; + + return theArray; +} + ++ (NSString *)artistForMetadataArray:(NSArray *)array { + return [array objectAtIndex:0]; +} + ++ (NSString *)songForMetadataArray:(NSArray *)array { + return [array objectAtIndex:1]; +} + ++ (NSString *)albumForMetadataArray:(NSArray *)array { + return [array objectAtIndex:2]; +} + +@end