Permalink
Browse files

Added Spotify login and hard-coded playback

  • Loading branch information...
insidegui committed Nov 15, 2017
1 parent 64f7be2 commit aaab11fb0bbee72f6826cc617d4a685f5a7481e4
Showing with 5,453 additions and 3 deletions.
  1. +22 −2 AnimojiStudio.xcodeproj/project.pbxproj
  2. +12 −0 AnimojiStudio/Bootstrap/AppDelegate.m
  3. +5 −1 AnimojiStudio/Controllers/Recording/RecordingFlowController.h
  4. +18 −0 AnimojiStudio/Controllers/Recording/RecordingFlowController.m
  5. +1 −0 AnimojiStudio/Controllers/Recording/RecordingViewController.h
  6. +20 −0 AnimojiStudio/Controllers/Recording/RecordingViewController.m
  7. +29 −0 AnimojiStudio/Core/SpotifyCoordinator.h
  8. +106 −0 AnimojiStudio/Core/SpotifyCoordinator.m
  9. +17 −0 AnimojiStudio/Resources/Info.plist
  10. +23 −0 SpotifyAudioPlayback.framework/Headers/SPTAudioPlaybackTypes.h
  11. +422 −0 SpotifyAudioPlayback.framework/Headers/SPTAudioStreamingController.h
  12. +71 −0 SpotifyAudioPlayback.framework/Headers/SPTAudioStreamingController_ErrorCodes.h
  13. +85 −0 SpotifyAudioPlayback.framework/Headers/SPTCircularBuffer.h
  14. +150 −0 SpotifyAudioPlayback.framework/Headers/SPTCoreAudioController.h
  15. +33 −0 SpotifyAudioPlayback.framework/Headers/SPTDiskCache.h
  16. +80 −0 SpotifyAudioPlayback.framework/Headers/SPTDiskCaching.h
  17. +62 −0 SpotifyAudioPlayback.framework/Headers/SPTPlaybackMetadata.h
  18. +40 −0 SpotifyAudioPlayback.framework/Headers/SPTPlaybackState.h
  19. +375 −0 SpotifyAudioPlayback.framework/Headers/SpPlaybackEvent.h
  20. +27 −0 SpotifyAudioPlayback.framework/Headers/SpotifyAudioPlayback.h
  21. BIN SpotifyAudioPlayback.framework/Info.plist
  22. BIN SpotifyAudioPlayback.framework/SpotifyAudioPlayback
  23. +263 −0 SpotifyAuthentication.framework/Headers/SPTAuth.h
  24. +99 −0 SpotifyAuthentication.framework/Headers/SPTAuthViewController.h
  25. +20 −0 SpotifyAuthentication.framework/Headers/SPTConnectButton.h
  26. +27 −0 SpotifyAuthentication.framework/Headers/SPTEmbeddedImages.h
  27. +86 −0 SpotifyAuthentication.framework/Headers/SPTSession.h
  28. +70 −0 SpotifyAuthentication.framework/Headers/SPTStoreViewController.h
  29. +29 −0 SpotifyAuthentication.framework/Headers/SpotifyAuthentication.h
  30. BIN SpotifyAuthentication.framework/Info.plist
  31. BIN SpotifyAuthentication.framework/SpotifyAuthentication
  32. +230 −0 SpotifyMetadata.framework/Headers/SPTAlbum.h
  33. +293 −0 SpotifyMetadata.framework/Headers/SPTArtist.h
  34. +155 −0 SpotifyMetadata.framework/Headers/SPTBrowse.h
  35. +55 −0 SpotifyMetadata.framework/Headers/SPTFeaturedPlaylistList.h
  36. +240 −0 SpotifyMetadata.framework/Headers/SPTFollow.h
  37. +57 −0 SpotifyMetadata.framework/Headers/SPTImage.h
  38. +86 −0 SpotifyMetadata.framework/Headers/SPTJSONDecoding.h
  39. +174 −0 SpotifyMetadata.framework/Headers/SPTListPage.h
  40. +23 −0 SpotifyMetadata.framework/Headers/SPTMetadataTypes.h
  41. +90 −0 SpotifyMetadata.framework/Headers/SPTPartialAlbum.h
  42. +56 −0 SpotifyMetadata.framework/Headers/SPTPartialArtist.h
  43. +32 −0 SpotifyMetadata.framework/Headers/SPTPartialObject.h
  44. +91 −0 SpotifyMetadata.framework/Headers/SPTPartialPlaylist.h
  45. +98 −0 SpotifyMetadata.framework/Headers/SPTPartialTrack.h
  46. +156 −0 SpotifyMetadata.framework/Headers/SPTPlaylistList.h
  47. +386 −0 SpotifyMetadata.framework/Headers/SPTPlaylistSnapshot.h
  48. +29 −0 SpotifyMetadata.framework/Headers/SPTPlaylistTrack.h
  49. +176 −0 SpotifyMetadata.framework/Headers/SPTRequest.h
  50. +33 −0 SpotifyMetadata.framework/Headers/SPTSavedTrack.h
  51. +184 −0 SpotifyMetadata.framework/Headers/SPTSearch.h
  52. +232 −0 SpotifyMetadata.framework/Headers/SPTTrack.h
  53. +28 −0 SpotifyMetadata.framework/Headers/SPTTrackProvider.h
  54. +183 −0 SpotifyMetadata.framework/Headers/SPTUser.h
  55. +131 −0 SpotifyMetadata.framework/Headers/SPTYourMusic.h
  56. +43 −0 SpotifyMetadata.framework/Headers/SpotifyMetadata.h
  57. BIN SpotifyMetadata.framework/Info.plist
  58. BIN SpotifyMetadata.framework/SpotifyMetadata
