Permalink
Browse files

* Added unit test target/code.

* Added TSLibraryImport class.
  • Loading branch information...
1 parent 0e08fc2 commit fc1cf037523f4c53a647003ed92e09e43555e680 agillesp@gmail.com committed Jul 10, 2010
View
@@ -0,0 +1,27 @@
+//
+// TSLibraryImport.h
+// iPodLibraryAccess
+//
+// Created by Art Gillespie on 7/9/10.
+// Copyright 2010 tapsquare, llc. All rights reserved.
+//
+
+#import <AVFoundation/AVFoundation.h>
+
+
+@interface TSLibraryImport : NSObject {
+
+}
+
+/**
+ * Pass in the NSURL* you get from an MPMediaItem's
+ * MPMediaItemAssetURL property to get the file's extension.
+ *
+ * Helpful in constructing the destination url for the
+ * imported file.
+ */
++ (NSString*)extensionForAssetURL:(NSURL*)assetURL;
+
+- (void)importAsset:(NSURL*)assetURL toURL:(NSURL*)destURL;
+
+@end
View
@@ -0,0 +1,73 @@
+//
+// TSLibraryImport.m
+// iPodLibraryAccess
+//
+// Created by Art Gillespie on 7/9/10.
+// Copyright 2010 tapsquare, llc. All rights reserved.
+//
+
+#import "TSLibraryImport.h"
+
+@interface TSLibraryImport()
+
++ (BOOL)validIpodLibraryURL:(NSURL*)url;
+
+@end
+
+
+@implementation TSLibraryImport
+
++ (BOOL)validIpodLibraryURL:(NSURL*)url {
+ NSString* IPOD_SCHEME = @"ipod-library";
+ if (nil == url) return NO;
+ if (nil == url.scheme) return NO;
+ if ([url.scheme compare:IPOD_SCHEME] != NSOrderedSame) return NO;
+ if ([url.pathExtension compare:@"mp3"] != NSOrderedSame &&
+ [url.pathExtension compare:@"aif"] != NSOrderedSame &&
+ [url.pathExtension compare:@"m4a"] != NSOrderedSame &&
+ [url.pathExtension compare:@"wav"] != NSOrderedSame) {
+ return NO;
+ }
+ return YES;
+}
+
++ (NSString*)extensionForAssetURL:(NSURL*)assetURL {
+ if (nil == assetURL)
+ @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"nil assetURL" userInfo:nil];
+ if (![self validIpodLibraryURL:assetURL])
+ @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"Invalid iPod Library URL: %@", assetURL] userInfo:nil];
+ return assetURL.pathExtension;
+}
+
+- (void)importAsset:(NSURL*)assetURL toURL:(NSURL*)destURL {
+ if (nil == assetURL || nil == destURL)
+ @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"nil url" userInfo:nil];
+ //TODO: throw on invalid urls
+ //TODO: add completion handler to method
+
+ NSDictionary * options = [[NSDictionary alloc] init];
+ AVURLAsset* asset = [AVURLAsset URLAssetWithURL:assetURL options:options];
+ //TODO: throw on nil?
+
+ AVAssetExportSession* export = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
+
+ //TODO: if tmpURL exists, fail -- caller must handle this themselves
+ //TODO: create a tmp url to write the .mov file to (NOT destURL)
+ export.outputURL = destURL;
+
+ export.outputFileType = AVFileTypeQuickTimeMovie;
+ [export exportAsynchronouslyWithCompletionHandler:^(void) {
+ if (export.status == AVAssetExportSessionStatusFailed) {
+ NSLog(@"export.error: %@", export.error);
+ } else if (export.status == AVAssetExportSessionStatusCancelled) {
+ NSLog(@"export canceled: %@", export.error);
+ } else {
+ NSLog(@"export complete!");
+ //TODO: parse .mov file to dest file
+ }
+
+ [export release];
+ }];
+}
+
+@end
@@ -8,6 +8,7 @@
#import "iPodLibraryAccessViewController.h"
#import <AudioToolbox/AudioToolbox.h>
+#import "TSLibraryImport.h"
@implementation iPodLibraryAccessViewController
@@ -56,6 +57,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
}
- (void)viewDidLoad {
+
[super viewDidLoad];
[progressView setProgress:0.f];
@@ -106,29 +108,6 @@ - (void)progressTimer:(NSTimer*)timer {
}
}
-- (void)dumpAsset:(AVURLAsset*)asset {
- NSLog(@"asset.url: %@", asset.URL);
- for (AVMetadataItem* item in asset.commonMetadata) {
- NSLog(@"metadata: %@", item);
- }
- for (AVAssetTrack* track in asset.tracks) {
- NSLog(@"track.id: %d", track.trackID);
- NSLog(@"track.mediaType: %@", track.mediaType);
- CMFormatDescriptionRef fmt = [track.formatDescriptions objectAtIndex:0];
- AudioStreamBasicDescription* desc = CMAudioFormatDescriptionGetStreamBasicDescription(fmt);
- NSLog(@"track.enabled: %d", track.enabled);
- NSLog(@"track.selfContained: %d", track.selfContained);
- }
-}
-
-- (void)openURL:(NSURL*)assetURL {
- AudioFileID audioFile;
- OSStatus err = AudioFileOpenURL((CFURLRef)assetURL, 0x01, 0, &audioFile);
- if (noErr != err) {
- NSLog(@"couldn't open url: %d", err);
- }
-}
-
- (void)exportAssetAtURL:(NSURL*)assetURL {
NSDictionary * options = [[NSDictionary alloc] init];
AVURLAsset* asset = [AVURLAsset URLAssetWithURL:assetURL options:options];
@@ -159,6 +138,7 @@ - (void)exportAssetAtURL:(NSURL*)assetURL {
for (NSString* type in export.supportedFileTypes) {
NSLog(@"type: %@", type);
}
+
//set the export session's outputURL to <Documents>/test.m4a
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
View
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>NSMainNibFile</key>
+ <string></string>
+</dict>
+</plist>
View
76 Tests.m
@@ -0,0 +1,76 @@
+//
+// Tests.m
+// iPodLibraryAccess
+//
+// Created by Art Gillespie on 7/10/10.
+// Copyright 2010 tapsquare, llc. All rights reserved.
+//
+
+#import "GHUnit.h"
+#import "TSLibraryImport.h"
+
+@interface Tests : GHTestCase
+@end
+
+
+@implementation Tests
+- (BOOL)shouldRunOnMainThread {
+ // By default NO, but if you have a UI test or test dependent on running on the main thread return YES
+ return NO;
+}
+
+- (void)setUpClass {
+ // Run at start of all tests in the class
+}
+
+- (void)tearDownClass {
+ // Run at end of all tests in the class
+}
+
+- (void)setUp {
+ // Run before each test method
+}
+
+- (void)tearDown {
+ // Run after each test method
+}
+
+- (void)testInvalidURL {
+ NSURL* badURL = [NSURL URLWithString:@"lame-scheme://item/lame.txt?id=1234"];
+ GHAssertThrowsSpecificNamed([TSLibraryImport extensionForAssetURL:badURL], NSException, NSInvalidArgumentException, @"extensionForAsset should throw NSInvalidArgumentException for %@", badURL);
+}
+
+- (void)testInvalidExtension {
+ NSURL* badExtension = [NSURL URLWithString:@"ipod-library://item/item.moo?id=879187038471087"];
+ GHAssertThrowsSpecificNamed([TSLibraryImport extensionForAssetURL:badExtension], NSException, NSInvalidArgumentException, @"extension for Asset should throw NSInvalidArgumentException (unrecognized file extension) for %@", badExtension);
+}
+
+- (void)testExtensionParsing {
+ // pulled these from my library using iOS 4. I imagine this url scheme could
+ // change in the future, so will have to test against future versions of
+ // SDK.
+
+ // Note that the MPMediaItemAssetURL property returns nil for .m4p (DRM'ed)
+ // files in the library
+
+ // mp3 - ipod-library://item/item.mp3?id=1425010501608620615
+ // m4a - ipod-library://item/item.m4a?id=-5920761218465604600
+ // aif - ipod-library://item/item.aif?id=-3986756244970330071
+
+ NSURL* mp3URL = [NSURL URLWithString:@"ipod-library://item/item.mp3?id=1425010501608620615"];
+ NSURL* m4aURL = [NSURL URLWithString:@"ipod-library://item/item.m4a?id=-5920761218465604600"];
+ NSURL* aifURL = [NSURL URLWithString:@"ipod-library://item/item.aif?id=-3986756244970330071"];
+
+ GHAssertEqualStrings(@"mp3", [TSLibraryImport extensionForAssetURL:mp3URL], @"mp3 extension incorrect: %@", [TSLibraryImport extensionForAssetURL:mp3URL]);
+ GHAssertEqualStrings(@"m4a", [TSLibraryImport extensionForAssetURL:m4aURL], @"m4a extension incorrect: %@", [TSLibraryImport extensionForAssetURL:m4aURL]);
+ GHAssertEqualStrings(@"aif", [TSLibraryImport extensionForAssetURL:aifURL], @"aif extension incorrect: %@", [TSLibraryImport extensionForAssetURL:aifURL]);
+}
+
+- (void)testExportNilParameters {
+ TSLibraryImport* import = [[TSLibraryImport alloc] init];
+ NSURL* dummyURL = [NSURL URLWithString:@"ipod-library://item/item.mp3?id=1425010501608620615"];
+ GHAssertThrowsSpecificNamed([import importAsset:dummyURL toURL:nil], NSException, NSInvalidArgumentException, @"nil parameter should throw NSInvalidArgumentException");
+ GHAssertThrowsSpecificNamed([import importAsset:nil toURL:dummyURL], NSException, NSInvalidArgumentException, @"nil parameter should throw NSInvalidArgumentException");
+}
+
+@end
Oops, something went wrong.

0 comments on commit fc1cf03

Please sign in to comment.