@@ -11,6 +11,10 @@
DD7135AF1FBB86E800AAA5E7 /* ASColorWell.m in Sources */ = {isa = PBXBuildFile; fileRef = DD7135AE1FBB86E800AAA5E7 /* ASColorWell.m */; };
DD7135DD1FBB99E900AAA5E7 /* ColorSheetPresentationController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD7135DA1FBB99E900AAA5E7 /* ColorSheetPresentationController.m */; };
DD7135DE1FBB99E900AAA5E7 /* ColorSheetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD7135DC1FBB99E900AAA5E7 /* ColorSheetViewController.m */; };
DD7135E41FBBDA9100AAA5E7 /* SpotifyAudioPlayback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD7135E21FBBDA8400AAA5E7 /* SpotifyAudioPlayback.framework */; };
DD7135E51FBBDA9400AAA5E7 /* SpotifyAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD7135E11FBBDA8400AAA5E7 /* SpotifyAuthentication.framework */; };
DD7135E61FBBDA9800AAA5E7 /* SpotifyMetadata.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD7135E31FBBDA8500AAA5E7 /* SpotifyMetadata.framework */; };
DD7135E91FBBDACD00AAA5E7 /* SpotifyCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = DD7135E81FBBDACD00AAA5E7 /* SpotifyCoordinator.m */; };
DDCE6C9F1FB87117000EAE11 /* RecordingCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = DDCE6C9E1FB87117000EAE11 /* RecordingCoordinator.m */; };
DDCE6CA61FB8C615000EAE11 /* RecordingStatusViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDCE6CA51FB8C615000EAE11 /* RecordingStatusViewController.m */; };
DDCE6CAA1FB8D9EF000EAE11 /* SharingFlowController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDCE6CA91FB8D9EF000EAE11 /* SharingFlowController.m */; };
@@ -39,6 +43,11 @@
DD7135DA1FBB99E900AAA5E7 /* ColorSheetPresentationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ColorSheetPresentationController.m; sourceTree = "<group>"; };
DD7135DB1FBB99E900AAA5E7 /* ColorSheetViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorSheetViewController.h; sourceTree = "<group>"; };
DD7135DC1FBB99E900AAA5E7 /* ColorSheetViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ColorSheetViewController.m; sourceTree = "<group>"; };
DD7135E11FBBDA8400AAA5E7 /* SpotifyAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SpotifyAuthentication.framework; sourceTree = "<group>"; };
DD7135E21FBBDA8400AAA5E7 /* SpotifyAudioPlayback.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SpotifyAudioPlayback.framework; sourceTree = "<group>"; };
DD7135E31FBBDA8500AAA5E7 /* SpotifyMetadata.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SpotifyMetadata.framework; sourceTree = "<group>"; };
DD7135E71FBBDACD00AAA5E7 /* SpotifyCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpotifyCoordinator.h; sourceTree = "<group>"; };
DD7135E81FBBDACD00AAA5E7 /* SpotifyCoordinator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SpotifyCoordinator.m; sourceTree = "<group>"; };
DDCE6C9D1FB87117000EAE11 /* RecordingCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordingCoordinator.h; sourceTree = "<group>"; };
DDCE6C9E1FB87117000EAE11 /* RecordingCoordinator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordingCoordinator.m; sourceTree = "<group>"; };
DDCE6CA41FB8C615000EAE11 /* RecordingStatusViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordingStatusViewController.h; sourceTree = "<group>"; };
@@ -82,6 +91,9 @@
buildActionMask = 2147483647;
files = (
DDDBBC211FB7A7E400291D45 /* AvatarKit.framework in Frameworks */,
DD7135E41FBBDA9100AAA5E7 /* SpotifyAudioPlayback.framework in Frameworks */,
DD7135E51FBBDA9400AAA5E7 /* SpotifyAuthentication.framework in Frameworks */,
DD7135E61FBBDA9800AAA5E7 /* SpotifyMetadata.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -106,6 +118,8 @@
DDCE6C9E1FB87117000EAE11 /* RecordingCoordinator.m */,
DD1D03BA1FBB0AB2006A47A6 /* ARConfiguration+Overrides.h */,
DD1D03BB1FBB0AB2006A47A6 /* ARConfiguration+Overrides.m */,
DD7135E71FBBDACD00AAA5E7 /* SpotifyCoordinator.h */,
DD7135E81FBBDACD00AAA5E7 /* SpotifyCoordinator.m */,
);
path = Core;
sourceTree = "<group>";
@@ -244,6 +258,9 @@
DDDBBC1F1FB7A7E400291D45 /* Frameworks */ = {
isa = PBXGroup;
children = (
DD7135E21FBBDA8400AAA5E7 /* SpotifyAudioPlayback.framework */,
DD7135E11FBBDA8400AAA5E7 /* SpotifyAuthentication.framework */,
DD7135E31FBBDA8500AAA5E7 /* SpotifyMetadata.framework */,
DDDBBC201FB7A7E400291D45 /* AvatarKit.framework */,
);
name = Frameworks;
@@ -333,6 +350,7 @@
DDCE6CAA1FB8D9EF000EAE11 /* SharingFlowController.m in Sources */,
DDDBBBEB1FB7917F00291D45 /* AppDelegate.m in Sources */,
DDDBBC0B1FB7987A00291D45 /* PuppetSelectionViewController.m in Sources */,
DD7135E91FBBDACD00AAA5E7 /* SpotifyCoordinator.m in Sources */,
DDDBBC111FB79A8F00291D45 /* ASAppearance.m in Sources */,
DD1D03BC1FBB0AB2006A47A6 /* ARConfiguration+Overrides.m in Sources */,
DDDBBC1B1FB7A28D00291D45 /* RecordingViewController.m in Sources */,
@@ -467,10 +485,11 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/AnimojiStudio/AvatarKit",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = "$(SRCROOT)/AnimojiStudio/Resources/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = fun.Animoji;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "52cea236-12c3-4754-b0d0-4c3300a2e2cf";
@@ -490,10 +509,11 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/AnimojiStudio/AvatarKit",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = "$(SRCROOT)/AnimojiStudio/Resources/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = fun.Animoji;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "749f009f-a7ac-4b9a-83fb-15fd3c6b210e";
@@ -13,9 +13,12 @@
#import "ErrorViewController.h"
#import "RecordingFlowController.h"
#import "SpotifyCoordinator.h"
@interface AppDelegate ()
@property (nonatomic, strong) RecordingFlowController *recordingFlow;
@property (nonatomic, strong) SpotifyCoordinator *spotifyCoordinator;
@end
@@ -24,6 +27,8 @@ @implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[ASAppearance install];
self.spotifyCoordinator = [SpotifyCoordinator new];
self.window = [UIWindow new];
[self.window setOpaque:YES];
@@ -37,6 +42,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
self.recordingFlow = [RecordingFlowController new];
self.recordingFlow.spotifyCoordinator = self.spotifyCoordinator;
[self.window setRootViewController:self.recordingFlow];
[self.window makeKeyAndVisible];
@@ -50,4 +57,9 @@ - (void)showErrorMessage:(NSString *)errorMessage
[self.window setRootViewController:controller];
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [self.spotifyCoordinator handleCallbackURL:url];
}
@end
@@ -6,8 +6,12 @@
// Copyright © 2017 Guilherme Rambo. All rights reserved.
//
#import <UIKit/UIKit.h>
@import UIKit;
@class SpotifyCoordinator;
@interface RecordingFlowController : UIViewController
@property (nonatomic, weak) SpotifyCoordinator *spotifyCoordinator;
@end
@@ -19,6 +19,8 @@
#import "SharingFlowController.h"
#import "SpotifyCoordinator.h"
@import ReplayKit;
@interface RecordingFlowController () <RPBroadcastActivityViewControllerDelegate, RPBroadcastControllerDelegate>
@@ -121,6 +123,8 @@ - (void)recordingViewControllerDidTapRecord:(RecordingViewController *)controlle
- (void)startRecording
{
[self.spotifyCoordinator playTrackID:@"spotify:track:58s6EuEYJdlb0kO7awm3Vp"];
self.coordinator = [RecordingCoordinator new];
self.coordinator.delegate = self;
@@ -133,6 +137,8 @@ - (void)startRecording
- (void)stopRecording
{
[self.spotifyCoordinator stop];
[self.coordinator stopRecording];
[self transitionToNormalState];
@@ -300,6 +306,18 @@ - (void)recordingStatusControllerDidSelectStop:(RecordingStatusViewController *)
}
}
#pragma mark Karaoke
- (void)recordingViewControllerDidTapKaraoke:(RecordingViewController *)controller
{
NSError *spotifyError;
[self.spotifyCoordinator startAuthFlowFromViewController:self withError:&spotifyError];
if (spotifyError) {
[self presentErrorControllerWithMessage:spotifyError.localizedDescription];
}
}
#pragma mark Haptics
- (void)_setupHaptics
@@ -14,6 +14,7 @@
- (void)recordingViewControllerDidTapRecord:(RecordingViewController *)controller;
- (void)recordingViewControllerDidTapBroadcast:(RecordingViewController *)controller;
- (void)recordingViewControllerDidTapKaraoke:(RecordingViewController *)controller;
@end
@@ -35,6 +35,8 @@ @interface RecordingViewController ()
@property (nonatomic, strong) UILabel *bgColorLabel;
@property (nonatomic, strong) ASColorWell *bgColorWell;
@property (nonatomic, strong) UIButton *karaokeButton;
@property (nonatomic, strong) ColorSheetViewController *colorSheet;
@end
@@ -166,6 +168,8 @@ - (void)_installSettingsUI
[self _installMicrophoneSettingsUI];
[self _installColorSettingsUI];
[self _installKaraokeUI];
[self _installInstructionLabel];
[self.settingsStack setCustomSpacing:24 afterView:self.bgColorStack];
@@ -230,6 +234,22 @@ - (void)_installInstructionLabel
[self.instructionLabel.widthAnchor constraintLessThanOrEqualToAnchor:self.settingsStack.widthAnchor multiplier:0.9].active = YES;
}
- (void)_installKaraokeUI
{
self.karaokeButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.karaokeButton setTitle:@"Configure Karaoke" forState:UIControlStateNormal];
[self.karaokeButton addTarget:self action:@selector(karaokeTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.settingsStack addArrangedSubview:self.karaokeButton];
}
#pragma mark - Karaoke
- (IBAction)karaokeTapped:(id)sender
{
[self.delegate recordingViewControllerDidTapKaraoke:self];
}
#pragma mark - Color customization
- (void)setSceneBackgroundColor:(UIColor *)color
@@ -0,0 +1,29 @@
//
// SpotifyCoordinator.h
// AnimojiStudio
//
// Created by Guilherme Rambo on 15/11/17.
// Copyright © 2017 Guilherme Rambo. All rights reserved.
//
@import UIKit;
@class SpotifyCoordinator;
@protocol SpotifyCoordinatorDelegate <NSObject>
- (void)spotifyCoordinatorDidFinishLogin:(SpotifyCoordinator *)coordinator;
@end
@interface SpotifyCoordinator : NSObject
@property (nonatomic, weak) id<SpotifyCoordinatorDelegate> delegate;
- (void)startAuthFlowFromViewController:(UIViewController *)presenter withError:(NSError **)outError;
- (BOOL)handleCallbackURL:(NSURL *)url;
- (void)playTrackID:(NSString *)trackID;
- (void)stop;
@end
@@ -0,0 +1,106 @@
//
// SpotifyCoordinator.m
// AnimojiStudio
//
// Created by Guilherme Rambo on 15/11/17.
// Copyright © 2017 Guilherme Rambo. All rights reserved.
//
#import "SpotifyCoordinator.h"
#import <SpotifyAuthentication/SpotifyAuthentication.h>
#import <SpotifyAudioPlayback/SpotifyAudioPlayback.h>
@import SafariServices;
@interface SpotifyCoordinator () <SPTAudioStreamingDelegate>
@property (nonatomic, strong) SPTAuth *auth;
@property (nonatomic, strong) SPTAudioStreamingController *player;
@property (nonatomic, strong) SPTCoreAudioController *coreAudioController;
@property (nonatomic, strong) SFSafariViewController *safariController;
@end
@implementation SpotifyCoordinator
- (instancetype)init
{
self = [super init];
self.player = [SPTAudioStreamingController sharedInstance];
self.player.delegate = self;
self.coreAudioController = [SPTCoreAudioController new];
self.auth = [SPTAuth defaultInstance];
self.auth.clientID = @"7cc18ebcb302432b86abe6d2f3f65578";
self.auth.redirectURL = [NSURL URLWithString:@"animojistudio://spotify"];
self.auth.sessionUserDefaultsKey = @"SpotifySession";
self.auth.requestedScopes = @[SPTAuthStreamingScope];
return self;
}
- (void)startAuthFlowFromViewController:(UIViewController *)presenter withError:(NSError **)outError
{
if (![self.player startWithClientId:self.auth.clientID audioController:self.coreAudioController allowCaching:YES error:outError]) {
return;
}
// not needed, already have a session
if (self.auth.session.isValid) {
[self.player loginWithAccessToken:self.auth.session.accessToken];
return;
}
if ([SPTAuth supportsApplicationAuthentication]) {
[[UIApplication sharedApplication] openURL:[self.auth spotifyAppAuthenticationURL] options:@{} completionHandler:^(BOOL success) {
if (!success) {
NSLog(@"Failed to open auth app");
}
}];
} else {
self.safariController = [[SFSafariViewController alloc] initWithURL:[self.auth spotifyWebAuthenticationURL]];
[presenter presentViewController:self.safariController animated:YES completion:nil];
}
}
- (BOOL)handleCallbackURL:(NSURL *)url
{
if (![self.auth canHandleURL:url]) return NO;
if (self.safariController.presentingViewController) {
[self.safariController dismissViewControllerAnimated:YES completion:nil];
}
[self.auth handleAuthCallbackWithTriggeredAuthURL:url callback:^(NSError *error, SPTSession *session) {
[self.player loginWithAccessToken:session.accessToken];
}];
return YES;
}
- (void)audioStreamingDidLogin:(SPTAudioStreamingController *)audioStreaming
{
[self.delegate spotifyCoordinatorDidFinishLogin:self];
}
- (void)playTrackID:(NSString *)trackID
{
[self.player playSpotifyURI:trackID startingWithIndex:0 startingWithPosition:0 callback:^(NSError *error) {
if (error) {
NSLog(@"Spotify playback error: %@", error);
}
}];
}
- (void)stop
{
[self.player setIsPlaying:NO callback:^(NSError *error) {
NSLog(@"setIsPlaying error: %@", error);
}];
}
@end
@@ -16,8 +16,25 @@
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>fun.Animoji.Spotify.login</string>
<key>CFBundleURLSchemes</key>
<array>
<string>animojistudio</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>spotify-action</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppleMusicUsageDescription</key>
Oops, something went wrong.

0 comments on commit aaab11f

Please sign in to comment.