bug fixes...will detail later, need to fix multipeer party streaming

This commit is contained in:
Okechi 2016-04-09 11:14:45 -04:00
parent 514b2d2b09
commit 8a16abdd02
79 changed files with 3922 additions and 369 deletions

View File

@ -0,0 +1,17 @@
//
// NSMutableArray+QueueMethods.h
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/12/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@interface NSMutableArray (QueueMethods)
- (void)pushObject:(id)object;
- (id)popObject;
- (id)topObject;
@end

View File

@ -0,0 +1,38 @@
//
// NSMutableArray+QueueMethods.m
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/12/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "NSMutableArray+QueueMethods.h"
@implementation NSMutableArray (QueueMethods)
- (void)pushObject:(id)object
{
[self addObject:object];
}
- (id)popObject
{
if (self.count > 0) {
id object = self[0];
[self removeObjectAtIndex:0];
return object;
}
return nil;
}
- (id)topObject
{
if (self.count > 0) {
return self[0];
}
return nil;
}
@end

View File

@ -0,0 +1,38 @@
//
// TDAudioFileStream.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@class TDAudioFileStream;
@protocol TDAudioFileStreamDelegate <NSObject>
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveError:(OSStatus)error;
@required
- (void)audioFileStreamDidBecomeReady:(TDAudioFileStream *)audioFileStream;
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription;
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveData:(const void *)data length:(UInt32)length;
@end
@interface TDAudioFileStream : NSObject
@property (assign, nonatomic) AudioStreamBasicDescription basicDescription;
@property (assign, nonatomic) UInt64 totalByteCount;
@property (assign, nonatomic) UInt32 packetBufferSize;
@property (assign, nonatomic) void *magicCookieData;
@property (assign, nonatomic) UInt32 magicCookieLength;
@property (assign, nonatomic) BOOL discontinuous;
@property (assign, nonatomic) id<TDAudioFileStreamDelegate> delegate;
- (instancetype)init;
- (void)parseData:(const void *)data length:(UInt32)length;
@end

View File

@ -0,0 +1,112 @@
//
// TDAudioFileStream.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioFileStream.h"
@interface TDAudioFileStream ()
@property (assign, nonatomic) AudioFileStreamID audioFileStreamID;
- (void)didChangeProperty:(AudioFileStreamPropertyID)propertyID flags:(UInt32 *)flags;
- (void)didReceivePackets:(const void *)packets packetDescriptions:(AudioStreamPacketDescription *)packetDescriptions numberOfPackets:(UInt32)numberOfPackets numberOfBytes:(UInt32)numberOfBytes;
@end
void TDAudioFileStreamPropertyListener(void *inClientData, AudioFileStreamID inAudioFileStreamID, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags)
{
TDAudioFileStream *audioFileStream = (__bridge TDAudioFileStream *)inClientData;
[audioFileStream didChangeProperty:inPropertyID flags:ioFlags];
}
void TDAudioFileStreamPacketsListener(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions)
{
TDAudioFileStream *audioFileStream = (__bridge TDAudioFileStream *)inClientData;
[audioFileStream didReceivePackets:inInputData packetDescriptions:inPacketDescriptions numberOfPackets:inNumberPackets numberOfBytes:inNumberBytes];
}
@implementation TDAudioFileStream
- (instancetype)init
{
self = [super init];
if (!self) return nil;
OSStatus err = AudioFileStreamOpen((__bridge void *)self, TDAudioFileStreamPropertyListener, TDAudioFileStreamPacketsListener, 0, &_audioFileStreamID);
if (err) return nil;
self.discontinuous = YES;
return self;
}
- (void)didChangeProperty:(AudioFileStreamPropertyID)propertyID flags:(UInt32 *)flags
{
if (propertyID == kAudioFileStreamProperty_ReadyToProducePackets) {
UInt32 basicDescriptionSize = sizeof(self.basicDescription);
OSStatus err = AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_DataFormat, &basicDescriptionSize, &_basicDescription);
if (err) return [self.delegate audioFileStream:self didReceiveError:err];
UInt32 byteCountSize;
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &_totalByteCount);
UInt32 sizeOfUInt32 = sizeof(UInt32);
err = AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &_packetBufferSize);
if (err || !self.packetBufferSize) {
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &_packetBufferSize);
}
Boolean writeable;
err = AudioFileStreamGetPropertyInfo(self.audioFileStreamID, kAudioFileStreamProperty_MagicCookieData, &_magicCookieLength, &writeable);
if (!err) {
self.magicCookieData = calloc(1, self.magicCookieLength);
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_MagicCookieData, &_magicCookieLength, self.magicCookieData);
}
[self.delegate audioFileStreamDidBecomeReady:self];
}
}
- (void)didReceivePackets:(const void *)packets packetDescriptions:(AudioStreamPacketDescription *)packetDescriptions numberOfPackets:(UInt32)numberOfPackets numberOfBytes:(UInt32)numberOfBytes
{
if (packetDescriptions) {
for (NSUInteger i = 0; i < numberOfPackets; i++) {
SInt64 packetOffset = packetDescriptions[i].mStartOffset;
UInt32 packetSize = packetDescriptions[i].mDataByteSize;
[self.delegate audioFileStream:self didReceiveData:(const void *)(packets + packetOffset) length:packetSize packetDescription:(AudioStreamPacketDescription)packetDescriptions[i]];
}
} else {
[self.delegate audioFileStream:self didReceiveData:(const void *)packets length:numberOfBytes];
}
}
- (void)parseData:(const void *)data length:(UInt32)length
{
OSStatus err;
if (self.discontinuous) {
err = AudioFileStreamParseBytes(self.audioFileStreamID, length, data, kAudioFileStreamParseFlag_Discontinuity);
self.discontinuous = NO;
} else {
err = AudioFileStreamParseBytes(self.audioFileStreamID, length, data, 0);
}
if (err) [self.delegate audioFileStream:self didReceiveError:err];
}
- (void)dealloc
{
AudioFileStreamClose(self.audioFileStreamID);
free(_magicCookieData);
}
@end

View File

@ -0,0 +1,45 @@
//
// TDAudioQueue.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
typedef NS_ENUM(NSUInteger, TDAudioQueueState) {
TDAudioQueueStateBuffering,
TDAudioQueueStateStopped,
TDAudioQueueStatePaused,
TDAudioQueueStatePlaying
};
@class TDAudioQueue;
@protocol TDAudioQueueDelegate <NSObject>
- (void)audioQueueDidFinishPlaying:(TDAudioQueue *)audioQueue;
- (void)audioQueueDidStartPlaying:(TDAudioQueue *)audioQueue;
@end
@class TDAudioQueueBuffer;
@interface TDAudioQueue : NSObject
@property (assign, nonatomic) TDAudioQueueState state;
@property (assign, nonatomic) id<TDAudioQueueDelegate> delegate;
- (instancetype)initWithBasicDescription:(AudioStreamBasicDescription)basicDescription bufferCount:(UInt32)bufferCount bufferSize:(UInt32)bufferSize magicCookieData:(void *)magicCookieData magicCookieSize:(UInt32)magicCookieSize;
- (TDAudioQueueBuffer *)nextFreeBuffer;
- (void)enqueue;
- (void)play;
- (void)pause;
- (void)stop;
- (void)finish;
@end

View File

@ -0,0 +1,141 @@
//
// TDAudioQueue.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueue.h"
#import "TDAudioQueueBuffer.h"
#import "TDAudioQueueController.h"
#import "TDAudioQueueBufferManager.h"
#import "TDAudioStreamerConstants.h"
@interface TDAudioQueue ()
@property (assign, nonatomic) AudioQueueRef audioQueue;
@property (strong, nonatomic) TDAudioQueueBufferManager *bufferManager;
@property (strong, nonatomic) NSCondition *waitForFreeBufferCondition;
@property (assign, nonatomic) NSUInteger buffersToFillBeforeStart;
- (void)didFreeAudioQueueBuffer:(AudioQueueBufferRef)audioQueueBuffer;
@end
void TDAudioQueueOutputCallback(void *inUserData, AudioQueueRef inAudioQueue, AudioQueueBufferRef inAudioQueueBuffer)
{
TDAudioQueue *audioQueue = (__bridge TDAudioQueue *)inUserData;
[audioQueue didFreeAudioQueueBuffer:inAudioQueueBuffer];
}
@implementation TDAudioQueue
- (instancetype)initWithBasicDescription:(AudioStreamBasicDescription)basicDescription bufferCount:(UInt32)bufferCount bufferSize:(UInt32)bufferSize magicCookieData:(void *)magicCookieData magicCookieSize:(UInt32)magicCookieSize
{
self = [self init];
if (!self) return nil;
OSStatus err = AudioQueueNewOutput(&basicDescription, TDAudioQueueOutputCallback, (__bridge void *)self, NULL, NULL, 0, &_audioQueue);
if (err) return nil;
self.bufferManager = [[TDAudioQueueBufferManager alloc] initWithAudioQueue:self.audioQueue size:bufferSize count:bufferCount];
AudioQueueSetProperty(self.audioQueue, kAudioQueueProperty_MagicCookie, magicCookieData, magicCookieSize);
free(magicCookieData);
AudioQueueSetParameter(self.audioQueue, kAudioQueueParam_Volume, 1.0);
self.waitForFreeBufferCondition = [[NSCondition alloc] init];
self.state = TDAudioQueueStateBuffering;
self.buffersToFillBeforeStart = kTDAudioQueueStartMinimumBuffers;
return self;
}
#pragma mark - Audio Queue Events
- (void)didFreeAudioQueueBuffer:(AudioQueueBufferRef)audioQueueBuffer
{
[self.bufferManager freeAudioQueueBuffer:audioQueueBuffer];
[self.waitForFreeBufferCondition lock];
[self.waitForFreeBufferCondition signal];
[self.waitForFreeBufferCondition unlock];
if (self.state == TDAudioQueueStateStopped && ![self.bufferManager isProcessingAudioQueueBuffer]) {
[self.delegate audioQueueDidFinishPlaying:self];
}
}
#pragma mark - Public Methods
- (TDAudioQueueBuffer *)nextFreeBuffer
{
if (![self.bufferManager hasAvailableAudioQueueBuffer]) {
[self.waitForFreeBufferCondition lock];
[self.waitForFreeBufferCondition wait];
[self.waitForFreeBufferCondition unlock];
}
TDAudioQueueBuffer *nextBuffer = [self.bufferManager nextFreeBuffer];
if (!nextBuffer) return [self nextFreeBuffer];
return nextBuffer;
}
- (void)enqueue
{
[self.bufferManager enqueueNextBufferOnAudioQueue:self.audioQueue];
if (self.state == TDAudioQueueStateBuffering && --self.buffersToFillBeforeStart == 0) {
AudioQueuePrime(self.audioQueue, 0, NULL);
[self play];
[self.delegate audioQueueDidStartPlaying:self];
}
}
#pragma mark - Audio Queue Controls
- (void)play
{
if (self.state == TDAudioQueueStatePlaying) return;
[TDAudioQueueController playAudioQueue:self.audioQueue];
self.state = TDAudioQueueStatePlaying;
}
- (void)pause
{
if (self.state == TDAudioQueueStatePaused) return;
[TDAudioQueueController pauseAudioQueue:self.audioQueue];
self.state = TDAudioQueueStatePaused;
}
- (void)stop
{
if (self.state == TDAudioQueueStateStopped) return;
[TDAudioQueueController stopAudioQueue:self.audioQueue];
self.state = TDAudioQueueStateStopped;
}
- (void)finish
{
if (self.state == TDAudioQueueStateStopped) return;
[TDAudioQueueController finishAudioQueue:self.audioQueue];
self.state = TDAudioQueueStateStopped;
}
#pragma mark - Cleanup
- (void)dealloc
{
[self.bufferManager freeBufferMemoryFromAudioQueue:self.audioQueue];
AudioQueueDispose(self.audioQueue, YES);
}
@end

View File

@ -0,0 +1,26 @@
//
// TDAudioQueueBuffer.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/11/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@interface TDAudioQueueBuffer : NSObject
- (instancetype)initWithAudioQueue:(AudioQueueRef)audioQueue size:(UInt32)size;
- (NSInteger)fillWithData:(const void *)data length:(UInt32)length offset:(UInt32)offset;
- (BOOL)fillWithData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription;
- (void)enqueueWithAudioQueue:(AudioQueueRef)auidoQueue;
- (void)reset;
- (BOOL)isEqual:(AudioQueueBufferRef)audioQueueBuffer;
- (void)freeFromAudioQueue:(AudioQueueRef)audioQueue;
@end

View File

@ -0,0 +1,106 @@
//
// TDAudioQueueBuffer.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/11/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueueBuffer.h"
const NSUInteger kTDMaxPacketDescriptions = 512;
@interface TDAudioQueueBuffer ()
@property (assign, nonatomic) AudioQueueBufferRef audioQueueBuffer;
@property (assign, nonatomic) UInt32 size;
@property (assign, nonatomic) UInt32 fillPosition;
@property (assign, nonatomic) AudioStreamPacketDescription *packetDescriptions;
@property (assign, nonatomic) UInt32 numberOfPacketDescriptions;
@end
@implementation TDAudioQueueBuffer
- (instancetype)initWithAudioQueue:(AudioQueueRef)audioQueue size:(UInt32)size
{
self = [super init];
if (!self) return nil;
self.size = size;
self.fillPosition = 0;
self.packetDescriptions = malloc(sizeof(AudioStreamPacketDescription) * kTDMaxPacketDescriptions);
self.numberOfPacketDescriptions = 0;
OSStatus err = AudioQueueAllocateBuffer(audioQueue, self.size, &_audioQueueBuffer);
if (err) return nil;
return self;
}
- (NSInteger)fillWithData:(const void *)data length:(UInt32)length offset:(UInt32)offset
{
if (self.fillPosition + length <= self.size)
{
memcpy((char *)(self.audioQueueBuffer->mAudioData + self.fillPosition), (const char *)(data + offset), length);
self.fillPosition += length;
}
else
{
NSUInteger availableSpace = self.size - self.fillPosition;
memcpy((char *)(self.audioQueueBuffer->mAudioData + self.fillPosition), (const char *)data, availableSpace);
self.fillPosition = self.size;
return length - availableSpace;
}
if (self.fillPosition == self.size) {
return -1;
}
return 0;
}
- (BOOL)fillWithData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription
{
if (self.fillPosition + packetDescription.mDataByteSize > self.size || self.numberOfPacketDescriptions == kTDMaxPacketDescriptions) return NO;
memcpy((char *)(self.audioQueueBuffer->mAudioData + self.fillPosition), (const char *)(data + packetDescription.mStartOffset), packetDescription.mDataByteSize);
self.packetDescriptions[self.numberOfPacketDescriptions] = packetDescription;
self.packetDescriptions[self.numberOfPacketDescriptions].mStartOffset = self.fillPosition;
self.numberOfPacketDescriptions++;
self.fillPosition += packetDescription.mDataByteSize;
return YES;
}
- (void)enqueueWithAudioQueue:(AudioQueueRef)audioQueue
{
self.audioQueueBuffer->mAudioDataByteSize = self.fillPosition;
AudioQueueEnqueueBuffer(audioQueue, self.audioQueueBuffer, self.numberOfPacketDescriptions, self.packetDescriptions);
}
- (void)reset
{
self.fillPosition = 0;
self.numberOfPacketDescriptions = 0;
}
- (BOOL)isEqual:(AudioQueueBufferRef)audioQueueBuffer
{
return audioQueueBuffer == self.audioQueueBuffer;
}
- (void)freeFromAudioQueue:(AudioQueueRef)audioQueue
{
AudioQueueFreeBuffer(audioQueue, self.audioQueueBuffer);
}
- (void)dealloc
{
free(_packetDescriptions);
}
@end

View File

@ -0,0 +1,27 @@
//
// TDAudioQueueBufferManager.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/29/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@class TDAudioQueueBuffer;
@interface TDAudioQueueBufferManager : NSObject
- (instancetype)initWithAudioQueue:(AudioQueueRef)audioQueue size:(UInt32)size count:(UInt32)count;
- (void)freeAudioQueueBuffer:(AudioQueueBufferRef)audioQueueBuffer;
- (TDAudioQueueBuffer *)nextFreeBuffer;
- (void)enqueueNextBufferOnAudioQueue:(AudioQueueRef)audioQueue;
- (BOOL)hasAvailableAudioQueueBuffer;
- (BOOL)isProcessingAudioQueueBuffer;
- (void)freeBufferMemoryFromAudioQueue:(AudioQueueRef)audioQueue;
@end

View File

@ -0,0 +1,114 @@
//
// TDAudioQueueBufferManager.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/29/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueueBufferManager.h"
#import "TDAudioQueueBuffer.h"
#import "NSMutableArray+QueueMethods.h"
@interface TDAudioQueueBufferManager ()
@property (assign, nonatomic) UInt32 bufferCount;
@property (assign, nonatomic) UInt32 bufferSize;
@property (strong, nonatomic) NSArray *audioQueueBuffers;
@property (strong, atomic) NSMutableArray *freeBuffers;
@end
@implementation TDAudioQueueBufferManager
- (instancetype)initWithAudioQueue:(AudioQueueRef)audioQueue size:(UInt32)size count:(UInt32)count
{
self = [super init];
if (!self) return nil;
self.bufferCount = count;
self.bufferSize = size;
self.freeBuffers = [NSMutableArray arrayWithCapacity:self.bufferCount];
NSMutableArray *audioqueuebuffers = [NSMutableArray arrayWithCapacity:self.bufferCount];
for (NSUInteger i = 0; i < self.bufferCount; i++) {
TDAudioQueueBuffer *buffer = [[TDAudioQueueBuffer alloc] initWithAudioQueue:audioQueue size:self.bufferSize];
if (!buffer) {
i--;
continue;
}
audioqueuebuffers[i] = buffer;
[self.freeBuffers pushObject:@(i)];
}
self.audioQueueBuffers = [audioqueuebuffers copy];
return self;
}
#pragma mark - Public Methods
- (void)freeAudioQueueBuffer:(AudioQueueBufferRef)audioQueueBuffer
{
for (NSUInteger i = 0; i < self.bufferCount; i++) {
if ([(TDAudioQueueBuffer *)self.audioQueueBuffers[i] isEqual:audioQueueBuffer]) {
[(TDAudioQueueBuffer *)self.audioQueueBuffers[i] reset];
@synchronized(self) {
[self.freeBuffers pushObject:@(i)];
}
break;
}
}
#if DEBUG
if (self.freeBuffers.count > self.bufferCount >> 1) {
NSLog(@"Free Buffers: %lu", (unsigned long)self.freeBuffers.count);
}
#endif
}
- (TDAudioQueueBuffer *)nextFreeBuffer
{
if (![self hasAvailableAudioQueueBuffer]) return nil;
@synchronized(self) {
return self.audioQueueBuffers[[[self.freeBuffers topObject] integerValue]];
}
}
- (void)enqueueNextBufferOnAudioQueue:(AudioQueueRef)audioQueue
{
@synchronized(self) {
NSInteger nextBufferIndex = [[self.freeBuffers popObject] integerValue];
TDAudioQueueBuffer *nextBuffer = self.audioQueueBuffers[nextBufferIndex];
[nextBuffer enqueueWithAudioQueue:audioQueue];
}
}
- (BOOL)hasAvailableAudioQueueBuffer
{
@synchronized(self) {
return self.freeBuffers.count > 0;
}
}
- (BOOL)isProcessingAudioQueueBuffer
{
@synchronized(self) {
return self.freeBuffers.count != self.bufferCount;
}
}
#pragma mark - Cleanup
- (void)freeBufferMemoryFromAudioQueue:(AudioQueueRef)audioQueue
{
for (NSUInteger i = 0; i < self.audioQueueBuffers.count; i++) {
[(TDAudioQueueBuffer *)self.audioQueueBuffers[i] freeFromAudioQueue:audioQueue];
}
}
@end

View File

@ -0,0 +1,19 @@
//
// TDAudioQueueController.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/29/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@interface TDAudioQueueController : NSObject
+ (OSStatus)playAudioQueue:(AudioQueueRef)audioQueue;
+ (OSStatus)pauseAudioQueue:(AudioQueueRef)audioQueue;
+ (OSStatus)stopAudioQueue:(AudioQueueRef)audioQueue;
+ (OSStatus)finishAudioQueue:(AudioQueueRef)audioQueue;
@end

View File

@ -0,0 +1,38 @@
//
// TDAudioQueueController.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/29/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueueController.h"
@implementation TDAudioQueueController
+ (OSStatus)playAudioQueue:(AudioQueueRef)audioQueue
{
return AudioQueueStart(audioQueue, NULL);
}
+ (OSStatus)pauseAudioQueue:(AudioQueueRef)audioQueue
{
return AudioQueuePause(audioQueue);
}
+ (OSStatus)stopAudioQueue:(AudioQueueRef)audioQueue
{
return [self stopAudioQueue:audioQueue immediately:YES];
}
+ (OSStatus)finishAudioQueue:(AudioQueueRef)audioQueue
{
return [self stopAudioQueue:audioQueue immediately:NO];
}
+ (OSStatus)stopAudioQueue:(AudioQueueRef)audioQueue immediately:(BOOL)immediately
{
return AudioQueueStop(audioQueue, immediately);
}
@end

View File

@ -0,0 +1,19 @@
//
// TDAudioQueueFiller.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/31/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@class TDAudioQueue;
@interface TDAudioQueueFiller : NSObject
+ (void)fillAudioQueue:(TDAudioQueue *)audioQueue withData:(const void *)data length:(UInt32)length offset:(UInt32)offset;
+ (void)fillAudioQueue:(TDAudioQueue *)audioQueue withData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription;
@end

View File

@ -0,0 +1,41 @@
//
// TDAudioQueueFiller.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/31/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueueFiller.h"
#import "TDAudioQueueBuffer.h"
#import "TDAudioQueue.h"
@implementation TDAudioQueueFiller
+ (void)fillAudioQueue:(TDAudioQueue *)audioQueue withData:(const void *)data length:(UInt32)length offset:(UInt32)offset
{
TDAudioQueueBuffer *audioQueueBuffer = [audioQueue nextFreeBuffer];
NSInteger leftovers = [audioQueueBuffer fillWithData:data length:length offset:offset];
if (leftovers == 0) return;
[audioQueue enqueue];
if (leftovers > 0)
[self fillAudioQueue:audioQueue withData:data length:length offset:(length - (UInt32)leftovers)];
}
+ (void)fillAudioQueue:(TDAudioQueue *)audioQueue withData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription
{
TDAudioQueueBuffer *audioQueueBuffer = [audioQueue nextFreeBuffer];
BOOL hasMoreRoomForPackets = [audioQueueBuffer fillWithData:data length:length packetDescription:packetDescription];
if (!hasMoreRoomForPackets) {
[audioQueue enqueue];
[self fillAudioQueue:audioQueue withData:data length:length packetDescription:packetDescription];
}
}
@end

View File

@ -0,0 +1,39 @@
//
// TDAudioStream.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, TDAudioStreamEvent) {
TDAudioStreamEventHasData,
TDAudioStreamEventWantsData,
TDAudioStreamEventEnd,
TDAudioStreamEventError
};
@class TDAudioStream;
@protocol TDAudioStreamDelegate <NSObject>
@required
- (void)audioStream:(TDAudioStream *)audioStream didRaiseEvent:(TDAudioStreamEvent)event;
@end
@interface TDAudioStream : NSObject
@property (assign, nonatomic) id<TDAudioStreamDelegate> delegate;
- (instancetype)initWithInputStream:(NSInputStream *)inputStream;
- (instancetype)initWithOutputStream:(NSOutputStream *)outputStream;
- (void)open;
- (void)close;
- (UInt32)readData:(uint8_t *)data maxLength:(UInt32)maxLength;
- (UInt32)writeData:(uint8_t *)data maxLength:(UInt32)maxLength;
@end

View File

@ -0,0 +1,93 @@
//
// TDAudioStream.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioStream.h"
@interface TDAudioStream () <NSStreamDelegate>
@property (strong, nonatomic) NSStream *stream;
@end
@implementation TDAudioStream
- (instancetype)initWithInputStream:(NSInputStream *)inputStream
{
self = [super init];
if (!self) return nil;
self.stream = inputStream;
return self;
}
- (instancetype)initWithOutputStream:(NSOutputStream *)outputStream
{
self = [super init];
if (!self) return nil;
self.stream = outputStream;
return self;
}
- (void)open
{
self.stream.delegate = self;
[self.stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
return [self.stream open];
}
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventHasBytesAvailable:
[self.delegate audioStream:self didRaiseEvent:TDAudioStreamEventHasData];
break;
case NSStreamEventHasSpaceAvailable:
[self.delegate audioStream:self didRaiseEvent:TDAudioStreamEventWantsData];
break;
case NSStreamEventEndEncountered:
[self.delegate audioStream:self didRaiseEvent:TDAudioStreamEventEnd];
break;
case NSStreamEventErrorOccurred:
[self.delegate audioStream:self didRaiseEvent:TDAudioStreamEventError];
break;
default:
break;
}
}
- (UInt32)readData:(uint8_t *)data maxLength:(UInt32)maxLength
{
return (UInt32)[(NSInputStream *)self.stream read:data maxLength:maxLength];
}
- (UInt32)writeData:(uint8_t *)data maxLength:(UInt32)maxLength
{
return (UInt32)[(NSOutputStream *)self.stream write:data maxLength:maxLength];
}
- (void)close
{
[self.stream close];
self.stream.delegate = nil;
[self.stream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)dealloc
{
if (self.stream)
[self close];
}
@end

View File

@ -0,0 +1,24 @@
//
// TDAudioInputStreamer.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@interface TDAudioInputStreamer : NSObject
@property (assign, nonatomic) UInt32 audioStreamReadMaxLength;
@property (assign, nonatomic) UInt32 audioQueueBufferSize;
@property (assign, nonatomic) UInt32 audioQueueBufferCount;
- (instancetype)initWithInputStream:(NSInputStream *)inputStream;
- (void)start;
- (void)resume;
- (void)pause;
- (void)stop;
@end

View File

@ -0,0 +1,195 @@
//
// TDAudioInputStreamer.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioInputStreamer.h"
#import "TDAudioFileStream.h"
#import "TDAudioStream.h"
#import "TDAudioQueue.h"
#import "TDAudioQueueBuffer.h"
#import "TDAudioQueueFiller.h"
#import "TDAudioStreamerConstants.h"
@interface TDAudioInputStreamer () <TDAudioStreamDelegate, TDAudioFileStreamDelegate, TDAudioQueueDelegate>
@property (strong, nonatomic) NSThread *audioStreamerThread;
@property (assign, atomic) BOOL isPlaying;
@property (strong, nonatomic) TDAudioStream *audioStream;
@property (strong, nonatomic) TDAudioFileStream *audioFileStream;
@property (strong, nonatomic) TDAudioQueue *audioQueue;
@end
@implementation TDAudioInputStreamer
- (instancetype)init
{
self = [super init];
if (!self) return nil;
self.audioFileStream = [[TDAudioFileStream alloc] init];
if (!self.audioFileStream) return nil;
self.audioFileStream.delegate = self;
return self;
}
- (instancetype)initWithInputStream:(NSInputStream *)inputStream
{
self = [self init];
if (!self) return nil;
self.audioStream = [[TDAudioStream alloc] initWithInputStream:inputStream];
if (!self.audioStream) return nil;
self.audioStream.delegate = self;
return self;
}
- (void)start
{
if (![[NSThread currentThread] isEqual:[NSThread mainThread]]) {
return [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:YES];
}
self.audioStreamerThread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[self.audioStreamerThread start];
}
- (void)run
{
@autoreleasepool {
[self.audioStream open];
self.isPlaying = YES;
while (self.isPlaying && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) ;
}
}
#pragma mark - Properties
- (UInt32)audioStreamReadMaxLength
{
if (!_audioStreamReadMaxLength)
_audioStreamReadMaxLength = kTDAudioStreamReadMaxLength;
return _audioStreamReadMaxLength;
}
- (UInt32)audioQueueBufferSize
{
if (!_audioQueueBufferSize)
_audioQueueBufferSize = kTDAudioQueueBufferSize;
return _audioQueueBufferSize;
}
- (UInt32)audioQueueBufferCount
{
if (!_audioQueueBufferCount)
_audioQueueBufferCount = kTDAudioQueueBufferCount;
return _audioQueueBufferCount;
}
#pragma mark - TDAudioStreamDelegate
- (void)audioStream:(TDAudioStream *)audioStream didRaiseEvent:(TDAudioStreamEvent)event
{
switch (event) {
case TDAudioStreamEventHasData: {
uint8_t bytes[self.audioStreamReadMaxLength];
UInt32 length = [audioStream readData:bytes maxLength:self.audioStreamReadMaxLength];
[self.audioFileStream parseData:bytes length:length];
break;
}
case TDAudioStreamEventEnd:
self.isPlaying = NO;
[self.audioQueue finish];
break;
case TDAudioStreamEventError:
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioStreamDidFinishPlayingNotification object:nil];
break;
default:
break;
}
}
#pragma mark - TDAudioFileStreamDelegate
- (void)audioFileStreamDidBecomeReady:(TDAudioFileStream *)audioFileStream
{
UInt32 bufferSize = audioFileStream.packetBufferSize ? audioFileStream.packetBufferSize : self.audioQueueBufferSize;
self.audioQueue = [[TDAudioQueue alloc] initWithBasicDescription:audioFileStream.basicDescription bufferCount:self.audioQueueBufferCount bufferSize:bufferSize magicCookieData:audioFileStream.magicCookieData magicCookieSize:audioFileStream.magicCookieLength];
self.audioQueue.delegate = self;
}
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveError:(OSStatus)error
{
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioStreamDidFinishPlayingNotification object:nil];
}
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveData:(const void *)data length:(UInt32)length
{
[TDAudioQueueFiller fillAudioQueue:self.audioQueue withData:data length:length offset:0];
}
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription
{
[TDAudioQueueFiller fillAudioQueue:self.audioQueue withData:data length:length packetDescription:packetDescription];
}
#pragma mark - TDAudioQueueDelegate
- (void)audioQueueDidFinishPlaying:(TDAudioQueue *)audioQueue
{
[self performSelectorOnMainThread:@selector(notifyMainThread:) withObject:TDAudioStreamDidFinishPlayingNotification waitUntilDone:NO];
}
- (void)audioQueueDidStartPlaying:(TDAudioQueue *)audioQueue
{
[self performSelectorOnMainThread:@selector(notifyMainThread:) withObject:TDAudioStreamDidStartPlayingNotification waitUntilDone:NO];
}
- (void)notifyMainThread:(NSString *)notificationName
{
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:nil];
}
#pragma mark - Public Methods
- (void)resume
{
[self.audioQueue play];
}
- (void)pause
{
[self.audioQueue pause];
}
- (void)stop
{
[self performSelector:@selector(stopThread) onThread:self.audioStreamerThread withObject:nil waitUntilDone:YES];
}
- (void)stopThread
{
self.isPlaying = NO;
[self.audioQueue stop];
}
@end

View File

@ -0,0 +1,21 @@
//
// TDAudioOutputStreamer.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/14/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@class AVURLAsset;
@interface TDAudioOutputStreamer : NSObject
- (instancetype)initWithOutputStream:(NSOutputStream *)stream;
- (void)streamAudioFromURL:(NSURL *)url;
- (void)start;
- (void)stop;
@end

View File

@ -0,0 +1,144 @@
//
// TDAudioOutputStreamer.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/14/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <AVFoundation/AVFoundation.h>
#import "TDAudioOutputStreamer.h"
#import "TDAudioStream.h"
@interface TDAudioOutputStreamer () <TDAudioStreamDelegate>
@property (strong, nonatomic) TDAudioStream *audioStream;
@property (strong, nonatomic) AVAssetReader *assetReader;
@property (strong, nonatomic) AVAssetReaderTrackOutput *assetOutput;
@property (strong, nonatomic) NSThread *streamThread;
@property (assign, atomic) BOOL isStreaming;
@end
@implementation TDAudioOutputStreamer
- (instancetype) initWithOutputStream:(NSOutputStream *)stream
{
self = [super init];
if (!self) return nil;
self.audioStream = [[TDAudioStream alloc] initWithOutputStream:stream];
self.audioStream.delegate = self;
NSLog(@"Init");
return self;
}
- (void)start
{
if (![[NSThread currentThread] isEqual:[NSThread mainThread]]) {
return [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:YES];
}
NSLog(@"Start");
self.streamThread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[self.streamThread start];
}
- (void)run
{
@autoreleasepool {
[self.audioStream open];
self.isStreaming = YES;
NSLog(@"Loop");
while (self.isStreaming && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) ;
NSLog(@"Done");
}
}
- (void)streamAudioFromURL:(NSURL *)url
{
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
NSError *assetError;
self.assetReader = [AVAssetReader assetReaderWithAsset:asset error:&assetError];
self.assetOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:asset.tracks[0] outputSettings:nil];
if (![self.assetReader canAddOutput:self.assetOutput]) return;
[self.assetReader addOutput:self.assetOutput];
[self.assetReader startReading];
NSLog(@"Read Asset");
}
- (void)sendDataChunk
{
CMSampleBufferRef sampleBuffer;
sampleBuffer = [self.assetOutput copyNextSampleBuffer];
if (sampleBuffer == NULL || CMSampleBufferGetNumSamples(sampleBuffer) == 0) {
CFRelease(sampleBuffer);
return;
}
CMBlockBufferRef blockBuffer;
AudioBufferList audioBufferList;
OSStatus err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, NULL, &audioBufferList, sizeof(AudioBufferList), NULL, NULL, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer);
if (err) {
CFRelease(sampleBuffer);
return;
}
for (NSUInteger i = 0; i < audioBufferList.mNumberBuffers; i++) {
AudioBuffer audioBuffer = audioBufferList.mBuffers[i];
[self.audioStream writeData:audioBuffer.mData maxLength:audioBuffer.mDataByteSize];
NSLog(@"buffer size: %u", (unsigned int)audioBuffer.mDataByteSize);
}
CFRelease(blockBuffer);
CFRelease(sampleBuffer);
}
- (void)stop
{
[self performSelector:@selector(stopThread) onThread:self.streamThread withObject:nil waitUntilDone:YES];
}
- (void)stopThread
{
self.isStreaming = NO;
[self.audioStream close];
NSLog(@"Stop");
}
#pragma mark - TDAudioStreamDelegate
- (void)audioStream:(TDAudioStream *)audioStream didRaiseEvent:(TDAudioStreamEvent)event
{
switch (event) {
case TDAudioStreamEventWantsData:
[self sendDataChunk];
break;
case TDAudioStreamEventError:
// TODO: shit!
NSLog(@"Stream Error");
break;
case TDAudioStreamEventEnd:
// TODO: shit!
NSLog(@"Stream Ended");
break;
default:
break;
}
}
@end

17
AudioStreamer/TDAudioStreamer.h Executable file
View File

@ -0,0 +1,17 @@
//
// TDAudioStreamer.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/18/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import "TDAudioStreamerConstants.h"
#import "TDAudioInputStreamer.h"
#import "TDAudioOutputStreamer.h"
@interface TDAudioStreamer : NSObject
@end

13
AudioStreamer/TDAudioStreamer.m Executable file
View File

@ -0,0 +1,13 @@
//
// TDAudioStreamer.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/18/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioStreamer.h"
@implementation TDAudioStreamer
@end

View File

@ -0,0 +1,25 @@
//
// TDAudioStreamerConstants.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/5/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
extern NSString *const TDAudioStreamerDidChangeAudioNotification;
extern NSString *const TDAudioStreamerDidPauseNotification;
extern NSString *const TDAudioStreamerDidPlayNotification;
extern NSString *const TDAudioStreamerDidStopNotification;
extern NSString *const TDAudioStreamerNextTrackRequestNotification;
extern NSString *const TDAudioStreamerPreviousTrackRequestNotification;
extern NSString *const TDAudioStreamDidFinishPlayingNotification;
extern NSString *const TDAudioStreamDidStartPlayingNotification;
extern UInt32 const kTDAudioStreamReadMaxLength;
extern UInt32 const kTDAudioQueueBufferSize;
extern UInt32 const kTDAudioQueueBufferCount;
extern UInt32 const kTDAudioQueueStartMinimumBuffers;

View File

@ -0,0 +1,25 @@
//
// TDAudioStreamerConstants.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/5/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioStreamerConstants.h"
NSString *const TDAudioStreamerDidChangeAudioNotification = @"TDAudioStreamerDidChangeAudioNotification";
NSString *const TDAudioStreamerDidPauseNotification = @"TDAudioStreamerDidPauseNotification";
NSString *const TDAudioStreamerDidPlayNotification = @"TDAudioStreamerDidPlayNotification";
NSString *const TDAudioStreamerDidStopNotification = @"TDAudioStreamerDidStopNotification";
NSString *const TDAudioStreamerNextTrackRequestNotification = @"TDAudioStreamerNextTrackRequestNotification";
NSString *const TDAudioStreamerPreviousTrackRequestNotification = @"TDAudioStreamerPreviousTrackRequestNotification";
NSString *const TDAudioStreamDidFinishPlayingNotification = @"TDAudioStreamDidFinishPlayingNotification";
NSString *const TDAudioStreamDidStartPlayingNotification = @"TDAudioStreamDidStartPlayingNotification";
UInt32 const kTDAudioStreamReadMaxLength = 512;
UInt32 const kTDAudioQueueBufferSize = 2048;
UInt32 const kTDAudioQueueBufferCount = 16;
UInt32 const kTDAudioQueueStartMinimumBuffers = 8;

View File

@ -100,20 +100,18 @@
3E5BD3161C6C45CE00266B16 /* Party@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3E5BD3131C6C45CE00266B16 /* Party@2x.png */; }; 3E5BD3161C6C45CE00266B16 /* Party@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3E5BD3131C6C45CE00266B16 /* Party@2x.png */; };
3E5BD3171C6C45CE00266B16 /* StarPlayer@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3E5BD3141C6C45CE00266B16 /* StarPlayer@2x.png */; }; 3E5BD3171C6C45CE00266B16 /* StarPlayer@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3E5BD3141C6C45CE00266B16 /* StarPlayer@2x.png */; };
3E627FC31C55978E005C0372 /* PartySessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FC21C55978E005C0372 /* PartySessionManager.swift */; }; 3E627FC31C55978E005C0372 /* PartySessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FC21C55978E005C0372 /* PartySessionManager.swift */; };
3E627FE61C55AE35005C0372 /* NSInputStream+URLInitialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FC81C55AE35005C0372 /* NSInputStream+URLInitialization.m */; }; 3E631B3F1CB4D3150050808F /* NSMutableArray+QueueMethods.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B271CB4D3150050808F /* NSMutableArray+QueueMethods.m */; };
3E627FE71C55AE35005C0372 /* NSMutableArray+QueueMethods.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FCA1C55AE35005C0372 /* NSMutableArray+QueueMethods.m */; }; 3E631B401CB4D3150050808F /* TDAudioFileStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B2A1CB4D3150050808F /* TDAudioFileStream.m */; };
3E627FE81C55AE35005C0372 /* TDAudioMetaInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FCD1C55AE35005C0372 /* TDAudioMetaInfo.m */; }; 3E631B411CB4D3150050808F /* TDAudioQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B2C1CB4D3150050808F /* TDAudioQueue.m */; };
3E627FE91C55AE35005C0372 /* TDAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FCF1C55AE35005C0372 /* TDAudioPlayer.m */; }; 3E631B421CB4D3150050808F /* TDAudioQueueBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B2E1CB4D3150050808F /* TDAudioQueueBuffer.m */; };
3E627FEA1C55AE35005C0372 /* TDAudioFileStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FD31C55AE35005C0372 /* TDAudioFileStream.m */; }; 3E631B431CB4D3150050808F /* TDAudioQueueBufferManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B301CB4D3150050808F /* TDAudioQueueBufferManager.m */; };
3E627FEB1C55AE35005C0372 /* TDAudioQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FD51C55AE35005C0372 /* TDAudioQueue.m */; }; 3E631B441CB4D3150050808F /* TDAudioQueueController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B321CB4D3150050808F /* TDAudioQueueController.m */; };
3E627FEC1C55AE35005C0372 /* TDAudioQueueBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FD71C55AE35005C0372 /* TDAudioQueueBuffer.m */; }; 3E631B451CB4D3150050808F /* TDAudioQueueFiller.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B341CB4D3150050808F /* TDAudioQueueFiller.m */; };
3E627FED1C55AE35005C0372 /* TDAudioQueueBufferManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FD91C55AE35005C0372 /* TDAudioQueueBufferManager.m */; }; 3E631B461CB4D3150050808F /* TDAudioStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B361CB4D3150050808F /* TDAudioStream.m */; };
3E627FEE1C55AE35005C0372 /* TDAudioQueueController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FDB1C55AE35005C0372 /* TDAudioQueueController.m */; }; 3E631B471CB4D3150050808F /* TDAudioInputStreamer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B381CB4D3150050808F /* TDAudioInputStreamer.m */; };
3E627FEF1C55AE35005C0372 /* TDAudioQueueFiller.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FDD1C55AE35005C0372 /* TDAudioQueueFiller.m */; }; 3E631B481CB4D3150050808F /* TDAudioOutputStreamer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B3A1CB4D3150050808F /* TDAudioOutputStreamer.m */; };
3E627FF01C55AE35005C0372 /* TDAudioStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FDF1C55AE35005C0372 /* TDAudioStream.m */; }; 3E631B491CB4D3150050808F /* TDAudioStreamer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B3C1CB4D3150050808F /* TDAudioStreamer.m */; };
3E627FF11C55AE35005C0372 /* TDAudioInputStreamer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FE11C55AE35005C0372 /* TDAudioInputStreamer.m */; }; 3E631B4A1CB4D3150050808F /* TDAudioStreamerConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E631B3E1CB4D3150050808F /* TDAudioStreamerConstants.m */; };
3E627FF21C55AE35005C0372 /* TDAudioOutputStreamer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FE31C55AE35005C0372 /* TDAudioOutputStreamer.m */; };
3E627FF31C55AE35005C0372 /* TDAudioPlayerConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E627FE51C55AE35005C0372 /* TDAudioPlayerConstants.m */; };
3E6738F51C6E9C7700B47C3E /* LoginController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E6738F41C6E9C7700B47C3E /* LoginController.swift */; }; 3E6738F51C6E9C7700B47C3E /* LoginController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E6738F41C6E9C7700B47C3E /* LoginController.swift */; };
3E6D43861C782E3200CA805F /* Decline@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3E6D43851C782E3200CA805F /* Decline@2x.png */; }; 3E6D43861C782E3200CA805F /* Decline@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3E6D43851C782E3200CA805F /* Decline@2x.png */; };
3E6D43891C7831B100CA805F /* InvitedToPartyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E6D43881C7831B100CA805F /* InvitedToPartyViewController.swift */; }; 3E6D43891C7831B100CA805F /* InvitedToPartyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E6D43881C7831B100CA805F /* InvitedToPartyViewController.swift */; };
@ -248,34 +246,30 @@
3E5BD3131C6C45CE00266B16 /* Party@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Party@2x.png"; path = "../../../Dropbox/Gethip/Screens/Song Playing/5 Play Screen/Assets/Party@2x.png"; sourceTree = "<group>"; }; 3E5BD3131C6C45CE00266B16 /* Party@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Party@2x.png"; path = "../../../Dropbox/Gethip/Screens/Song Playing/5 Play Screen/Assets/Party@2x.png"; sourceTree = "<group>"; };
3E5BD3141C6C45CE00266B16 /* StarPlayer@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "StarPlayer@2x.png"; path = "../../../Dropbox/Gethip/Screens/Song Playing/5 Play Screen/Assets/StarPlayer@2x.png"; sourceTree = "<group>"; }; 3E5BD3141C6C45CE00266B16 /* StarPlayer@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "StarPlayer@2x.png"; path = "../../../Dropbox/Gethip/Screens/Song Playing/5 Play Screen/Assets/StarPlayer@2x.png"; sourceTree = "<group>"; };
3E627FC21C55978E005C0372 /* PartySessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartySessionManager.swift; sourceTree = "<group>"; }; 3E627FC21C55978E005C0372 /* PartySessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartySessionManager.swift; sourceTree = "<group>"; };
3E627FC71C55AE35005C0372 /* NSInputStream+URLInitialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSInputStream+URLInitialization.h"; sourceTree = "<group>"; }; 3E631B261CB4D3150050808F /* NSMutableArray+QueueMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+QueueMethods.h"; sourceTree = "<group>"; };
3E627FC81C55AE35005C0372 /* NSInputStream+URLInitialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSInputStream+URLInitialization.m"; sourceTree = "<group>"; }; 3E631B271CB4D3150050808F /* NSMutableArray+QueueMethods.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+QueueMethods.m"; sourceTree = "<group>"; };
3E627FC91C55AE35005C0372 /* NSMutableArray+QueueMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+QueueMethods.h"; sourceTree = "<group>"; }; 3E631B291CB4D3150050808F /* TDAudioFileStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioFileStream.h; sourceTree = "<group>"; };
3E627FCA1C55AE35005C0372 /* NSMutableArray+QueueMethods.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+QueueMethods.m"; sourceTree = "<group>"; }; 3E631B2A1CB4D3150050808F /* TDAudioFileStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioFileStream.m; sourceTree = "<group>"; };
3E627FCC1C55AE35005C0372 /* TDAudioMetaInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioMetaInfo.h; sourceTree = "<group>"; }; 3E631B2B1CB4D3150050808F /* TDAudioQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueue.h; sourceTree = "<group>"; };
3E627FCD1C55AE35005C0372 /* TDAudioMetaInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioMetaInfo.m; sourceTree = "<group>"; }; 3E631B2C1CB4D3150050808F /* TDAudioQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueue.m; sourceTree = "<group>"; };
3E627FCE1C55AE35005C0372 /* TDAudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioPlayer.h; sourceTree = "<group>"; }; 3E631B2D1CB4D3150050808F /* TDAudioQueueBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueueBuffer.h; sourceTree = "<group>"; };
3E627FCF1C55AE35005C0372 /* TDAudioPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioPlayer.m; sourceTree = "<group>"; }; 3E631B2E1CB4D3150050808F /* TDAudioQueueBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueueBuffer.m; sourceTree = "<group>"; };
3E627FD21C55AE35005C0372 /* TDAudioFileStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioFileStream.h; sourceTree = "<group>"; }; 3E631B2F1CB4D3150050808F /* TDAudioQueueBufferManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueueBufferManager.h; sourceTree = "<group>"; };
3E627FD31C55AE35005C0372 /* TDAudioFileStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioFileStream.m; sourceTree = "<group>"; }; 3E631B301CB4D3150050808F /* TDAudioQueueBufferManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueueBufferManager.m; sourceTree = "<group>"; };
3E627FD41C55AE35005C0372 /* TDAudioQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueue.h; sourceTree = "<group>"; }; 3E631B311CB4D3150050808F /* TDAudioQueueController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueueController.h; sourceTree = "<group>"; };
3E627FD51C55AE35005C0372 /* TDAudioQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueue.m; sourceTree = "<group>"; }; 3E631B321CB4D3150050808F /* TDAudioQueueController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueueController.m; sourceTree = "<group>"; };
3E627FD61C55AE35005C0372 /* TDAudioQueueBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueueBuffer.h; sourceTree = "<group>"; }; 3E631B331CB4D3150050808F /* TDAudioQueueFiller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueueFiller.h; sourceTree = "<group>"; };
3E627FD71C55AE35005C0372 /* TDAudioQueueBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueueBuffer.m; sourceTree = "<group>"; }; 3E631B341CB4D3150050808F /* TDAudioQueueFiller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueueFiller.m; sourceTree = "<group>"; };
3E627FD81C55AE35005C0372 /* TDAudioQueueBufferManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueueBufferManager.h; sourceTree = "<group>"; }; 3E631B351CB4D3150050808F /* TDAudioStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioStream.h; sourceTree = "<group>"; };
3E627FD91C55AE35005C0372 /* TDAudioQueueBufferManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueueBufferManager.m; sourceTree = "<group>"; }; 3E631B361CB4D3150050808F /* TDAudioStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioStream.m; sourceTree = "<group>"; };
3E627FDA1C55AE35005C0372 /* TDAudioQueueController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueueController.h; sourceTree = "<group>"; }; 3E631B371CB4D3150050808F /* TDAudioInputStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioInputStreamer.h; sourceTree = "<group>"; };
3E627FDB1C55AE35005C0372 /* TDAudioQueueController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueueController.m; sourceTree = "<group>"; }; 3E631B381CB4D3150050808F /* TDAudioInputStreamer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioInputStreamer.m; sourceTree = "<group>"; };
3E627FDC1C55AE35005C0372 /* TDAudioQueueFiller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioQueueFiller.h; sourceTree = "<group>"; }; 3E631B391CB4D3150050808F /* TDAudioOutputStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioOutputStreamer.h; sourceTree = "<group>"; };
3E627FDD1C55AE35005C0372 /* TDAudioQueueFiller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioQueueFiller.m; sourceTree = "<group>"; }; 3E631B3A1CB4D3150050808F /* TDAudioOutputStreamer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioOutputStreamer.m; sourceTree = "<group>"; };
3E627FDE1C55AE35005C0372 /* TDAudioStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioStream.h; sourceTree = "<group>"; }; 3E631B3B1CB4D3150050808F /* TDAudioStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioStreamer.h; sourceTree = "<group>"; };
3E627FDF1C55AE35005C0372 /* TDAudioStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioStream.m; sourceTree = "<group>"; }; 3E631B3C1CB4D3150050808F /* TDAudioStreamer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioStreamer.m; sourceTree = "<group>"; };
3E627FE01C55AE35005C0372 /* TDAudioInputStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioInputStreamer.h; sourceTree = "<group>"; }; 3E631B3D1CB4D3150050808F /* TDAudioStreamerConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioStreamerConstants.h; sourceTree = "<group>"; };
3E627FE11C55AE35005C0372 /* TDAudioInputStreamer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioInputStreamer.m; sourceTree = "<group>"; }; 3E631B3E1CB4D3150050808F /* TDAudioStreamerConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioStreamerConstants.m; sourceTree = "<group>"; };
3E627FE21C55AE35005C0372 /* TDAudioOutputStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TDAudioOutputStreamer.h; sourceTree = "<group>"; };
3E627FE31C55AE35005C0372 /* TDAudioOutputStreamer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDAudioOutputStreamer.m; sourceTree = "<group>"; };
3E627FE41C55AE35005C0372 /* TDAudioPlayerConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TDAudioPlayerConstants.h; path = "../../../../Downloads/TDAudioPlayer-master/TDAudioPlayer/AudioPlayerLibrary/TDAudioPlayerConstants.h"; sourceTree = "<group>"; };
3E627FE51C55AE35005C0372 /* TDAudioPlayerConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TDAudioPlayerConstants.m; path = "../../../../Downloads/TDAudioPlayer-master/TDAudioPlayer/AudioPlayerLibrary/TDAudioPlayerConstants.m"; sourceTree = "<group>"; };
3E6738F41C6E9C7700B47C3E /* LoginController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginController.swift; sourceTree = "<group>"; }; 3E6738F41C6E9C7700B47C3E /* LoginController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginController.swift; sourceTree = "<group>"; };
3E6D43851C782E3200CA805F /* Decline@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Decline@2x.png"; path = "../../../Dropbox/gethip/Screens/Invited To Join Party/5 When Invited/When Invited/Assets/Decline@2x.png"; sourceTree = "<group>"; }; 3E6D43851C782E3200CA805F /* Decline@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Decline@2x.png"; path = "../../../Dropbox/gethip/Screens/Invited To Join Party/5 When Invited/When Invited/Assets/Decline@2x.png"; sourceTree = "<group>"; };
3E6D43881C7831B100CA805F /* InvitedToPartyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InvitedToPartyViewController.swift; sourceTree = "<group>"; }; 3E6D43881C7831B100CA805F /* InvitedToPartyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InvitedToPartyViewController.swift; sourceTree = "<group>"; };
@ -631,76 +625,54 @@
3E627FC41C55ADDE005C0372 /* TDAudioPlayer.framework */ = { 3E627FC41C55ADDE005C0372 /* TDAudioPlayer.framework */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3E627FC51C55AE35005C0372 /* AudioPlayer */, 3E631B241CB4D3150050808F /* AudioStreamer */,
3E627FD01C55AE35005C0372 /* AudioStreamer */,
3E627FE41C55AE35005C0372 /* TDAudioPlayerConstants.h */,
3E627FE51C55AE35005C0372 /* TDAudioPlayerConstants.m */,
); );
name = TDAudioPlayer.framework; name = TDAudioPlayer.framework;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
3E627FC51C55AE35005C0372 /* AudioPlayer */ = { 3E631B241CB4D3150050808F /* AudioStreamer */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3E627FC61C55AE35005C0372 /* Categories */, 3E631B251CB4D3150050808F /* Categories */,
3E627FCB1C55AE35005C0372 /* Classes */, 3E631B281CB4D3150050808F /* Classes */,
3E627FCE1C55AE35005C0372 /* TDAudioPlayer.h */, 3E631B371CB4D3150050808F /* TDAudioInputStreamer.h */,
3E627FCF1C55AE35005C0372 /* TDAudioPlayer.m */, 3E631B381CB4D3150050808F /* TDAudioInputStreamer.m */,
3E631B391CB4D3150050808F /* TDAudioOutputStreamer.h */,
3E631B3A1CB4D3150050808F /* TDAudioOutputStreamer.m */,
3E631B3B1CB4D3150050808F /* TDAudioStreamer.h */,
3E631B3C1CB4D3150050808F /* TDAudioStreamer.m */,
3E631B3D1CB4D3150050808F /* TDAudioStreamerConstants.h */,
3E631B3E1CB4D3150050808F /* TDAudioStreamerConstants.m */,
); );
name = AudioPlayer; path = AudioStreamer;
path = "../../../../Downloads/TDAudioPlayer-master/TDAudioPlayer/AudioPlayerLibrary/AudioPlayer"; sourceTree = SOURCE_ROOT;
sourceTree = "<group>";
}; };
3E627FC61C55AE35005C0372 /* Categories */ = { 3E631B251CB4D3150050808F /* Categories */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3E627FC71C55AE35005C0372 /* NSInputStream+URLInitialization.h */, 3E631B261CB4D3150050808F /* NSMutableArray+QueueMethods.h */,
3E627FC81C55AE35005C0372 /* NSInputStream+URLInitialization.m */, 3E631B271CB4D3150050808F /* NSMutableArray+QueueMethods.m */,
3E627FC91C55AE35005C0372 /* NSMutableArray+QueueMethods.h */,
3E627FCA1C55AE35005C0372 /* NSMutableArray+QueueMethods.m */,
); );
path = Categories; path = Categories;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
3E627FCB1C55AE35005C0372 /* Classes */ = { 3E631B281CB4D3150050808F /* Classes */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3E627FCC1C55AE35005C0372 /* TDAudioMetaInfo.h */, 3E631B291CB4D3150050808F /* TDAudioFileStream.h */,
3E627FCD1C55AE35005C0372 /* TDAudioMetaInfo.m */, 3E631B2A1CB4D3150050808F /* TDAudioFileStream.m */,
); 3E631B2B1CB4D3150050808F /* TDAudioQueue.h */,
path = Classes; 3E631B2C1CB4D3150050808F /* TDAudioQueue.m */,
sourceTree = "<group>"; 3E631B2D1CB4D3150050808F /* TDAudioQueueBuffer.h */,
}; 3E631B2E1CB4D3150050808F /* TDAudioQueueBuffer.m */,
3E627FD01C55AE35005C0372 /* AudioStreamer */ = { 3E631B2F1CB4D3150050808F /* TDAudioQueueBufferManager.h */,
isa = PBXGroup; 3E631B301CB4D3150050808F /* TDAudioQueueBufferManager.m */,
children = ( 3E631B311CB4D3150050808F /* TDAudioQueueController.h */,
3E627FD11C55AE35005C0372 /* Classes */, 3E631B321CB4D3150050808F /* TDAudioQueueController.m */,
3E627FE01C55AE35005C0372 /* TDAudioInputStreamer.h */, 3E631B331CB4D3150050808F /* TDAudioQueueFiller.h */,
3E627FE11C55AE35005C0372 /* TDAudioInputStreamer.m */, 3E631B341CB4D3150050808F /* TDAudioQueueFiller.m */,
3E627FE21C55AE35005C0372 /* TDAudioOutputStreamer.h */, 3E631B351CB4D3150050808F /* TDAudioStream.h */,
3E627FE31C55AE35005C0372 /* TDAudioOutputStreamer.m */, 3E631B361CB4D3150050808F /* TDAudioStream.m */,
);
name = AudioStreamer;
path = "../../../../Downloads/TDAudioPlayer-master/TDAudioPlayer/AudioPlayerLibrary/AudioStreamer";
sourceTree = "<group>";
};
3E627FD11C55AE35005C0372 /* Classes */ = {
isa = PBXGroup;
children = (
3E627FD21C55AE35005C0372 /* TDAudioFileStream.h */,
3E627FD31C55AE35005C0372 /* TDAudioFileStream.m */,
3E627FD41C55AE35005C0372 /* TDAudioQueue.h */,
3E627FD51C55AE35005C0372 /* TDAudioQueue.m */,
3E627FD61C55AE35005C0372 /* TDAudioQueueBuffer.h */,
3E627FD71C55AE35005C0372 /* TDAudioQueueBuffer.m */,
3E627FD81C55AE35005C0372 /* TDAudioQueueBufferManager.h */,
3E627FD91C55AE35005C0372 /* TDAudioQueueBufferManager.m */,
3E627FDA1C55AE35005C0372 /* TDAudioQueueController.h */,
3E627FDB1C55AE35005C0372 /* TDAudioQueueController.m */,
3E627FDC1C55AE35005C0372 /* TDAudioQueueFiller.h */,
3E627FDD1C55AE35005C0372 /* TDAudioQueueFiller.m */,
3E627FDE1C55AE35005C0372 /* TDAudioStream.h */,
3E627FDF1C55AE35005C0372 /* TDAudioStream.m */,
); );
path = Classes; path = Classes;
sourceTree = "<group>"; sourceTree = "<group>";
@ -897,56 +869,54 @@
files = ( files = (
3E101F081C52E65300C895CA /* PartyServiceManager.swift in Sources */, 3E101F081C52E65300C895CA /* PartyServiceManager.swift in Sources */,
3E330B1A1C38502F00276FE4 /* LoginViewController.swift in Sources */, 3E330B1A1C38502F00276FE4 /* LoginViewController.swift in Sources */,
3E627FEA1C55AE35005C0372 /* TDAudioFileStream.m in Sources */,
3E1EE6391C6D02EB00F5C5D7 /* InPartyViewController.swift in Sources */, 3E1EE6391C6D02EB00F5C5D7 /* InPartyViewController.swift in Sources */,
3E627FC31C55978E005C0372 /* PartySessionManager.swift in Sources */, 3E627FC31C55978E005C0372 /* PartySessionManager.swift in Sources */,
3E627FE61C55AE35005C0372 /* NSInputStream+URLInitialization.m in Sources */,
3E5485B51C69CE2F00E7D5AB /* InvitedCollectionViewCell.swift in Sources */, 3E5485B51C69CE2F00E7D5AB /* InvitedCollectionViewCell.swift in Sources */,
3E6D43891C7831B100CA805F /* InvitedToPartyViewController.swift in Sources */, 3E6D43891C7831B100CA805F /* InvitedToPartyViewController.swift in Sources */,
3E37709E1CAB5EC000A66097 /* ForgotPassViewController.swift in Sources */, 3E37709E1CAB5EC000A66097 /* ForgotPassViewController.swift in Sources */,
3E3412571C54C31F006226E0 /* SongSelectionViewController.swift in Sources */, 3E3412571C54C31F006226E0 /* SongSelectionViewController.swift in Sources */,
3E627FE81C55AE35005C0372 /* TDAudioMetaInfo.m in Sources */,
3E6738F51C6E9C7700B47C3E /* LoginController.swift in Sources */, 3E6738F51C6E9C7700B47C3E /* LoginController.swift in Sources */,
3E34125B1C54C73A006226E0 /* PartySession.swift in Sources */, 3E34125B1C54C73A006226E0 /* PartySession.swift in Sources */,
3E631B451CB4D3150050808F /* TDAudioQueueFiller.m in Sources */,
3E631B421CB4D3150050808F /* TDAudioQueueBuffer.m in Sources */,
3EBE825A1CB06793004A2730 /* HomeTabController.swift in Sources */, 3EBE825A1CB06793004A2730 /* HomeTabController.swift in Sources */,
3E50E0401C74B97300EB9EA9 /* BackToHomeScreenViewController.swift in Sources */, 3E50E0401C74B97300EB9EA9 /* BackToHomeScreenViewController.swift in Sources */,
3E627FF01C55AE35005C0372 /* TDAudioStream.m in Sources */,
3E627FE91C55AE35005C0372 /* TDAudioPlayer.m in Sources */,
3EDA82E31C4741C70081ED53 /* FriendDataSource.swift in Sources */, 3EDA82E31C4741C70081ED53 /* FriendDataSource.swift in Sources */,
3EDA82E11C473E900081ED53 /* FriendData.swift in Sources */, 3EDA82E11C473E900081ED53 /* FriendData.swift in Sources */,
3E627FF21C55AE35005C0372 /* TDAudioOutputStreamer.m in Sources */,
3EB6B39B1C87B8AE006B674D /* JoiningPartyViewController.swift in Sources */, 3EB6B39B1C87B8AE006B674D /* JoiningPartyViewController.swift in Sources */,
3E379F051C3F982900F7BCCD /* FriendsCell.swift in Sources */, 3E379F051C3F982900F7BCCD /* FriendsCell.swift in Sources */,
3E1BDA571C37111D00EE3B84 /* ViewController.swift in Sources */, 3E1BDA571C37111D00EE3B84 /* ViewController.swift in Sources */,
3E1AAD141C3BD92600809367 /* FriendsListViewController.swift in Sources */, 3E1AAD141C3BD92600809367 /* FriendsListViewController.swift in Sources */,
3E326BCE1C51C77600F785CF /* SettingsCellWrapper.swift in Sources */, 3E326BCE1C51C77600F785CF /* SettingsCellWrapper.swift in Sources */,
3E627FF31C55AE35005C0372 /* TDAudioPlayerConstants.m in Sources */,
3E5485B31C69A7DA00E7D5AB /* LoadingPartyViewController.swift in Sources */, 3E5485B31C69A7DA00E7D5AB /* LoadingPartyViewController.swift in Sources */,
3E631B411CB4D3150050808F /* TDAudioQueue.m in Sources */,
3E3B14DC1C5BBB3B001C437F /* PendingRequestViewController.swift in Sources */, 3E3B14DC1C5BBB3B001C437F /* PendingRequestViewController.swift in Sources */,
3E379EF61C3E646000F7BCCD /* ParseNetDebug.m in Sources */, 3E379EF61C3E646000F7BCCD /* ParseNetDebug.m in Sources */,
3E627FED1C55AE35005C0372 /* TDAudioQueueBufferManager.m in Sources */,
3EBE976F1C53E6950079B54A /* InviteFriendCell.swift in Sources */, 3EBE976F1C53E6950079B54A /* InviteFriendCell.swift in Sources */,
3E627FEF1C55AE35005C0372 /* TDAudioQueueFiller.m in Sources */,
3E1BDA551C37111D00EE3B84 /* GetHip.xcdatamodeld in Sources */, 3E1BDA551C37111D00EE3B84 /* GetHip.xcdatamodeld in Sources */,
3E326BCC1C51C20000F785CF /* SettingsTableViewController.swift in Sources */, 3E326BCC1C51C20000F785CF /* SettingsTableViewController.swift in Sources */,
3EF36C761C71694C00CD0DC0 /* SignInController.swift in Sources */, 3EF36C761C71694C00CD0DC0 /* SignInController.swift in Sources */,
3E631B441CB4D3150050808F /* TDAudioQueueController.m in Sources */,
3EBE97731C5413240079B54A /* TestInviteFriendsCell.swift in Sources */, 3EBE97731C5413240079B54A /* TestInviteFriendsCell.swift in Sources */,
3E631B4A1CB4D3150050808F /* TDAudioStreamerConstants.m in Sources */,
3E101F0A1C52F14A00C895CA /* InviteFriendsView.swift in Sources */, 3E101F0A1C52F14A00C895CA /* InviteFriendsView.swift in Sources */,
3E1B5E451C5274E700D1AB62 /* SettingsDetailViewWrapper.swift in Sources */, 3E1B5E451C5274E700D1AB62 /* SettingsDetailViewWrapper.swift in Sources */,
3E631B481CB4D3150050808F /* TDAudioOutputStreamer.m in Sources */,
3EBE97711C540BB80079B54A /* TestInviteFriendsController.swift in Sources */, 3EBE97711C540BB80079B54A /* TestInviteFriendsController.swift in Sources */,
3E18D4951C51FAC60012F7DF /* UserParseDataSource.swift in Sources */, 3E18D4951C51FAC60012F7DF /* UserParseDataSource.swift in Sources */,
3E627FEC1C55AE35005C0372 /* TDAudioQueueBuffer.m in Sources */,
3E627FEB1C55AE35005C0372 /* TDAudioQueue.m in Sources */,
3E3412591C54C6B7006226E0 /* SongCellWrapper.swift in Sources */, 3E3412591C54C6B7006226E0 /* SongCellWrapper.swift in Sources */,
3E1BDA521C37111D00EE3B84 /* AppDelegate.swift in Sources */, 3E1BDA521C37111D00EE3B84 /* AppDelegate.swift in Sources */,
3E627FF11C55AE35005C0372 /* TDAudioInputStreamer.m in Sources */,
3E4169551C398A5B00B193AF /* SignUpViewController.swift in Sources */, 3E4169551C398A5B00B193AF /* SignUpViewController.swift in Sources */,
3E5BD3111C6C424300266B16 /* CurrentlyPlayingViewController.swift in Sources */, 3E5BD3111C6C424300266B16 /* CurrentlyPlayingViewController.swift in Sources */,
3E627FEE1C55AE35005C0372 /* TDAudioQueueController.m in Sources */,
3E627FE71C55AE35005C0372 /* NSMutableArray+QueueMethods.m in Sources */,
3E3B14DE1C5BCC9B001C437F /* FriendRequestViewController.swift in Sources */, 3E3B14DE1C5BCC9B001C437F /* FriendRequestViewController.swift in Sources */,
3E631B491CB4D3150050808F /* TDAudioStreamer.m in Sources */,
3E631B431CB4D3150050808F /* TDAudioQueueBufferManager.m in Sources */,
3E631B461CB4D3150050808F /* TDAudioStream.m in Sources */,
3E631B401CB4D3150050808F /* TDAudioFileStream.m in Sources */,
3E18D4931C51F6230012F7DF /* UserParseData.swift in Sources */, 3E18D4931C51F6230012F7DF /* UserParseData.swift in Sources */,
3E416EEE1C97BE31001EA319 /* NextUpViewController.swift in Sources */, 3E416EEE1C97BE31001EA319 /* NextUpViewController.swift in Sources */,
3E631B3F1CB4D3150050808F /* NSMutableArray+QueueMethods.m in Sources */,
3E631B471CB4D3150050808F /* TDAudioInputStreamer.m in Sources */,
3E5952851C39E54A00C88C71 /* HomeScreenViewController.swift in Sources */, 3E5952851C39E54A00C88C71 /* HomeScreenViewController.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@ -49,7 +49,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate , CLLocationManagerDelegat
if(PFUser.currentUser() == nil){ if(PFUser.currentUser() == nil){
//var initialViewController = storyboard.instantiateViewControllerWithIdentifier("HomeVC") as! HomeScreenViewController //var initialViewController = storyboard.instantiateViewControllerWithIdentifier("HomeVC") as! HomeScreenViewController
var initialViewController = storyboard.instantiateViewControllerWithIdentifier("LoginVC") as! UITabBarController var initialViewController = storyboard.instantiateViewControllerWithIdentifier("LoginVC") as! LoginController
self.window?.rootViewController = initialViewController self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible() self.window?.makeKeyAndVisible()

View File

@ -0,0 +1,15 @@
//
// NSInputStream+URLInitialization.h
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/11/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@interface NSInputStream (URLInitialization)
+ (NSInputStream *)inputStreamWithExternalURL:(NSURL *)url;
@end

View File

@ -0,0 +1,47 @@
//
// NSInputStream+URLInitialization.m
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/11/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "NSInputStream+URLInitialization.h"
@implementation NSInputStream (URLInitialization)
+ (NSInputStream *)inputStreamWithExternalURL:(NSURL *)url
{
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)(url), kCFHTTPVersion1_1);
if (!message) return nil;
CFReadStreamRef stream = CFReadStreamCreateForHTTPRequest(NULL, message);
CFRelease(message);
if (!stream) return nil;
CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue);
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPProxy, proxySettings);
CFRelease(proxySettings);
if ([url.absoluteString rangeOfString:@"https"].location != NSNotFound) {
NSDictionary *sslSettings = @{(NSString *)kCFStreamSSLLevel: (NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL,
(NSString *)kCFStreamSSLAllowsExpiredCertificates: @YES,
(NSString *)kCFStreamSSLAllowsExpiredRoots: @YES,
(NSString *)kCFStreamSSLAllowsAnyRoot: @YES,
(NSString *)kCFStreamSSLValidatesCertificateChain: @NO,
(NSString *)kCFStreamSSLPeerName: [NSNull null]};
CFReadStreamSetProperty(stream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)(sslSettings));
}
// CFRetain(stream);
return (__bridge NSInputStream *)stream;
}
@end

View File

@ -0,0 +1,17 @@
//
// NSMutableArray+QueueMethods.h
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/12/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@interface NSMutableArray (QueueMethods)
- (void)pushObject:(id)object;
- (id)popObject;
- (id)topObject;
@end

View File

@ -0,0 +1,38 @@
//
// NSMutableArray+QueueMethods.m
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/12/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "NSMutableArray+QueueMethods.h"
@implementation NSMutableArray (QueueMethods)
- (void)pushObject:(id)object
{
[self addObject:object];
}
- (id)popObject
{
if (self.count > 0) {
id object = self[0];
[self removeObjectAtIndex:0];
return object;
}
return nil;
}
- (id)topObject
{
if (self.count > 0) {
return self[0];
}
return nil;
}
@end

View File

@ -0,0 +1,19 @@
//
// TDAudioMetaInfo.h
// TDAudioPlayer
//
// Created by Tony DiPasquale on 10/16/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@interface TDAudioMetaInfo : NSObject
@property (strong, nonatomic) NSString *title;
@property (strong, nonatomic) NSString *artist;
@property (strong, nonatomic) NSString *albumArtSmall;
@property (strong, nonatomic) NSString *albumArtLarge;
@property (strong, nonatomic) NSNumber *duration;
@end

View File

@ -0,0 +1,13 @@
//
// TDAudioMetaInfo.m
// TDAudioPlayer
//
// Created by Tony DiPasquale on 10/16/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioMetaInfo.h"
@implementation TDAudioMetaInfo
@end

View File

@ -0,0 +1,41 @@
//
// TDAudioPlayer.h
// TDAudioPlayer
//
// Created by Tony DiPasquale on 10/16/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "TDAudioMetaInfo.h"
#import "TDAudioInputStreamer.h"
#import "TDAudioPlayerConstants.h"
typedef NS_ENUM(NSInteger, TDAudioPlayerState) {
TDAudioPlayerStateStopped,
TDAudioPlayerStateStarting,
TDAudioPlayerStatePlaying,
TDAudioPlayerStatePaused
};
@interface TDAudioPlayer : NSObject
@property (assign, nonatomic, readonly) TDAudioPlayerState state;
+ (instancetype)sharedAudioPlayer;
- (void)loadAudioFromURL:(NSURL *)url;
- (void)loadAudioFromURL:(NSURL *)url withMetaData:(TDAudioMetaInfo *)meta;
- (void)loadAudioFromStream:(NSInputStream *)stream;
- (void)loadAudioFromStream:(NSInputStream *)stream withMetaData:(TDAudioMetaInfo *)meta;
- (void)play;
- (void)pause;
- (void)stop;
- (void)handleRemoteControlEvent:(UIEvent *)event;
@end

View File

@ -0,0 +1,261 @@
//
// TDAudioPlayer.m
// TDAudioPlayer
//
// Created by Tony DiPasquale on 10/16/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import "TDAudioPlayer.h"
@interface TDAudioPlayer ()
@property (strong, nonatomic) TDAudioInputStreamer *streamer;
@property (strong, nonatomic) NSMutableDictionary *nowPlayingMetaInfo;
@property (assign, nonatomic) TDAudioPlayerState state;
@property (strong, nonatomic) NSTimer *timer;
@property (assign, nonatomic) NSUInteger elapsedTime;
@end
@implementation TDAudioPlayer
+ (instancetype)sharedAudioPlayer
{
static TDAudioPlayer *player;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
player = [[TDAudioPlayer alloc] init];
});
return player;
}
- (instancetype)init
{
self = [super init];
if (!self) return nil;
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionDidInterrupt:) name:AVAudioSessionInterruptionNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionDidChangeRoute:) name:AVAudioSessionRouteChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioDidStartPlaying) name:TDAudioStreamDidStartPlayingNotification object:nil];
return self;
}
#pragma mark - Audio Loading
- (void)loadAudioFromURL:(NSURL *)url
{
[self loadAudioFromURL:url withMetaData:nil];
}
- (void)loadAudioFromURL:(NSURL *)url withMetaData:(TDAudioMetaInfo *)meta
{
[self reset];
self.streamer = [[TDAudioInputStreamer alloc] initWithURL:url];
[self changeAudioMetaInfo:meta];
}
- (void)loadAudioFromStream:(NSInputStream *)stream
{
[self loadAudioFromStream:stream withMetaData:nil];
}
- (void)loadAudioFromStream:(NSInputStream *)stream withMetaData:(TDAudioMetaInfo *)meta
{
[self reset];
self.streamer = [[TDAudioInputStreamer alloc] initWithInputStream:stream];
[self changeAudioMetaInfo:meta];
}
- (void)reset
{
[self.streamer stop];
self.streamer = nil;
self.state = TDAudioPlayerStateStopped;
self.elapsedTime = 0;
[self clearTimer];
}
#pragma mark - Audio Controls
- (void)play
{
if (!self.streamer || self.state == TDAudioPlayerStatePlaying) return;
if (self.state == TDAudioPlayerStateStopped) return [self start];
[self.streamer resume];
[self setNowPlayingInfoWithPlaybackRate:@1];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(elapseTime) userInfo:nil repeats:YES];
self.state = TDAudioPlayerStatePlaying;
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioPlayerDidPlayNotification object:nil];
}
- (void)start
{
if (self.state == TDAudioPlayerStateStarting) return;
[self.streamer start];
self.state = TDAudioPlayerStateStarting;
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioPlayerDidPlayNotification object:nil];
}
- (void)pause
{
if (!self.streamer || self.state == TDAudioPlayerStatePaused) return;
[self setNowPlayingInfoWithPlaybackRate:@0.000001f];
[self clearTimer];
[self.streamer pause];
self.state = TDAudioPlayerStatePaused;
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioPlayerDidPauseNotification object:nil];
}
- (void)stop
{
if (!self.streamer || self.state == TDAudioPlayerStateStopped) return;
[self reset];
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioPlayerDidStopNotification object:nil];
}
#pragma mark - Remote Events
- (void)handleRemoteControlEvent:(UIEvent *)event
{
if (event.type != UIEventTypeRemoteControl) return;
switch (event.subtype) {
case UIEventSubtypeRemoteControlPause:
[self pause];
break;
case UIEventSubtypeRemoteControlPlay:
[self play];
break;
case UIEventSubtypeRemoteControlStop:
[self stop];
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
if (self.state == TDAudioPlayerStatePlaying) {
[self pause];
} else {
[self play];
}
break;
case UIEventSubtypeRemoteControlNextTrack:
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioPlayerNextTrackRequestNotification object:nil];
break;
case UIEventSubtypeRemoteControlPreviousTrack:
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioPlayerPreviousTrackRequestNotification object:nil];
break;
default:
break;
}
}
#pragma mark - Timer Helpers
- (void)elapseTime
{
self.elapsedTime++;
}
- (void)clearTimer
{
[self.timer invalidate];
self.timer = nil;
}
#pragma mark - Now Playing Info Helpers
- (void)changeAudioMetaInfo:(TDAudioMetaInfo *)meta
{
[self setNowPlayingInfoWithMetaInfo:meta];
if (!meta)
return [[NSNotificationCenter defaultCenter] postNotificationName:TDAudioPlayerDidChangeAudioNotification object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioPlayerDidChangeAudioNotification object:nil userInfo:@{@"meta": meta}];
}
- (void)setNowPlayingInfoWithMetaInfo:(TDAudioMetaInfo *)info
{
if (!info) {
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = @{};
return;
}
if (!self.nowPlayingMetaInfo)
self.nowPlayingMetaInfo = [NSMutableDictionary dictionary];
else
[self.nowPlayingMetaInfo removeAllObjects];
if (info.title) self.nowPlayingMetaInfo[MPMediaItemPropertyTitle] = info.title;
if (info.artist) self.nowPlayingMetaInfo[MPMediaItemPropertyArtist] = info.artist;
if (info.albumArtLarge) {
MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:info.albumArtLarge]]]];
if (artwork) self.nowPlayingMetaInfo[MPMediaItemPropertyArtwork] = artwork;
}
if (info.duration) self.nowPlayingMetaInfo[MPMediaItemPropertyPlaybackDuration] = info.duration;
[self setNowPlayingInfoWithPlaybackRate:@0];
}
- (void)setNowPlayingInfoWithPlaybackRate:(NSNumber *)rate
{
if (!self.nowPlayingMetaInfo) return;
self.nowPlayingMetaInfo[MPNowPlayingInfoPropertyPlaybackRate] = rate;
self.nowPlayingMetaInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = @(self.elapsedTime);
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = self.nowPlayingMetaInfo;
}
#pragma mark - Notification Handlers
- (void)audioSessionDidInterrupt:(NSNotification *)notification
{
NSUInteger type = [notification.userInfo[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (type == AVAudioSessionInterruptionTypeBegan)
[self pause];
}
- (void)audioSessionDidChangeRoute:(NSNotification *)notification
{
NSUInteger reason = [notification.userInfo[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable)
[self pause];
}
- (void)audioDidStartPlaying
{
[self setNowPlayingInfoWithPlaybackRate:@1];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(elapseTime) userInfo:nil repeats:YES];
self.state = TDAudioPlayerStatePlaying;
}
#pragma mark - Cleanup
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

View File

@ -0,0 +1,17 @@
//
// NSMutableArray+QueueMethods.h
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/12/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@interface NSMutableArray (QueueMethods)
- (void)pushObject:(id)object;
- (id)popObject;
- (id)topObject;
@end

View File

@ -0,0 +1,38 @@
//
// NSMutableArray+QueueMethods.m
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/12/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "NSMutableArray+QueueMethods.h"
@implementation NSMutableArray (QueueMethods)
- (void)pushObject:(id)object
{
[self addObject:object];
}
- (id)popObject
{
if (self.count > 0) {
id object = self[0];
[self removeObjectAtIndex:0];
return object;
}
return nil;
}
- (id)topObject
{
if (self.count > 0) {
return self[0];
}
return nil;
}
@end

View File

@ -0,0 +1,38 @@
//
// TDAudioFileStream.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@class TDAudioFileStream;
@protocol TDAudioFileStreamDelegate <NSObject>
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveError:(OSStatus)error;
@required
- (void)audioFileStreamDidBecomeReady:(TDAudioFileStream *)audioFileStream;
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription;
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveData:(const void *)data length:(UInt32)length;
@end
@interface TDAudioFileStream : NSObject
@property (assign, nonatomic) AudioStreamBasicDescription basicDescription;
@property (assign, nonatomic) UInt64 totalByteCount;
@property (assign, nonatomic) UInt32 packetBufferSize;
@property (assign, nonatomic) void *magicCookieData;
@property (assign, nonatomic) UInt32 magicCookieLength;
@property (assign, nonatomic) BOOL discontinuous;
@property (assign, nonatomic) id<TDAudioFileStreamDelegate> delegate;
- (instancetype)init;
- (void)parseData:(const void *)data length:(UInt32)length;
@end

View File

@ -0,0 +1,112 @@
//
// TDAudioFileStream.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioFileStream.h"
@interface TDAudioFileStream ()
@property (assign, nonatomic) AudioFileStreamID audioFileStreamID;
- (void)didChangeProperty:(AudioFileStreamPropertyID)propertyID flags:(UInt32 *)flags;
- (void)didReceivePackets:(const void *)packets packetDescriptions:(AudioStreamPacketDescription *)packetDescriptions numberOfPackets:(UInt32)numberOfPackets numberOfBytes:(UInt32)numberOfBytes;
@end
void TDAudioFileStreamPropertyListener(void *inClientData, AudioFileStreamID inAudioFileStreamID, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags)
{
TDAudioFileStream *audioFileStream = (__bridge TDAudioFileStream *)inClientData;
[audioFileStream didChangeProperty:inPropertyID flags:ioFlags];
}
void TDAudioFileStreamPacketsListener(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions)
{
TDAudioFileStream *audioFileStream = (__bridge TDAudioFileStream *)inClientData;
[audioFileStream didReceivePackets:inInputData packetDescriptions:inPacketDescriptions numberOfPackets:inNumberPackets numberOfBytes:inNumberBytes];
}
@implementation TDAudioFileStream
- (instancetype)init
{
self = [super init];
if (!self) return nil;
OSStatus err = AudioFileStreamOpen((__bridge void *)self, TDAudioFileStreamPropertyListener, TDAudioFileStreamPacketsListener, 0, &_audioFileStreamID);
if (err) return nil;
self.discontinuous = YES;
return self;
}
- (void)didChangeProperty:(AudioFileStreamPropertyID)propertyID flags:(UInt32 *)flags
{
if (propertyID == kAudioFileStreamProperty_ReadyToProducePackets) {
UInt32 basicDescriptionSize = sizeof(self.basicDescription);
OSStatus err = AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_DataFormat, &basicDescriptionSize, &_basicDescription);
if (err) return [self.delegate audioFileStream:self didReceiveError:err];
UInt32 byteCountSize;
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &_totalByteCount);
UInt32 sizeOfUInt32 = sizeof(UInt32);
err = AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &_packetBufferSize);
if (err || !self.packetBufferSize) {
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &_packetBufferSize);
}
Boolean writeable;
err = AudioFileStreamGetPropertyInfo(self.audioFileStreamID, kAudioFileStreamProperty_MagicCookieData, &_magicCookieLength, &writeable);
if (!err) {
self.magicCookieData = calloc(1, self.magicCookieLength);
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_MagicCookieData, &_magicCookieLength, self.magicCookieData);
}
[self.delegate audioFileStreamDidBecomeReady:self];
}
}
- (void)didReceivePackets:(const void *)packets packetDescriptions:(AudioStreamPacketDescription *)packetDescriptions numberOfPackets:(UInt32)numberOfPackets numberOfBytes:(UInt32)numberOfBytes
{
if (packetDescriptions) {
for (NSUInteger i = 0; i < numberOfPackets; i++) {
SInt64 packetOffset = packetDescriptions[i].mStartOffset;
UInt32 packetSize = packetDescriptions[i].mDataByteSize;
[self.delegate audioFileStream:self didReceiveData:(const void *)(packets + packetOffset) length:packetSize packetDescription:(AudioStreamPacketDescription)packetDescriptions[i]];
}
} else {
[self.delegate audioFileStream:self didReceiveData:(const void *)packets length:numberOfBytes];
}
}
- (void)parseData:(const void *)data length:(UInt32)length
{
OSStatus err;
if (self.discontinuous) {
err = AudioFileStreamParseBytes(self.audioFileStreamID, length, data, kAudioFileStreamParseFlag_Discontinuity);
self.discontinuous = NO;
} else {
err = AudioFileStreamParseBytes(self.audioFileStreamID, length, data, 0);
}
if (err) [self.delegate audioFileStream:self didReceiveError:err];
}
- (void)dealloc
{
AudioFileStreamClose(self.audioFileStreamID);
free(_magicCookieData);
}
@end

View File

@ -0,0 +1,45 @@
//
// TDAudioQueue.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
typedef NS_ENUM(NSUInteger, TDAudioQueueState) {
TDAudioQueueStateBuffering,
TDAudioQueueStateStopped,
TDAudioQueueStatePaused,
TDAudioQueueStatePlaying
};
@class TDAudioQueue;
@protocol TDAudioQueueDelegate <NSObject>
- (void)audioQueueDidFinishPlaying:(TDAudioQueue *)audioQueue;
- (void)audioQueueDidStartPlaying:(TDAudioQueue *)audioQueue;
@end
@class TDAudioQueueBuffer;
@interface TDAudioQueue : NSObject
@property (assign, nonatomic) TDAudioQueueState state;
@property (assign, nonatomic) id<TDAudioQueueDelegate> delegate;
- (instancetype)initWithBasicDescription:(AudioStreamBasicDescription)basicDescription bufferCount:(UInt32)bufferCount bufferSize:(UInt32)bufferSize magicCookieData:(void *)magicCookieData magicCookieSize:(UInt32)magicCookieSize;
- (TDAudioQueueBuffer *)nextFreeBuffer;
- (void)enqueue;
- (void)play;
- (void)pause;
- (void)stop;
- (void)finish;
@end

View File

@ -0,0 +1,141 @@
//
// TDAudioQueue.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueue.h"
#import "TDAudioQueueBuffer.h"
#import "TDAudioQueueController.h"
#import "TDAudioQueueBufferManager.h"
#import "TDAudioStreamerConstants.h"
@interface TDAudioQueue ()
@property (assign, nonatomic) AudioQueueRef audioQueue;
@property (strong, nonatomic) TDAudioQueueBufferManager *bufferManager;
@property (strong, nonatomic) NSCondition *waitForFreeBufferCondition;
@property (assign, nonatomic) NSUInteger buffersToFillBeforeStart;
- (void)didFreeAudioQueueBuffer:(AudioQueueBufferRef)audioQueueBuffer;
@end
void TDAudioQueueOutputCallback(void *inUserData, AudioQueueRef inAudioQueue, AudioQueueBufferRef inAudioQueueBuffer)
{
TDAudioQueue *audioQueue = (__bridge TDAudioQueue *)inUserData;
[audioQueue didFreeAudioQueueBuffer:inAudioQueueBuffer];
}
@implementation TDAudioQueue
- (instancetype)initWithBasicDescription:(AudioStreamBasicDescription)basicDescription bufferCount:(UInt32)bufferCount bufferSize:(UInt32)bufferSize magicCookieData:(void *)magicCookieData magicCookieSize:(UInt32)magicCookieSize
{
self = [self init];
if (!self) return nil;
OSStatus err = AudioQueueNewOutput(&basicDescription, TDAudioQueueOutputCallback, (__bridge void *)self, NULL, NULL, 0, &_audioQueue);
if (err) return nil;
self.bufferManager = [[TDAudioQueueBufferManager alloc] initWithAudioQueue:self.audioQueue size:bufferSize count:bufferCount];
AudioQueueSetProperty(self.audioQueue, kAudioQueueProperty_MagicCookie, magicCookieData, magicCookieSize);
free(magicCookieData);
AudioQueueSetParameter(self.audioQueue, kAudioQueueParam_Volume, 1.0);
self.waitForFreeBufferCondition = [[NSCondition alloc] init];
self.state = TDAudioQueueStateBuffering;
self.buffersToFillBeforeStart = kTDAudioQueueStartMinimumBuffers;
return self;
}
#pragma mark - Audio Queue Events
- (void)didFreeAudioQueueBuffer:(AudioQueueBufferRef)audioQueueBuffer
{
[self.bufferManager freeAudioQueueBuffer:audioQueueBuffer];
[self.waitForFreeBufferCondition lock];
[self.waitForFreeBufferCondition signal];
[self.waitForFreeBufferCondition unlock];
if (self.state == TDAudioQueueStateStopped && ![self.bufferManager isProcessingAudioQueueBuffer]) {
[self.delegate audioQueueDidFinishPlaying:self];
}
}
#pragma mark - Public Methods
- (TDAudioQueueBuffer *)nextFreeBuffer
{
if (![self.bufferManager hasAvailableAudioQueueBuffer]) {
[self.waitForFreeBufferCondition lock];
[self.waitForFreeBufferCondition wait];
[self.waitForFreeBufferCondition unlock];
}
TDAudioQueueBuffer *nextBuffer = [self.bufferManager nextFreeBuffer];
if (!nextBuffer) return [self nextFreeBuffer];
return nextBuffer;
}
- (void)enqueue
{
[self.bufferManager enqueueNextBufferOnAudioQueue:self.audioQueue];
if (self.state == TDAudioQueueStateBuffering && --self.buffersToFillBeforeStart == 0) {
AudioQueuePrime(self.audioQueue, 0, NULL);
[self play];
[self.delegate audioQueueDidStartPlaying:self];
}
}
#pragma mark - Audio Queue Controls
- (void)play
{
if (self.state == TDAudioQueueStatePlaying) return;
[TDAudioQueueController playAudioQueue:self.audioQueue];
self.state = TDAudioQueueStatePlaying;
}
- (void)pause
{
if (self.state == TDAudioQueueStatePaused) return;
[TDAudioQueueController pauseAudioQueue:self.audioQueue];
self.state = TDAudioQueueStatePaused;
}
- (void)stop
{
if (self.state == TDAudioQueueStateStopped) return;
[TDAudioQueueController stopAudioQueue:self.audioQueue];
self.state = TDAudioQueueStateStopped;
}
- (void)finish
{
if (self.state == TDAudioQueueStateStopped) return;
[TDAudioQueueController finishAudioQueue:self.audioQueue];
self.state = TDAudioQueueStateStopped;
}
#pragma mark - Cleanup
- (void)dealloc
{
[self.bufferManager freeBufferMemoryFromAudioQueue:self.audioQueue];
AudioQueueDispose(self.audioQueue, YES);
}
@end

View File

@ -0,0 +1,26 @@
//
// TDAudioQueueBuffer.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/11/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@interface TDAudioQueueBuffer : NSObject
- (instancetype)initWithAudioQueue:(AudioQueueRef)audioQueue size:(UInt32)size;
- (NSInteger)fillWithData:(const void *)data length:(UInt32)length offset:(UInt32)offset;
- (BOOL)fillWithData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription;
- (void)enqueueWithAudioQueue:(AudioQueueRef)auidoQueue;
- (void)reset;
- (BOOL)isEqual:(AudioQueueBufferRef)audioQueueBuffer;
- (void)freeFromAudioQueue:(AudioQueueRef)audioQueue;
@end

View File

@ -0,0 +1,106 @@
//
// TDAudioQueueBuffer.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/11/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueueBuffer.h"
const NSUInteger kTDMaxPacketDescriptions = 512;
@interface TDAudioQueueBuffer ()
@property (assign, nonatomic) AudioQueueBufferRef audioQueueBuffer;
@property (assign, nonatomic) UInt32 size;
@property (assign, nonatomic) UInt32 fillPosition;
@property (assign, nonatomic) AudioStreamPacketDescription *packetDescriptions;
@property (assign, nonatomic) UInt32 numberOfPacketDescriptions;
@end
@implementation TDAudioQueueBuffer
- (instancetype)initWithAudioQueue:(AudioQueueRef)audioQueue size:(UInt32)size
{
self = [super init];
if (!self) return nil;
self.size = size;
self.fillPosition = 0;
self.packetDescriptions = malloc(sizeof(AudioStreamPacketDescription) * kTDMaxPacketDescriptions);
self.numberOfPacketDescriptions = 0;
OSStatus err = AudioQueueAllocateBuffer(audioQueue, self.size, &_audioQueueBuffer);
if (err) return nil;
return self;
}
- (NSInteger)fillWithData:(const void *)data length:(UInt32)length offset:(UInt32)offset
{
if (self.fillPosition + length <= self.size)
{
memcpy((char *)(self.audioQueueBuffer->mAudioData + self.fillPosition), (const char *)(data + offset), length);
self.fillPosition += length;
}
else
{
NSUInteger availableSpace = self.size - self.fillPosition;
memcpy((char *)(self.audioQueueBuffer->mAudioData + self.fillPosition), (const char *)data, availableSpace);
self.fillPosition = self.size;
return length - availableSpace;
}
if (self.fillPosition == self.size) {
return -1;
}
return 0;
}
- (BOOL)fillWithData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription
{
if (self.fillPosition + packetDescription.mDataByteSize > self.size || self.numberOfPacketDescriptions == kTDMaxPacketDescriptions) return NO;
memcpy((char *)(self.audioQueueBuffer->mAudioData + self.fillPosition), (const char *)(data + packetDescription.mStartOffset), packetDescription.mDataByteSize);
self.packetDescriptions[self.numberOfPacketDescriptions] = packetDescription;
self.packetDescriptions[self.numberOfPacketDescriptions].mStartOffset = self.fillPosition;
self.numberOfPacketDescriptions++;
self.fillPosition += packetDescription.mDataByteSize;
return YES;
}
- (void)enqueueWithAudioQueue:(AudioQueueRef)audioQueue
{
self.audioQueueBuffer->mAudioDataByteSize = self.fillPosition;
AudioQueueEnqueueBuffer(audioQueue, self.audioQueueBuffer, self.numberOfPacketDescriptions, self.packetDescriptions);
}
- (void)reset
{
self.fillPosition = 0;
self.numberOfPacketDescriptions = 0;
}
- (BOOL)isEqual:(AudioQueueBufferRef)audioQueueBuffer
{
return audioQueueBuffer == self.audioQueueBuffer;
}
- (void)freeFromAudioQueue:(AudioQueueRef)audioQueue
{
AudioQueueFreeBuffer(audioQueue, self.audioQueueBuffer);
}
- (void)dealloc
{
free(_packetDescriptions);
}
@end

View File

@ -0,0 +1,27 @@
//
// TDAudioQueueBufferManager.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/29/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@class TDAudioQueueBuffer;
@interface TDAudioQueueBufferManager : NSObject
- (instancetype)initWithAudioQueue:(AudioQueueRef)audioQueue size:(UInt32)size count:(UInt32)count;
- (void)freeAudioQueueBuffer:(AudioQueueBufferRef)audioQueueBuffer;
- (TDAudioQueueBuffer *)nextFreeBuffer;
- (void)enqueueNextBufferOnAudioQueue:(AudioQueueRef)audioQueue;
- (BOOL)hasAvailableAudioQueueBuffer;
- (BOOL)isProcessingAudioQueueBuffer;
- (void)freeBufferMemoryFromAudioQueue:(AudioQueueRef)audioQueue;
@end

View File

@ -0,0 +1,114 @@
//
// TDAudioQueueBufferManager.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/29/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueueBufferManager.h"
#import "TDAudioQueueBuffer.h"
#import "NSMutableArray+QueueMethods.h"
@interface TDAudioQueueBufferManager ()
@property (assign, nonatomic) UInt32 bufferCount;
@property (assign, nonatomic) UInt32 bufferSize;
@property (strong, nonatomic) NSArray *audioQueueBuffers;
@property (strong, atomic) NSMutableArray *freeBuffers;
@end
@implementation TDAudioQueueBufferManager
- (instancetype)initWithAudioQueue:(AudioQueueRef)audioQueue size:(UInt32)size count:(UInt32)count
{
self = [super init];
if (!self) return nil;
self.bufferCount = count;
self.bufferSize = size;
self.freeBuffers = [NSMutableArray arrayWithCapacity:self.bufferCount];
NSMutableArray *audioqueuebuffers = [NSMutableArray arrayWithCapacity:self.bufferCount];
for (NSUInteger i = 0; i < self.bufferCount; i++) {
TDAudioQueueBuffer *buffer = [[TDAudioQueueBuffer alloc] initWithAudioQueue:audioQueue size:self.bufferSize];
if (!buffer) {
i--;
continue;
}
audioqueuebuffers[i] = buffer;
[self.freeBuffers pushObject:@(i)];
}
self.audioQueueBuffers = [audioqueuebuffers copy];
return self;
}
#pragma mark - Public Methods
- (void)freeAudioQueueBuffer:(AudioQueueBufferRef)audioQueueBuffer
{
for (NSUInteger i = 0; i < self.bufferCount; i++) {
if ([(TDAudioQueueBuffer *)self.audioQueueBuffers[i] isEqual:audioQueueBuffer]) {
[(TDAudioQueueBuffer *)self.audioQueueBuffers[i] reset];
@synchronized(self) {
[self.freeBuffers pushObject:@(i)];
}
break;
}
}
#if DEBUG
if (self.freeBuffers.count > self.bufferCount >> 1) {
NSLog(@"Free Buffers: %lu", (unsigned long)self.freeBuffers.count);
}
#endif
}
- (TDAudioQueueBuffer *)nextFreeBuffer
{
if (![self hasAvailableAudioQueueBuffer]) return nil;
@synchronized(self) {
return self.audioQueueBuffers[[[self.freeBuffers topObject] integerValue]];
}
}
- (void)enqueueNextBufferOnAudioQueue:(AudioQueueRef)audioQueue
{
@synchronized(self) {
NSInteger nextBufferIndex = [[self.freeBuffers popObject] integerValue];
TDAudioQueueBuffer *nextBuffer = self.audioQueueBuffers[nextBufferIndex];
[nextBuffer enqueueWithAudioQueue:audioQueue];
}
}
- (BOOL)hasAvailableAudioQueueBuffer
{
@synchronized(self) {
return self.freeBuffers.count > 0;
}
}
- (BOOL)isProcessingAudioQueueBuffer
{
@synchronized(self) {
return self.freeBuffers.count != self.bufferCount;
}
}
#pragma mark - Cleanup
- (void)freeBufferMemoryFromAudioQueue:(AudioQueueRef)audioQueue
{
for (NSUInteger i = 0; i < self.audioQueueBuffers.count; i++) {
[(TDAudioQueueBuffer *)self.audioQueueBuffers[i] freeFromAudioQueue:audioQueue];
}
}
@end

View File

@ -0,0 +1,19 @@
//
// TDAudioQueueController.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/29/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@interface TDAudioQueueController : NSObject
+ (OSStatus)playAudioQueue:(AudioQueueRef)audioQueue;
+ (OSStatus)pauseAudioQueue:(AudioQueueRef)audioQueue;
+ (OSStatus)stopAudioQueue:(AudioQueueRef)audioQueue;
+ (OSStatus)finishAudioQueue:(AudioQueueRef)audioQueue;
@end

View File

@ -0,0 +1,38 @@
//
// TDAudioQueueController.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/29/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueueController.h"
@implementation TDAudioQueueController
+ (OSStatus)playAudioQueue:(AudioQueueRef)audioQueue
{
return AudioQueueStart(audioQueue, NULL);
}
+ (OSStatus)pauseAudioQueue:(AudioQueueRef)audioQueue
{
return AudioQueuePause(audioQueue);
}
+ (OSStatus)stopAudioQueue:(AudioQueueRef)audioQueue
{
return [self stopAudioQueue:audioQueue immediately:YES];
}
+ (OSStatus)finishAudioQueue:(AudioQueueRef)audioQueue
{
return [self stopAudioQueue:audioQueue immediately:NO];
}
+ (OSStatus)stopAudioQueue:(AudioQueueRef)audioQueue immediately:(BOOL)immediately
{
return AudioQueueStop(audioQueue, immediately);
}
@end

View File

@ -0,0 +1,19 @@
//
// TDAudioQueueFiller.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/31/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@class TDAudioQueue;
@interface TDAudioQueueFiller : NSObject
+ (void)fillAudioQueue:(TDAudioQueue *)audioQueue withData:(const void *)data length:(UInt32)length offset:(UInt32)offset;
+ (void)fillAudioQueue:(TDAudioQueue *)audioQueue withData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription;
@end

View File

@ -0,0 +1,41 @@
//
// TDAudioQueueFiller.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/31/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioQueueFiller.h"
#import "TDAudioQueueBuffer.h"
#import "TDAudioQueue.h"
@implementation TDAudioQueueFiller
+ (void)fillAudioQueue:(TDAudioQueue *)audioQueue withData:(const void *)data length:(UInt32)length offset:(UInt32)offset
{
TDAudioQueueBuffer *audioQueueBuffer = [audioQueue nextFreeBuffer];
NSInteger leftovers = [audioQueueBuffer fillWithData:data length:length offset:offset];
if (leftovers == 0) return;
[audioQueue enqueue];
if (leftovers > 0)
[self fillAudioQueue:audioQueue withData:data length:length offset:(length - (UInt32)leftovers)];
}
+ (void)fillAudioQueue:(TDAudioQueue *)audioQueue withData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription
{
TDAudioQueueBuffer *audioQueueBuffer = [audioQueue nextFreeBuffer];
BOOL hasMoreRoomForPackets = [audioQueueBuffer fillWithData:data length:length packetDescription:packetDescription];
if (!hasMoreRoomForPackets) {
[audioQueue enqueue];
[self fillAudioQueue:audioQueue withData:data length:length packetDescription:packetDescription];
}
}
@end

View File

@ -0,0 +1,39 @@
//
// TDAudioStream.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, TDAudioStreamEvent) {
TDAudioStreamEventHasData,
TDAudioStreamEventWantsData,
TDAudioStreamEventEnd,
TDAudioStreamEventError
};
@class TDAudioStream;
@protocol TDAudioStreamDelegate <NSObject>
@required
- (void)audioStream:(TDAudioStream *)audioStream didRaiseEvent:(TDAudioStreamEvent)event;
@end
@interface TDAudioStream : NSObject
@property (assign, nonatomic) id<TDAudioStreamDelegate> delegate;
- (instancetype)initWithInputStream:(NSInputStream *)inputStream;
- (instancetype)initWithOutputStream:(NSOutputStream *)outputStream;
- (void)open;
- (void)close;
- (UInt32)readData:(uint8_t *)data maxLength:(UInt32)maxLength;
- (UInt32)writeData:(uint8_t *)data maxLength:(UInt32)maxLength;
@end

View File

@ -0,0 +1,93 @@
//
// TDAudioStream.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioStream.h"
@interface TDAudioStream () <NSStreamDelegate>
@property (strong, nonatomic) NSStream *stream;
@end
@implementation TDAudioStream
- (instancetype)initWithInputStream:(NSInputStream *)inputStream
{
self = [super init];
if (!self) return nil;
self.stream = inputStream;
return self;
}
- (instancetype)initWithOutputStream:(NSOutputStream *)outputStream
{
self = [super init];
if (!self) return nil;
self.stream = outputStream;
return self;
}
- (void)open
{
self.stream.delegate = self;
[self.stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
return [self.stream open];
}
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventHasBytesAvailable:
[self.delegate audioStream:self didRaiseEvent:TDAudioStreamEventHasData];
break;
case NSStreamEventHasSpaceAvailable:
[self.delegate audioStream:self didRaiseEvent:TDAudioStreamEventWantsData];
break;
case NSStreamEventEndEncountered:
[self.delegate audioStream:self didRaiseEvent:TDAudioStreamEventEnd];
break;
case NSStreamEventErrorOccurred:
[self.delegate audioStream:self didRaiseEvent:TDAudioStreamEventError];
break;
default:
break;
}
}
- (UInt32)readData:(uint8_t *)data maxLength:(UInt32)maxLength
{
return (UInt32)[(NSInputStream *)self.stream read:data maxLength:maxLength];
}
- (UInt32)writeData:(uint8_t *)data maxLength:(UInt32)maxLength
{
return (UInt32)[(NSOutputStream *)self.stream write:data maxLength:maxLength];
}
- (void)close
{
[self.stream close];
self.stream.delegate = nil;
[self.stream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)dealloc
{
if (self.stream)
[self close];
}
@end

View File

@ -0,0 +1,24 @@
//
// TDAudioInputStreamer.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@interface TDAudioInputStreamer : NSObject
@property (assign, nonatomic) UInt32 audioStreamReadMaxLength;
@property (assign, nonatomic) UInt32 audioQueueBufferSize;
@property (assign, nonatomic) UInt32 audioQueueBufferCount;
- (instancetype)initWithInputStream:(NSInputStream *)inputStream;
- (void)start;
- (void)resume;
- (void)pause;
- (void)stop;
@end

View File

@ -0,0 +1,195 @@
//
// TDAudioInputStreamer.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioInputStreamer.h"
#import "TDAudioFileStream.h"
#import "TDAudioStream.h"
#import "TDAudioQueue.h"
#import "TDAudioQueueBuffer.h"
#import "TDAudioQueueFiller.h"
#import "TDAudioStreamerConstants.h"
@interface TDAudioInputStreamer () <TDAudioStreamDelegate, TDAudioFileStreamDelegate, TDAudioQueueDelegate>
@property (strong, nonatomic) NSThread *audioStreamerThread;
@property (assign, atomic) BOOL isPlaying;
@property (strong, nonatomic) TDAudioStream *audioStream;
@property (strong, nonatomic) TDAudioFileStream *audioFileStream;
@property (strong, nonatomic) TDAudioQueue *audioQueue;
@end
@implementation TDAudioInputStreamer
- (instancetype)init
{
self = [super init];
if (!self) return nil;
self.audioFileStream = [[TDAudioFileStream alloc] init];
if (!self.audioFileStream) return nil;
self.audioFileStream.delegate = self;
return self;
}
- (instancetype)initWithInputStream:(NSInputStream *)inputStream
{
self = [self init];
if (!self) return nil;
self.audioStream = [[TDAudioStream alloc] initWithInputStream:inputStream];
if (!self.audioStream) return nil;
self.audioStream.delegate = self;
return self;
}
- (void)start
{
if (![[NSThread currentThread] isEqual:[NSThread mainThread]]) {
return [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:YES];
}
self.audioStreamerThread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[self.audioStreamerThread start];
}
- (void)run
{
@autoreleasepool {
[self.audioStream open];
self.isPlaying = YES;
while (self.isPlaying && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) ;
}
}
#pragma mark - Properties
- (UInt32)audioStreamReadMaxLength
{
if (!_audioStreamReadMaxLength)
_audioStreamReadMaxLength = kTDAudioStreamReadMaxLength;
return _audioStreamReadMaxLength;
}
- (UInt32)audioQueueBufferSize
{
if (!_audioQueueBufferSize)
_audioQueueBufferSize = kTDAudioQueueBufferSize;
return _audioQueueBufferSize;
}
- (UInt32)audioQueueBufferCount
{
if (!_audioQueueBufferCount)
_audioQueueBufferCount = kTDAudioQueueBufferCount;
return _audioQueueBufferCount;
}
#pragma mark - TDAudioStreamDelegate
- (void)audioStream:(TDAudioStream *)audioStream didRaiseEvent:(TDAudioStreamEvent)event
{
switch (event) {
case TDAudioStreamEventHasData: {
uint8_t bytes[self.audioStreamReadMaxLength];
UInt32 length = [audioStream readData:bytes maxLength:self.audioStreamReadMaxLength];
[self.audioFileStream parseData:bytes length:length];
break;
}
case TDAudioStreamEventEnd:
self.isPlaying = NO;
[self.audioQueue finish];
break;
case TDAudioStreamEventError:
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioStreamDidFinishPlayingNotification object:nil];
break;
default:
break;
}
}
#pragma mark - TDAudioFileStreamDelegate
- (void)audioFileStreamDidBecomeReady:(TDAudioFileStream *)audioFileStream
{
UInt32 bufferSize = audioFileStream.packetBufferSize ? audioFileStream.packetBufferSize : self.audioQueueBufferSize;
self.audioQueue = [[TDAudioQueue alloc] initWithBasicDescription:audioFileStream.basicDescription bufferCount:self.audioQueueBufferCount bufferSize:bufferSize magicCookieData:audioFileStream.magicCookieData magicCookieSize:audioFileStream.magicCookieLength];
self.audioQueue.delegate = self;
}
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveError:(OSStatus)error
{
[[NSNotificationCenter defaultCenter] postNotificationName:TDAudioStreamDidFinishPlayingNotification object:nil];
}
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveData:(const void *)data length:(UInt32)length
{
[TDAudioQueueFiller fillAudioQueue:self.audioQueue withData:data length:length offset:0];
}
- (void)audioFileStream:(TDAudioFileStream *)audioFileStream didReceiveData:(const void *)data length:(UInt32)length packetDescription:(AudioStreamPacketDescription)packetDescription
{
[TDAudioQueueFiller fillAudioQueue:self.audioQueue withData:data length:length packetDescription:packetDescription];
}
#pragma mark - TDAudioQueueDelegate
- (void)audioQueueDidFinishPlaying:(TDAudioQueue *)audioQueue
{
[self performSelectorOnMainThread:@selector(notifyMainThread:) withObject:TDAudioStreamDidFinishPlayingNotification waitUntilDone:NO];
}
- (void)audioQueueDidStartPlaying:(TDAudioQueue *)audioQueue
{
[self performSelectorOnMainThread:@selector(notifyMainThread:) withObject:TDAudioStreamDidStartPlayingNotification waitUntilDone:NO];
}
- (void)notifyMainThread:(NSString *)notificationName
{
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:nil];
}
#pragma mark - Public Methods
- (void)resume
{
[self.audioQueue play];
}
- (void)pause
{
[self.audioQueue pause];
}
- (void)stop
{
[self performSelector:@selector(stopThread) onThread:self.audioStreamerThread withObject:nil waitUntilDone:YES];
}
- (void)stopThread
{
self.isPlaying = NO;
[self.audioQueue stop];
}
@end

View File

@ -0,0 +1,21 @@
//
// TDAudioOutputStreamer.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/14/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
@class AVURLAsset;
@interface TDAudioOutputStreamer : NSObject
- (instancetype)initWithOutputStream:(NSOutputStream *)stream;
- (void)streamAudioFromURL:(NSURL *)url;
- (void)start;
- (void)stop;
@end

View File

@ -0,0 +1,144 @@
//
// TDAudioOutputStreamer.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/14/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <AVFoundation/AVFoundation.h>
#import "TDAudioOutputStreamer.h"
#import "TDAudioStream.h"
@interface TDAudioOutputStreamer () <TDAudioStreamDelegate>
@property (strong, nonatomic) TDAudioStream *audioStream;
@property (strong, nonatomic) AVAssetReader *assetReader;
@property (strong, nonatomic) AVAssetReaderTrackOutput *assetOutput;
@property (strong, nonatomic) NSThread *streamThread;
@property (assign, atomic) BOOL isStreaming;
@end
@implementation TDAudioOutputStreamer
- (instancetype) initWithOutputStream:(NSOutputStream *)stream
{
self = [super init];
if (!self) return nil;
self.audioStream = [[TDAudioStream alloc] initWithOutputStream:stream];
self.audioStream.delegate = self;
NSLog(@"Init");
return self;
}
- (void)start
{
if (![[NSThread currentThread] isEqual:[NSThread mainThread]]) {
return [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:YES];
}
NSLog(@"Start");
self.streamThread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[self.streamThread start];
}
- (void)run
{
@autoreleasepool {
[self.audioStream open];
self.isStreaming = YES;
NSLog(@"Loop");
while (self.isStreaming && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) ;
NSLog(@"Done");
}
}
- (void)streamAudioFromURL:(NSURL *)url
{
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
NSError *assetError;
self.assetReader = [AVAssetReader assetReaderWithAsset:asset error:&assetError];
self.assetOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:asset.tracks[0] outputSettings:nil];
if (![self.assetReader canAddOutput:self.assetOutput]) return;
[self.assetReader addOutput:self.assetOutput];
[self.assetReader startReading];
NSLog(@"Read Asset");
}
- (void)sendDataChunk
{
CMSampleBufferRef sampleBuffer;
sampleBuffer = [self.assetOutput copyNextSampleBuffer];
if (sampleBuffer == NULL || CMSampleBufferGetNumSamples(sampleBuffer) == 0) {
CFRelease(sampleBuffer);
return;
}
CMBlockBufferRef blockBuffer;
AudioBufferList audioBufferList;
OSStatus err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, NULL, &audioBufferList, sizeof(AudioBufferList), NULL, NULL, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer);
if (err) {
CFRelease(sampleBuffer);
return;
}
for (NSUInteger i = 0; i < audioBufferList.mNumberBuffers; i++) {
AudioBuffer audioBuffer = audioBufferList.mBuffers[i];
[self.audioStream writeData:audioBuffer.mData maxLength:audioBuffer.mDataByteSize];
NSLog(@"buffer size: %u", (unsigned int)audioBuffer.mDataByteSize);
}
CFRelease(blockBuffer);
CFRelease(sampleBuffer);
}
- (void)stop
{
[self performSelector:@selector(stopThread) onThread:self.streamThread withObject:nil waitUntilDone:YES];
}
- (void)stopThread
{
self.isStreaming = NO;
[self.audioStream close];
NSLog(@"Stop");
}
#pragma mark - TDAudioStreamDelegate
- (void)audioStream:(TDAudioStream *)audioStream didRaiseEvent:(TDAudioStreamEvent)event
{
switch (event) {
case TDAudioStreamEventWantsData:
[self sendDataChunk];
break;
case TDAudioStreamEventError:
// TODO: shit!
NSLog(@"Stream Error");
break;
case TDAudioStreamEventEnd:
// TODO: shit!
NSLog(@"Stream Ended");
break;
default:
break;
}
}
@end

View File

@ -0,0 +1,17 @@
//
// TDAudioStreamer.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/18/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import <Foundation/Foundation.h>
#import "TDAudioStreamerConstants.h"
#import "TDAudioInputStreamer.h"
#import "TDAudioOutputStreamer.h"
@interface TDAudioStreamer : NSObject
@end

View File

@ -0,0 +1,13 @@
//
// TDAudioStreamer.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/18/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioStreamer.h"
@implementation TDAudioStreamer
@end

View File

@ -0,0 +1,25 @@
//
// TDAudioStreamerConstants.h
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/5/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "Foundation/Foundation.h"
extern NSString *const TDAudioStreamerDidChangeAudioNotification;
extern NSString *const TDAudioStreamerDidPauseNotification;
extern NSString *const TDAudioStreamerDidPlayNotification;
extern NSString *const TDAudioStreamerDidStopNotification;
extern NSString *const TDAudioStreamerNextTrackRequestNotification;
extern NSString *const TDAudioStreamerPreviousTrackRequestNotification;
extern NSString *const TDAudioStreamDidFinishPlayingNotification;
extern NSString *const TDAudioStreamDidStartPlayingNotification;
extern UInt32 const kTDAudioStreamReadMaxLength;
extern UInt32 const kTDAudioQueueBufferSize;
extern UInt32 const kTDAudioQueueBufferCount;
extern UInt32 const kTDAudioQueueStartMinimumBuffers;

View File

@ -0,0 +1,25 @@
//
// TDAudioStreamerConstants.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 11/5/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioStreamerConstants.h"
NSString *const TDAudioStreamerDidChangeAudioNotification = @"TDAudioStreamerDidChangeAudioNotification";
NSString *const TDAudioStreamerDidPauseNotification = @"TDAudioStreamerDidPauseNotification";
NSString *const TDAudioStreamerDidPlayNotification = @"TDAudioStreamerDidPlayNotification";
NSString *const TDAudioStreamerDidStopNotification = @"TDAudioStreamerDidStopNotification";
NSString *const TDAudioStreamerNextTrackRequestNotification = @"TDAudioStreamerNextTrackRequestNotification";
NSString *const TDAudioStreamerPreviousTrackRequestNotification = @"TDAudioStreamerPreviousTrackRequestNotification";
NSString *const TDAudioStreamDidFinishPlayingNotification = @"TDAudioStreamDidFinishPlayingNotification";
NSString *const TDAudioStreamDidStartPlayingNotification = @"TDAudioStreamDidStartPlayingNotification";
UInt32 const kTDAudioStreamReadMaxLength = 512;
UInt32 const kTDAudioQueueBufferSize = 2048;
UInt32 const kTDAudioQueueBufferCount = 16;
UInt32 const kTDAudioQueueStartMinimumBuffers = 8;

View File

@ -17,13 +17,13 @@
#import "ParseNetDebug.h" #import "ParseNetDebug.h"
//TDAudioPlayer //TDAudioPlayer
#import "NSInputStream+URLInitialization.h" //#import "NSInputStream+URLInitialization.h"
#import "NSMutableArray+QueueMethods.h" #import "NSMutableArray+QueueMethods.h"
#import "TDAudioMetaInfo.h" //#import "TDAudioMetaInfo.h"
#import "TDAudioInputStreamer.h" #import "TDAudioInputStreamer.h"
#import "TDAudioOutputStreamer.h" #import "TDAudioOutputStreamer.h"
#import "TDAudioPlayerConstants.h" //#import "TDAudioPlayerConstants.h"
#import "TDAudioPlayer.h" //#import "TDAudioPlayer.h"
#import "TDAudioFileStream.h" #import "TDAudioFileStream.h"
#import "TDAudioQueue.h" #import "TDAudioQueue.h"
#import "TDAudioQueueBuffer.h" #import "TDAudioQueueBuffer.h"

View File

@ -8,12 +8,45 @@
import UIKit import UIKit
class ForgotPassViewController: UIViewController { class ForgotPassViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var emailField: UITextField!
@IBOutlet weak var resestPass: UIButton!
@IBAction func dismiss(sender:UIBarButtonItem){
self.dismissViewControllerAnimated(true, completion: nil)
}
@IBAction func sendResetRequest(sender: UIButton){
PFUser.requestPasswordResetForEmailInBackground(self.emailField.text!) {
(succeeded, error) -> Void in
if (error == nil){
let alert = UIAlertController(title: "Success", message: "Check your email to start the password reset cycle.", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)}))
self.presentViewController(alert, animated: true, completion: nil)
}else{
let errorMessage = error!.userInfo!["error"] as! NSString
let alert = UIAlertController(title: "Failure", message:( errorMessage as? String)!, preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)}))
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
//dismisses keyboard when screen is tapped
let tapGesture = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard"))
tapGesture.cancelsTouchesInView = true
self.view.addGestureRecognizer(tapGesture)
self.emailField.delegate = self
// Do any additional setup after loading the view. // Do any additional setup after loading the view.
self.resestPass!.layer.borderWidth = 1
self.resestPass!.layer.cornerRadius = 5
self.resestPass!.layer.borderColor = UIColor.blackColor().CGColor
} }
override func didReceiveMemoryWarning() { override func didReceiveMemoryWarning() {
@ -22,6 +55,15 @@ class ForgotPassViewController: UIViewController {
} }
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
func hideKeyboard() {
self.view.endEditing(true)
}
/* /*
// MARK: - Navigation // MARK: - Navigation

View File

@ -12,13 +12,15 @@ class FriendData: NSObject, NSCoding {
var displayName: String! var displayName: String!
var profileImg: UIImageView! var profileImg: UIImageView!
var status: String! var status: String!
var username: String! //var username: String!
var email: String!
init(display: String, status: String, username: String){ init(display: String, status: String, /*username: String,*/ email: String){
self.displayName = display self.displayName = display
self.profileImg = nil self.profileImg = nil
self.status = status self.status = status
self.username = username //self.username = username
self.email = email
super.init() super.init()
} }
@ -29,7 +31,8 @@ class FriendData: NSObject, NSCoding {
self.displayName = aDecoder.decodeObjectForKey("displayName") as! String self.displayName = aDecoder.decodeObjectForKey("displayName") as! String
self.profileImg = aDecoder.decodeObjectForKey("profileImg") as! UIImageView! self.profileImg = aDecoder.decodeObjectForKey("profileImg") as! UIImageView!
self.status = aDecoder.decodeObjectForKey("status") as! String self.status = aDecoder.decodeObjectForKey("status") as! String
self.username = aDecoder.decodeObjectForKey("username") as! String //self.username = aDecoder.decodeObjectForKey("username") as! String
self.email = aDecoder.decodeObjectForKey("email") as! String
super.init() super.init()
} }
@ -37,7 +40,8 @@ class FriendData: NSObject, NSCoding {
aCoder.encodeObject(self.displayName, forKey: "displayName") aCoder.encodeObject(self.displayName, forKey: "displayName")
aCoder.encodeObject(self.profileImg, forKey: "profileImg") aCoder.encodeObject(self.profileImg, forKey: "profileImg")
aCoder.encodeObject(self.status, forKey: "status") aCoder.encodeObject(self.status, forKey: "status")
aCoder.encodeObject(self.username, forKey: "username") //aCoder.encodeObject(self.username, forKey: "username")
aCoder.encodeObject(self.email, forKey: "email")
} }
//Mark: NSObject //Mark: NSObject
@ -47,7 +51,8 @@ class FriendData: NSObject, NSCoding {
return self.displayName == object.displayName return self.displayName == object.displayName
&& self.profileImg == object.profileImg && self.profileImg == object.profileImg
&& self.status == object.status && self.status == object.status
&& self.username == object.username // && self.username == object.username
&& self.email == object.email
}else { }else {
return false return false
} }

View File

@ -30,12 +30,14 @@ class FriendDataSource{
for object in objects! { for object in objects! {
//var image:UIImage = UIImage() //var image:UIImage = UIImage()
let userName = object.objectForKey("OtherUser")!.objectForKey("username") as! String let email = object.objectForKey("OtherUser")!.objectForKey("email") as! String
println(email)
let displayName = object.objectForKey("OtherUser")!.objectForKey("displayName") as! String let displayName = object.objectForKey("OtherUser")!.objectForKey("displayName") as! String
let requestStatus = object.objectForKey("RequestStatus")! as! String let requestStatus = object.objectForKey("RequestStatus")! as! String
var newFriend: FriendData = FriendData(display: displayName, status: requestStatus, username: userName )
var newFriend: FriendData = FriendData(display: displayName, status: requestStatus, email: email )
var img = object.objectForKey("OtherUser")!.objectForKey("profilePicture")! as? PFFile var img = object.objectForKey("OtherUser")!.objectForKey("profilePicture")! as? PFFile
@ -49,7 +51,7 @@ class FriendDataSource{
}) })
//print(userName) //print(userName)
self.dataSource.append(newFriend) self.dataSource.append(newFriend)
println(self.dataSource.count)
} }
NSLog("%d", self.dataSource.count) NSLog("%d", self.dataSource.count)
@ -65,10 +67,11 @@ class FriendDataSource{
if (error == nil){ if (error == nil){
for object in objects! { for object in objects! {
let userName = object.objectForKey("OtherUser")!.objectForKey("username") as! String let email = object.objectForKey("OtherUser")!.objectForKey("email") as! String
println(email)
let displayName = object.objectForKey("OtherUser")!.objectForKey("displayName") as! String let displayName = object.objectForKey("OtherUser")!.objectForKey("displayName") as! String
let requestStatus = object.objectForKey("RequestStatus")! as! String let requestStatus = object.objectForKey("RequestStatus")! as! String
var newFriend: FriendData = FriendData(display: displayName, status: requestStatus, username: userName) var newFriend: FriendData = FriendData(display: displayName, status: requestStatus, email: email)
var img = object.objectForKey("OtherUser")!.objectForKey("profilePicture")! as? PFFile var img = object.objectForKey("OtherUser")!.objectForKey("profilePicture")! as? PFFile
@ -84,6 +87,7 @@ class FriendDataSource{
//print(userName) //print(userName)
self.dataSource.append(newFriend) self.dataSource.append(newFriend)
println(self.dataSource.count)
} }
NSNotificationCenter.defaultCenter().postNotificationName("refreshTableView", object: nil) NSNotificationCenter.defaultCenter().postNotificationName("refreshTableView", object: nil)

View File

@ -9,8 +9,8 @@
import UIKit import UIKit
class FriendRequestViewController: UIViewController{ class FriendRequestViewController: UIViewController{
var searchedUsername: String! var searchedEmail: String! //contains the searched email address by user
var frnds: [String]! var frnds: [String]! //holds email addresses of current users friends
var party: PartyServiceManager! var party: PartyServiceManager!
@IBOutlet var displayImage: UIImageView! @IBOutlet var displayImage: UIImageView!
@ -20,7 +20,7 @@ class FriendRequestViewController: UIViewController{
@IBAction func sendButtonClicked(sender: AnyObject){ @IBAction func sendButtonClicked(sender: AnyObject){
var query = PFQuery(className: "_User") var query = PFQuery(className: "_User")
query.whereKey("username", equalTo: foundName.text!) query.whereKey("username", equalTo: self.searchedEmail!)
dispatch_async(dispatch_get_main_queue(),{ dispatch_async(dispatch_get_main_queue(),{
query.getFirstObjectInBackgroundWithBlock({ query.getFirstObjectInBackgroundWithBlock({
(object:PFObject?, error: NSError?) -> Void in (object:PFObject?, error: NSError?) -> Void in
@ -135,49 +135,88 @@ extension FriendRequestViewController: UITextFieldDelegate{
} }
func textFieldDidEndEditing(textField: UITextField) { func textFieldDidEndEditing(textField: UITextField) {
self.searchedUsername = searchBar.text
var inFriendsList: Bool = false var inFriendsList: Bool = false
for name in self.frnds{
if name == self.searchedUsername{
inFriendsList = true
break
}
}
if(inFriendsList == false){
var query = PFQuery(className: "_User")
query.whereKey("username", equalTo: searchedUsername)
dispatch_async(dispatch_get_main_queue(), {() -> Void in //case where user display name is entered
query.getFirstObjectInBackgroundWithBlock({ self.searchedEmail = searchBar.text
(object: PFObject?, error: NSError?) -> Void in
if(error == nil){ for email in self.frnds{
self.foundName.text = object?.objectForKey("username") as? String if email == self.searchedEmail{
inFriendsList = true
break
}
}
if(self.searchedEmail == (self.tabBarController as! HomeTabController).userData[0].email){
let alert = UIAlertController(title: "That's You!", message: "Sorry, you can't send a request to yourself.", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)}))
self.presentViewController(alert, animated: true, completion: nil)
}
else if(inFriendsList == false){
var checkRelation: PFRelation! = PFUser.currentUser()?.relationForKey("FriendRequest")
var checkQuery = checkRelation.query().whereKey("RequestStatus", equalTo: "Awaiting Response")
checkQuery.whereKey("inRealtionTo", equalTo: self.searchedEmail)
dispatch_async(dispatch_get_main_queue(), {() -> Void in
checkQuery.getFirstObjectInBackgroundWithBlock({
(object, error) -> Void in
//download profile imge //put in the checking code after lab today
var img = object!.objectForKey("profilePicture")! as? PFFile if object == nil {
var query = PFQuery(className: "_User")
dispatch_async(dispatch_get_main_queue(), { query.whereKey("username", equalTo: self.searchedEmail)
img!.getDataInBackgroundWithBlock({
(imgData, error) -> Void in dispatch_async(dispatch_get_main_queue(), {() -> Void in
query.getFirstObjectInBackgroundWithBlock({
var downloadedImg = UIImage(data: imgData!) (object: PFObject?, error: NSError?) -> Void in
self.displayImage.image = downloadedImg if(error == nil){
self.foundName.text = object?.objectForKey("displayName") as? String
//download profile imge
var img = object!.objectForKey("profilePicture")! as? PFFile
dispatch_async(dispatch_get_main_queue(), {
img!.getDataInBackgroundWithBlock({
(imgData, error) -> Void in
var downloadedImg = UIImage(data: imgData!)
self.displayImage.image = downloadedImg
})
})
self.sendRequest.enabled = true
}else{
self.foundName.text = "No Friend Found :("
self.sendRequest.enabled = false
}
})
}) })
})
}else{
let alert = UIAlertController(title: "Request Already Made", message: "You have already sent a friend request to this user.", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)}))
self.presentViewController(alert, animated: true, completion: nil)
}
self.sendRequest.enabled = true })
}else{
self.foundName.text = "No Friend Found :("
self.sendRequest.enabled = false
}
}) })
})
}else{ }else{
let alert = UIAlertController(title: "Already Friends", message: "You are already friends with this user!", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)})) let alert = UIAlertController(title: "Already Friends", message: "You are already friends with this user!", preferredStyle: .Alert)
self.presentViewController(alert, animated: true, completion: nil) alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)}))
} self.presentViewController(alert, animated: true, completion: nil)
}
} }

View File

@ -30,6 +30,17 @@ class FriendsListViewController: UIViewController, UITableViewDelegate, UITableV
self.performSegueWithIdentifier("FriendRequestSegue", sender: nil) self.performSegueWithIdentifier("FriendRequestSegue", sender: nil)
} }
@IBAction func reloadList(sender: UIBarButtonItem){
NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshFriends:", name: "reloadDataF", object: nil)
(self.tabBarController as! HomeTabController).reloadParseData()
}
func refreshFriends(notification: NSNotification){
self.viewDidLoad()
self.table.reloadData()
NSNotificationCenter.defaultCenter().removeObserver(self, name: "reloadDataF", object: nil)
}
func setData(frnds:[FriendData], requst: [FriendData], party: PartyServiceManager, user: [UserParseData]){ func setData(frnds:[FriendData], requst: [FriendData], party: PartyServiceManager, user: [UserParseData]){
self.friends = frnds self.friends = frnds
self.request = requst self.request = requst
@ -181,8 +192,8 @@ class FriendsListViewController: UIViewController, UITableViewDelegate, UITableV
if (self.friends.count != 0){ if (self.friends.count != 0){
for i in 0...self.friends.count-1{ for i in 0...self.friends.count-1{
var frends: FriendData! = self.friends[i] as! FriendData var frends: FriendData! = self.friends[i] as! FriendData
println(frends.displayName!) println(frends.email!)
frndNames.append(frends.displayName!) frndNames.append(frends.email!)
} }
} }

View File

@ -17,6 +17,7 @@ class HomeTabController: UITabBarController {
var userData: [UserParseData] = [] var userData: [UserParseData] = []
let partyData = PartyServiceManager() let partyData = PartyServiceManager()
var firstTime: Bool = true var firstTime: Bool = true
private var reloadingData: Bool = false
private var firstTimeBrowsing: Bool = true private var firstTimeBrowsing: Bool = true
//@IBOutlet weak var CreateAPartyBtn: UIButton! //@IBOutlet weak var CreateAPartyBtn: UIButton!
@ -33,17 +34,22 @@ class HomeTabController: UITabBarController {
self.friendData.append(pendingFriend) self.friendData.append(pendingFriend)
} }
} }
if(firstTime == true){
//start browsing for peers
self.partyData.setBrowser()
self.partyData.startBrowser()
//self.partyData.delegate = self
self.firstTime = false
}
//start browsing for peers
self.partyData.setBrowser()
self.partyData.startBrowser()
//self.partyData.delegate = self
self.firstTime = false
NSNotificationCenter.defaultCenter().postNotificationName("dataMark", object: nil) NSNotificationCenter.defaultCenter().postNotificationName("dataMark", object: nil)
if(self.reloadingData == true){
NSNotificationCenter.defaultCenter().postNotificationName("reloadDataF", object: nil)
NSNotificationCenter.defaultCenter().postNotificationName("reloadDataS", object: nil)
self.reloadingData = false
}
} }
func refreshUserData(notification:NSNotification){ func refreshUserData(notification:NSNotification){
@ -91,6 +97,20 @@ class HomeTabController: UITabBarController {
self.userData = [] self.userData = []
self.friendData = [] self.friendData = []
self.requestData = []
dispatch_async(dispatch_get_main_queue(), {
self.usrDataManager = UserParseDataSource()
//self.frndDataManager = FriendDataSource()
})
}
//Parse data refresh methods
func reloadParseData(){
self.reloadingData = true
self.userData = []
self.friendData = []
self.requestData = []
dispatch_async(dispatch_get_main_queue(), { dispatch_async(dispatch_get_main_queue(), {
self.usrDataManager = UserParseDataSource() self.usrDataManager = UserParseDataSource()
//self.frndDataManager = FriendDataSource() //self.frndDataManager = FriendDataSource()

View File

@ -37,13 +37,13 @@ class InvitedToPartyViewController: UIViewController , PartyServiceManagerDelega
// Do any additional setup after loading the view. // Do any additional setup after loading the view.
var query = PFQuery(className: "_User") var query = PFQuery(className: "_User")
query.whereKey("username", equalTo: self.fromPeer.displayName) query.whereKey("displayName", equalTo: self.fromPeer.displayName)
dispatch_async(dispatch_get_main_queue(), {() -> Void in dispatch_async(dispatch_get_main_queue(), {() -> Void in
query.getFirstObjectInBackgroundWithBlock({ query.getFirstObjectInBackgroundWithBlock({
(object: PFObject?, error: NSError?) -> Void in (object: PFObject?, error: NSError?) -> Void in
if(error == nil){ if(error == nil){
self.inviteTxt.text = "You have been invited by " + (object?.objectForKey("username")! as? String)! + " to join a Party!" self.inviteTxt.text = "You have been invited by " + (object?.objectForKey("displayName")! as? String)! + " to join a Party!"
//download profile imge //download profile imge
var img = object!.objectForKey("profilePicture")! as? PFFile var img = object!.objectForKey("profilePicture")! as? PFFile

View File

@ -144,7 +144,7 @@ class LoadingPartyViewController: UIViewController, UICollectionViewDataSource,
} }
} }
} }
var userDat = FriendData(display: self.usr[0].displayName, status: "", username: self.usr[0].username) var userDat = FriendData(display: self.usr[0].displayName, status: "", email: self.usr[0].email)
userDat.profileImg = UIImageView(image: self.usr[0].profileImg.image) userDat.profileImg = UIImageView(image: self.usr[0].profileImg.image)
currentlyConnected.append(userDat) currentlyConnected.append(userDat)

View File

@ -29,7 +29,7 @@ class LoginController: UIViewController, PFLogInViewControllerDelegate, UITextFi
(object, error) -> Void in (object, error) -> Void in
if(object != nil && error == nil){ if(object != nil && error == nil){
PFUser.logInWithUsernameInBackground(object!.objectForKey("username") as! String, password: self.password.text!, block: { PFUser.logInWithUsernameInBackground(object!.objectForKey("email") as! String, password: self.password.text!, block: {
(user, error) -> Void in (user, error) -> Void in
if(user != nil || error == nil){ if(user != nil || error == nil){
@ -56,7 +56,7 @@ class LoginController: UIViewController, PFLogInViewControllerDelegate, UITextFi
}) })
}) })
}else{ }else{
let alert = UIAlertController(title: "Invalid Login", message: "Invalid email or password", preferredStyle: .Alert) var alert = UIAlertController(title: "Invalid Login", message: "Invalid email or password", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)})) alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)}))
self.presentViewController(alert, animated: true, completion: nil) self.presentViewController(alert, animated: true, completion: nil)
/* /*

View File

@ -129,6 +129,7 @@
<outlet property="userEmailField" destination="gFr-9c-756" id="xPA-UK-gem"/> <outlet property="userEmailField" destination="gFr-9c-756" id="xPA-UK-gem"/>
<segue destination="CzG-yI-Fm4" kind="show" identifier="signUpSegue" id="5eZ-Bl-cuD"/> <segue destination="CzG-yI-Fm4" kind="show" identifier="signUpSegue" id="5eZ-Bl-cuD"/>
<segue destination="MML-b6-w6u" kind="show" identifier="LoginToHomeSegue" id="OLY-AZ-xl6"/> <segue destination="MML-b6-w6u" kind="show" identifier="LoginToHomeSegue" id="OLY-AZ-xl6"/>
<segue destination="B3S-yT-K9Q" kind="show" identifier="ForgotPassSegue" id="jZ2-Lm-JTd"/>
</connections> </connections>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="6qe-4m-7Cy" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="6qe-4m-7Cy" userLabel="First Responder" sceneMemberID="firstResponder"/>
@ -148,7 +149,7 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/> <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8lW-PH-WAb"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8lW-PH-WAb">
<rect key="frame" x="0.0" y="533" width="320" height="35"/> <rect key="frame" x="0.0" y="533" width="320" height="35"/>
<color key="backgroundColor" red="0.097259112270000003" green="0.60830058499999995" blue="1" alpha="1" colorSpace="calibratedRGB"/> <color key="backgroundColor" red="0.097259112270000003" green="0.60830058499999995" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<constraints> <constraints>
@ -161,10 +162,10 @@
<action selector="saveNewProfile:" destination="dsv-bM-qgc" eventType="touchUpInside" id="NQ8-4Y-OtT"/> <action selector="saveNewProfile:" destination="dsv-bM-qgc" eventType="touchUpInside" id="NQ8-4Y-OtT"/>
</connections> </connections>
</button> </button>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" misplaced="YES" bounces="NO" translatesAutoresizingMaskIntoConstraints="NO" id="B5E-KO-Yxe"> <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" misplaced="YES" bounces="NO" translatesAutoresizingMaskIntoConstraints="NO" id="B5E-KO-Yxe">
<rect key="frame" x="0.0" y="64" width="320" height="533"/> <rect key="frame" x="0.0" y="64" width="320" height="533"/>
<subviews> <subviews>
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ify-XA-8uy"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ify-XA-8uy">
<rect key="frame" x="70" y="248" width="180" height="30"/> <rect key="frame" x="70" y="248" width="180" height="30"/>
<constraints> <constraints>
<constraint firstAttribute="width" secondItem="Ify-XA-8uy" secondAttribute="height" multiplier="6:1" id="1SL-2w-vwy"/> <constraint firstAttribute="width" secondItem="Ify-XA-8uy" secondAttribute="height" multiplier="6:1" id="1SL-2w-vwy"/>
@ -178,32 +179,14 @@
<action selector="chngePhoto:" destination="dsv-bM-qgc" eventType="touchUpInside" id="YSc-B1-dfo"/> <action selector="chngePhoto:" destination="dsv-bM-qgc" eventType="touchUpInside" id="YSc-B1-dfo"/>
</connections> </connections>
</button> </button>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Password" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="epf-V1-rcM"> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Password" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="epf-V1-rcM">
<rect key="frame" x="16" y="417" width="288" height="30"/> <rect key="frame" x="16" y="411" width="288" height="30"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits"/> <textInputTraits key="textInputTraits" secureTextEntry="YES"/>
</textField> </textField>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Email" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="TZI-98-3nh"> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Email" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="TZI-98-3nh">
<rect key="frame" x="16" y="379" width="288" height="30"/> <rect key="frame" x="16" y="357" width="288" height="30"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits"/>
</textField>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Username" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="wbB-YU-CFd">
<rect key="frame" x="16" y="341" width="288" height="30"/>
<constraints>
<constraint firstAttribute="width" secondItem="wbB-YU-CFd" secondAttribute="height" multiplier="32:3" id="2MB-BQ-5t6"/>
</constraints>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits"/>
</textField>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Name" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="t1a-J1-BHH">
<rect key="frame" x="16" y="303" width="288" height="30"/>
<constraints>
<constraint firstAttribute="width" secondItem="t1a-J1-BHH" secondAttribute="height" multiplier="32:3" id="0uZ-Nb-Nyu"/>
</constraints>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits"/> <textInputTraits key="textInputTraits"/>
@ -214,26 +197,34 @@
<constraint firstAttribute="width" secondItem="sAc-4h-398" secondAttribute="height" multiplier="1:1" id="SQw-gH-hIZ"/> <constraint firstAttribute="width" secondItem="sAc-4h-398" secondAttribute="height" multiplier="1:1" id="SQw-gH-hIZ"/>
</constraints> </constraints>
</imageView> </imageView>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Name" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="t1a-J1-BHH">
<rect key="frame" x="16" y="303" width="288" height="30"/>
<constraints>
<constraint firstAttribute="width" secondItem="t1a-J1-BHH" secondAttribute="height" multiplier="32:3" constant="-32" id="0uZ-Nb-Nyu"/>
</constraints>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits"/>
</textField>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstItem="epf-V1-rcM" firstAttribute="top" secondItem="TZI-98-3nh" secondAttribute="bottom" constant="8" symbolic="YES" id="5RJ-dV-boL"/> <constraint firstItem="epf-V1-rcM" firstAttribute="top" secondItem="TZI-98-3nh" secondAttribute="bottom" constant="24" id="5RJ-dV-boL"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="centerX" secondItem="Ify-XA-8uy" secondAttribute="centerX" id="EK4-t8-jCX"/> <constraint firstItem="t1a-J1-BHH" firstAttribute="centerX" secondItem="sAc-4h-398" secondAttribute="centerX" id="6ES-i5-J94"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="centerX" secondItem="B5E-KO-Yxe" secondAttribute="centerX" id="LdE-up-ylo"/> <constraint firstItem="t1a-J1-BHH" firstAttribute="centerX" secondItem="Ify-XA-8uy" secondAttribute="centerX" id="7L7-J2-evb"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="leading" secondItem="B5E-KO-Yxe" secondAttribute="leading" constant="16" id="Lii-LT-TJq"/> <constraint firstAttribute="bottom" secondItem="t1a-J1-BHH" secondAttribute="bottom" constant="200" id="Q5p-kt-yDM"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="leading" secondItem="epf-V1-rcM" secondAttribute="leading" id="QRl-lO-pO6"/> <constraint firstItem="t1a-J1-BHH" firstAttribute="leading" secondItem="TZI-98-3nh" secondAttribute="leading" id="TOW-Bj-nyc"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="trailing" secondItem="t1a-J1-BHH" secondAttribute="trailing" id="T2J-Ng-o0i"/> <constraint firstItem="t1a-J1-BHH" firstAttribute="top" secondItem="B5E-KO-Yxe" secondAttribute="top" constant="303" id="beu-xk-wVu"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="trailing" secondItem="TZI-98-3nh" secondAttribute="trailing" id="f06-W4-muf"/> <constraint firstAttribute="trailing" secondItem="t1a-J1-BHH" secondAttribute="trailing" constant="16" id="foz-bT-Pg0"/>
<constraint firstItem="t1a-J1-BHH" firstAttribute="trailing" secondItem="epf-V1-rcM" secondAttribute="trailing" id="gM3-1R-7lN"/>
<constraint firstItem="t1a-J1-BHH" firstAttribute="leading" secondItem="B5E-KO-Yxe" secondAttribute="leading" constant="16" id="gWF-YO-MTB"/>
<constraint firstItem="Ify-XA-8uy" firstAttribute="top" secondItem="sAc-4h-398" secondAttribute="bottom" constant="8" symbolic="YES" id="haj-F9-T5W"/> <constraint firstItem="Ify-XA-8uy" firstAttribute="top" secondItem="sAc-4h-398" secondAttribute="bottom" constant="8" symbolic="YES" id="haj-F9-T5W"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="trailing" secondItem="epf-V1-rcM" secondAttribute="trailing" id="ibk-tH-GfB"/> <constraint firstItem="t1a-J1-BHH" firstAttribute="top" secondItem="Ify-XA-8uy" secondAttribute="bottom" constant="25" id="jPN-6Q-i51"/>
<constraint firstAttribute="bottom" secondItem="wbB-YU-CFd" secondAttribute="bottom" constant="133" id="iti-Rp-9Q2"/>
<constraint firstItem="TZI-98-3nh" firstAttribute="top" secondItem="wbB-YU-CFd" secondAttribute="bottom" constant="8" symbolic="YES" id="kfy-2D-xV8"/>
<constraint firstItem="sAc-4h-398" firstAttribute="leading" secondItem="B5E-KO-Yxe" secondAttribute="leading" constant="85" id="mjn-BE-a4S"/> <constraint firstItem="sAc-4h-398" firstAttribute="leading" secondItem="B5E-KO-Yxe" secondAttribute="leading" constant="85" id="mjn-BE-a4S"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="leading" secondItem="TZI-98-3nh" secondAttribute="leading" id="naG-L3-oth"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="top" secondItem="t1a-J1-BHH" secondAttribute="bottom" constant="8" symbolic="YES" id="pEv-lF-0al"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="centerX" secondItem="sAc-4h-398" secondAttribute="centerX" id="rJv-zc-oX5"/>
<constraint firstItem="wbB-YU-CFd" firstAttribute="top" secondItem="B5E-KO-Yxe" secondAttribute="top" constant="341" id="sHO-ag-bTv"/>
<constraint firstItem="sAc-4h-398" firstAttribute="top" secondItem="B5E-KO-Yxe" secondAttribute="top" constant="90" id="tSU-om-RR7"/> <constraint firstItem="sAc-4h-398" firstAttribute="top" secondItem="B5E-KO-Yxe" secondAttribute="top" constant="90" id="tSU-om-RR7"/>
<constraint firstItem="epf-V1-rcM" firstAttribute="leading" secondItem="t1a-J1-BHH" secondAttribute="leading" id="utR-jT-sgQ"/> <constraint firstItem="epf-V1-rcM" firstAttribute="leading" secondItem="t1a-J1-BHH" secondAttribute="leading" id="utR-jT-sgQ"/>
<constraint firstItem="TZI-98-3nh" firstAttribute="top" secondItem="t1a-J1-BHH" secondAttribute="bottom" constant="24" id="wPT-oF-cle"/>
<constraint firstItem="t1a-J1-BHH" firstAttribute="trailing" secondItem="TZI-98-3nh" secondAttribute="trailing" id="zJp-nv-wEJ"/>
<constraint firstItem="t1a-J1-BHH" firstAttribute="centerX" secondItem="B5E-KO-Yxe" secondAttribute="centerX" id="zym-cm-DS1"/>
</constraints> </constraints>
<userDefinedRuntimeAttributes> <userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="size" keyPath="contentSize"> <userDefinedRuntimeAttribute type="size" keyPath="contentSize">
@ -245,9 +236,12 @@
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<gestureRecognizers/> <gestureRecognizers/>
<constraints> <constraints>
<constraint firstItem="8lW-PH-WAb" firstAttribute="leading" secondItem="B5E-KO-Yxe" secondAttribute="leading" id="APm-hD-EfK"/>
<constraint firstItem="8lW-PH-WAb" firstAttribute="trailing" secondItem="B5E-KO-Yxe" secondAttribute="trailing" id="J63-sb-wyG"/>
<constraint firstAttribute="trailing" secondItem="B5E-KO-Yxe" secondAttribute="trailing" id="QQH-87-7SW"/> <constraint firstAttribute="trailing" secondItem="B5E-KO-Yxe" secondAttribute="trailing" id="QQH-87-7SW"/>
<constraint firstItem="B5E-KO-Yxe" firstAttribute="leading" secondItem="ZUX-lP-V5A" secondAttribute="leading" id="dfk-eg-tLF"/> <constraint firstItem="B5E-KO-Yxe" firstAttribute="leading" secondItem="ZUX-lP-V5A" secondAttribute="leading" id="dfk-eg-tLF"/>
<constraint firstItem="B5E-KO-Yxe" firstAttribute="top" secondItem="BqE-PA-y7k" secondAttribute="bottom" id="ghm-79-99I"/> <constraint firstItem="B5E-KO-Yxe" firstAttribute="top" secondItem="BqE-PA-y7k" secondAttribute="bottom" id="ghm-79-99I"/>
<constraint firstItem="8lW-PH-WAb" firstAttribute="bottom" secondItem="d3F-vg-2MJ" secondAttribute="top" id="lr7-n5-KRz"/>
<constraint firstItem="d3F-vg-2MJ" firstAttribute="top" secondItem="B5E-KO-Yxe" secondAttribute="bottom" id="roc-Zy-auE"/> <constraint firstItem="d3F-vg-2MJ" firstAttribute="top" secondItem="B5E-KO-Yxe" secondAttribute="bottom" id="roc-Zy-auE"/>
</constraints> </constraints>
<connections> <connections>
@ -272,7 +266,6 @@
<outlet property="profilePic" destination="sAc-4h-398" id="rlt-kj-GBV"/> <outlet property="profilePic" destination="sAc-4h-398" id="rlt-kj-GBV"/>
<outlet property="saveBtn" destination="8lW-PH-WAb" id="7lt-lh-9gs"/> <outlet property="saveBtn" destination="8lW-PH-WAb" id="7lt-lh-9gs"/>
<outlet property="scrollView" destination="B5E-KO-Yxe" id="Z6y-0w-ugI"/> <outlet property="scrollView" destination="B5E-KO-Yxe" id="Z6y-0w-ugI"/>
<outlet property="userField" destination="wbB-YU-CFd" id="rQn-dc-zWM"/>
<segue destination="i3K-xv-zw1" kind="modal" identifier="SignedUpSegue" id="4Cw-Wg-nXy"/> <segue destination="i3K-xv-zw1" kind="modal" identifier="SignedUpSegue" id="4Cw-Wg-nXy"/>
</connections> </connections>
</viewController> </viewController>
@ -614,13 +607,7 @@
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="0aX-nL-3Yl" id="pEH-Wf-32b"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="0aX-nL-3Yl" id="pEH-Wf-32b">
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="SGy-7j-oTR"> <button opaque="NO" contentMode="scaleToFill" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="u49-z7-QQX">
<rect key="frame" x="20" y="7" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" secondItem="SGy-7j-oTR" secondAttribute="height" multiplier="1:1" id="4zV-QW-CvE"/>
</constraints>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="u49-z7-QQX">
<rect key="frame" x="266" y="17" width="28" height="28"/> <rect key="frame" x="266" y="17" width="28" height="28"/>
<constraints> <constraints>
<constraint firstAttribute="width" secondItem="u49-z7-QQX" secondAttribute="height" multiplier="1:1" id="Tsq-hj-hPI"/> <constraint firstAttribute="width" secondItem="u49-z7-QQX" secondAttribute="height" multiplier="1:1" id="Tsq-hj-hPI"/>
@ -632,11 +619,8 @@
<action selector="didAcceptFriend:" destination="Rnb-lz-mp4" eventType="touchUpInside" id="Tdz-pW-bEv"/> <action selector="didAcceptFriend:" destination="Rnb-lz-mp4" eventType="touchUpInside" id="Tdz-pW-bEv"/>
</connections> </connections>
</button> </button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VKQ-62-km5"> <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VKQ-62-km5">
<rect key="frame" x="181" y="17" width="28" height="28"/> <rect key="frame" x="181" y="17" width="28" height="28"/>
<constraints>
<constraint firstAttribute="width" secondItem="VKQ-62-km5" secondAttribute="height" multiplier="1:1" id="Lfo-li-PtI"/>
</constraints>
<state key="normal" image="Cancel.png"> <state key="normal" image="Cancel.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/> <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state> </state>
@ -644,30 +628,16 @@
<action selector="didRejectFriend:" destination="Rnb-lz-mp4" eventType="touchUpInside" id="cFh-Yk-AUE"/> <action selector="didRejectFriend:" destination="Rnb-lz-mp4" eventType="touchUpInside" id="cFh-Yk-AUE"/>
</connections> </connections>
</button> </button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Username" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J2y-S7-GWi"> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SGy-7j-oTR">
<rect key="frame" x="20" y="7" width="50" height="50"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Username" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J2y-S7-GWi">
<rect key="frame" x="78" y="21" width="234" height="21"/> <rect key="frame" x="78" y="21" width="234" height="21"/>
<constraints>
<constraint firstAttribute="width" secondItem="J2y-S7-GWi" secondAttribute="height" multiplier="78:7" id="mWr-ln-k4F"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
</subviews> </subviews>
<constraints>
<constraint firstAttribute="bottomMargin" secondItem="J2y-S7-GWi" secondAttribute="bottom" constant="14" id="1Gj-Sp-VuN"/>
<constraint firstAttribute="bottomMargin" secondItem="SGy-7j-oTR" secondAttribute="bottom" constant="-1" id="7ae-Hy-MTF"/>
<constraint firstItem="u49-z7-QQX" firstAttribute="leading" secondItem="VKQ-62-km5" secondAttribute="trailing" constant="57" id="Buo-Vq-ROc"/>
<constraint firstItem="J2y-S7-GWi" firstAttribute="leading" secondItem="SGy-7j-oTR" secondAttribute="trailing" constant="8" id="Dke-PT-vGY"/>
<constraint firstAttribute="bottomMargin" secondItem="u49-z7-QQX" secondAttribute="bottom" constant="11" id="FoU-Yk-uER"/>
<constraint firstItem="SGy-7j-oTR" firstAttribute="top" secondItem="pEH-Wf-32b" secondAttribute="topMargin" constant="-1" id="Kdf-Fc-FiD"/>
<constraint firstItem="VKQ-62-km5" firstAttribute="top" secondItem="pEH-Wf-32b" secondAttribute="topMargin" constant="9" id="Sl1-Oa-MYt"/>
<constraint firstItem="J2y-S7-GWi" firstAttribute="top" secondItem="pEH-Wf-32b" secondAttribute="topMargin" constant="13" id="UVW-O0-06a"/>
<constraint firstItem="u49-z7-QQX" firstAttribute="top" secondItem="pEH-Wf-32b" secondAttribute="topMargin" constant="9" id="XtD-uv-8hS"/>
<constraint firstAttribute="trailingMargin" secondItem="u49-z7-QQX" secondAttribute="trailing" constant="18" id="g1Z-H6-hnT"/>
<constraint firstAttribute="bottomMargin" secondItem="VKQ-62-km5" secondAttribute="bottom" constant="11" id="pVs-iE-Sdy"/>
<constraint firstItem="SGy-7j-oTR" firstAttribute="leading" secondItem="pEH-Wf-32b" secondAttribute="leadingMargin" constant="12" id="soz-eK-e6b"/>
</constraints>
</tableViewCellContentView> </tableViewCellContentView>
<connections> <connections>
<outlet property="acceptButton" destination="u49-z7-QQX" id="09O-Sv-ynY"/> <outlet property="acceptButton" destination="u49-z7-QQX" id="09O-Sv-ynY"/>
@ -735,13 +705,29 @@
</navigationBar> </navigationBar>
<connections> <connections>
<segue destination="dsv-bM-qgc" kind="relationship" relationship="rootViewController" id="NSw-6O-EkM"/> <segue destination="dsv-bM-qgc" kind="relationship" relationship="rootViewController" id="NSw-6O-EkM"/>
<segue destination="8Od-AM-nj1" kind="presentation" identifier="ForgotPassSegue" id="soS-fw-yyJ"/>
</connections> </connections>
</navigationController> </navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="mbC-CF-JRB" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="mbC-CF-JRB" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="205" y="1027"/> <point key="canvasLocation" x="205" y="1027"/>
</scene> </scene>
<!--Navigation Controller-->
<scene sceneID="l3M-Bz-Ddl">
<objects>
<navigationController id="B3S-yT-K9Q" sceneMemberID="viewController">
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="dXu-a4-mQL">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="8Od-AM-nj1" kind="relationship" relationship="rootViewController" id="1dr-x0-2Nu"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="IiH-Dr-z9w" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-274" y="1707"/>
</scene>
<!--Forgot Pass View Controller--> <!--Forgot Pass View Controller-->
<scene sceneID="0H6-d7-0mA"> <scene sceneID="0H6-d7-0mA">
<objects> <objects>
@ -753,13 +739,73 @@
<view key="view" contentMode="scaleToFill" id="67T-1a-Dhx"> <view key="view" contentMode="scaleToFill" id="67T-1a-Dhx">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/> <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Email" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="Eu3-dl-Fzu">
<rect key="frame" x="10" y="216" width="288" height="30"/>
<constraints>
<constraint firstAttribute="width" secondItem="Eu3-dl-Fzu" secondAttribute="height" multiplier="32:3" constant="-32" id="VCL-mw-nTg"/>
</constraints>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits"/>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" usesAttributedText="YES" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8UP-4m-htm">
<rect key="frame" x="4" y="187" width="313" height="21"/>
<attributedString key="attributedText">
<fragment content="Provide the email address of the account:">
<attributes>
<font key="NSFont" size="14" name="Helvetica"/>
<font key="NSOriginalFont" size="14" name="Helvetica"/>
<paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
</attributes>
</fragment>
</attributedString>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uO2-vA-7HL">
<rect key="frame" x="59" y="269" width="202" height="30"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="width" secondItem="uO2-vA-7HL" secondAttribute="height" multiplier="101:15" id="sUJ-JO-Up4"/>
</constraints>
<state key="normal" title="Reset Password">
<color key="titleColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="ChnEmailComfirm:" destination="O66-YD-dIP" eventType="touchUpInside" id="ODK-e5-MYq"/>
<action selector="DspBtnConfrim:" destination="CpB-9L-oYx" eventType="touchUpInside" id="Ety-Tl-ps2"/>
<action selector="sendResetRequest:" destination="8Od-AM-nj1" eventType="touchUpInside" id="0ie-h0-Rp2"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<gestureRecognizers/>
<constraints>
<constraint firstItem="uO2-vA-7HL" firstAttribute="width" secondItem="uO2-vA-7HL" secondAttribute="height" multiplier="101:15" id="dcH-8x-yzk"/>
<constraint firstItem="Eu3-dl-Fzu" firstAttribute="width" secondItem="Eu3-dl-Fzu" secondAttribute="height" multiplier="32:3" constant="-32" id="klK-SB-bZn"/>
</constraints>
<connections>
<outletCollection property="gestureRecognizers" destination="odT-J1-h31" appends="YES" id="ekn-gN-1zi"/>
</connections>
</view> </view>
<navigationItem key="navigationItem" id="n6p-Ns-IxC">
<barButtonItem key="leftBarButtonItem" title="Close" id="ue2-Pc-Oa2">
<connections>
<action selector="dismiss:" destination="8Od-AM-nj1" id="Axg-zq-4gY"/>
</connections>
</barButtonItem>
</navigationItem>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/> <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
<connections>
<outlet property="emailField" destination="Eu3-dl-Fzu" id="ksO-E3-ySd"/>
<outlet property="resestPass" destination="uO2-vA-7HL" id="lmS-jj-1ah"/>
</connections>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="HT6-Cr-HH3" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="HT6-Cr-HH3" userLabel="First Responder" sceneMemberID="firstResponder"/>
<tapGestureRecognizer id="odT-J1-h31"/>
</objects> </objects>
<point key="canvasLocation" x="205" y="1837"/> <point key="canvasLocation" x="205" y="1713"/>
</scene> </scene>
<!--Friends--> <!--Friends-->
<scene sceneID="f64-9e-nxp"> <scene sceneID="f64-9e-nxp">
@ -851,6 +897,11 @@
</view> </view>
<tabBarItem key="tabBarItem" title="Friends" image="FriendsTab" id="a0b-Vf-ZtP"/> <tabBarItem key="tabBarItem" title="Friends" image="FriendsTab" id="a0b-Vf-ZtP"/>
<navigationItem key="navigationItem" id="50c-DG-Vcp"> <navigationItem key="navigationItem" id="50c-DG-Vcp">
<barButtonItem key="leftBarButtonItem" systemItem="refresh" id="yTp-pq-c8o">
<connections>
<action selector="reloadList:" destination="Wv2-hP-rqT" id="Jp4-OS-2i4"/>
</connections>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" systemItem="add" id="3QF-Yw-Pq0"> <barButtonItem key="rightBarButtonItem" systemItem="add" id="3QF-Yw-Pq0">
<connections> <connections>
<action selector="addFriend:" destination="Wv2-hP-rqT" id="HtN-NM-NLa"/> <action selector="addFriend:" destination="Wv2-hP-rqT" id="HtN-NM-NLa"/>
@ -907,7 +958,7 @@
<viewControllerLayoutGuide type="bottom" id="nqn-B0-8f9"/> <viewControllerLayoutGuide type="bottom" id="nqn-B0-8f9"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="TKW-IF-c3d"> <view key="view" contentMode="scaleToFill" id="TKW-IF-c3d">
<rect key="frame" x="0.0" y="0.0" width="320" height="519"/> <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="HomeScreenTurnTable" translatesAutoresizingMaskIntoConstraints="NO" id="Ugh-Mp-5Vj"> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="HomeScreenTurnTable" translatesAutoresizingMaskIntoConstraints="NO" id="Ugh-Mp-5Vj">
@ -1101,30 +1152,7 @@
<outlet property="dispName" destination="q7S-sF-r2w" id="Gxy-lk-RdC"/> <outlet property="dispName" destination="q7S-sF-r2w" id="Gxy-lk-RdC"/>
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="UserNameCell" id="q3Z-7M-2bk" customClass="UserNameCell" customModule="GetHip" customModuleProvider="target"> <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="EmailCell" id="hNW-1m-4W0" customClass="EmailCell" customModule="GetHip" customModuleProvider="target">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="q3Z-7M-2bk" id="km5-ox-ec8">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Username" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X6g-ni-EeU">
<rect key="frame" x="15" y="11" width="91" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Username Display" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="87L-ZN-1Ya">
<rect key="frame" x="114" y="11" width="158" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<outlet property="usrName" destination="87L-ZN-1Ya" id="LMA-nT-Gic"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="EmailCell" id="hNW-1m-4W0" customClass="EmailCell" customModule="GetHip" customModuleProvider="target">
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hNW-1m-4W0" id="9Gc-eb-pvb"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hNW-1m-4W0" id="9Gc-eb-pvb">
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
@ -1199,6 +1227,7 @@
<segue destination="O66-YD-dIP" kind="show" identifier="EmailSegue" id="dXF-h4-Qgp"/> <segue destination="O66-YD-dIP" kind="show" identifier="EmailSegue" id="dXF-h4-Qgp"/>
<segue destination="JcU-T3-nLI" kind="show" identifier="PhotoSegue" id="w90-PF-6yk"/> <segue destination="JcU-T3-nLI" kind="show" identifier="PhotoSegue" id="w90-PF-6yk"/>
<segue destination="j0X-k4-h6H" kind="presentation" identifier="LogOutSegue" id="5Ml-AJ-rNB"/> <segue destination="j0X-k4-h6H" kind="presentation" identifier="LogOutSegue" id="5Ml-AJ-rNB"/>
<segue destination="jfk-nm-PpC" kind="show" identifier="ResetPassSegue" id="0o9-1e-Pdd"/>
</connections> </connections>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Qjc-mB-GgZ" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="Qjc-mB-GgZ" userLabel="First Responder" sceneMemberID="firstResponder"/>
@ -1231,11 +1260,11 @@
<viewControllerLayoutGuide type="bottom" id="l3V-w7-kEv"/> <viewControllerLayoutGuide type="bottom" id="l3V-w7-kEv"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="Jzb-Yh-jPx"> <view key="view" contentMode="scaleToFill" id="Jzb-Yh-jPx">
<rect key="frame" x="0.0" y="0.0" width="320" height="519"/> <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="I0x-SG-Vbs"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="I0x-SG-Vbs">
<rect key="frame" x="0.0" y="479" width="320" height="40"/> <rect key="frame" x="0.0" y="528" width="320" height="40"/>
<constraints> <constraints>
<constraint firstAttribute="width" secondItem="I0x-SG-Vbs" secondAttribute="height" multiplier="8:1" id="D3B-IT-RFg"/> <constraint firstAttribute="width" secondItem="I0x-SG-Vbs" secondAttribute="height" multiplier="8:1" id="D3B-IT-RFg"/>
</constraints> </constraints>
@ -1247,13 +1276,13 @@
</connections> </connections>
</button> </button>
<tableView clipsSubviews="YES" contentMode="scaleToFill" ambiguous="YES" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="n64-qL-raO"> <tableView clipsSubviews="YES" contentMode="scaleToFill" ambiguous="YES" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="n64-qL-raO">
<rect key="frame" x="0.0" y="64" width="320" height="416"/> <rect key="frame" x="0.0" y="64" width="348" height="465"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints> <constraints>
<constraint firstAttribute="width" secondItem="n64-qL-raO" secondAttribute="height" multiplier="40:71" constant="85.633802816901408" id="4zb-FR-IKu"/> <constraint firstAttribute="width" secondItem="n64-qL-raO" secondAttribute="height" multiplier="40:71" constant="85.633802816901408" id="4zb-FR-IKu"/>
</constraints> </constraints>
<searchBar key="tableHeaderView" contentMode="redraw" id="fQ0-dw-Xa4"> <searchBar key="tableHeaderView" contentMode="redraw" id="fQ0-dw-Xa4">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/> <rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textInputTraits key="textInputTraits"/> <textInputTraits key="textInputTraits"/>
<connections> <connections>
@ -1911,17 +1940,17 @@
<viewControllerLayoutGuide type="bottom" id="Zss-AJ-MHl"/> <viewControllerLayoutGuide type="bottom" id="Zss-AJ-MHl"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="gPw-6a-U7E"> <view key="view" contentMode="scaleToFill" id="gPw-6a-U7E">
<rect key="frame" x="0.0" y="0.0" width="320" height="519"/> <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="iAI-5U-c8e"> <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="iAI-5U-c8e">
<rect key="frame" x="0.0" y="64" width="289" height="455"/> <rect key="frame" x="0.0" y="64" width="320" height="504"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints> <constraints>
<constraint firstAttribute="width" secondItem="iAI-5U-c8e" secondAttribute="height" multiplier="40:63" id="Ux3-OS-MI8"/> <constraint firstAttribute="width" secondItem="iAI-5U-c8e" secondAttribute="height" multiplier="40:63" id="Ux3-OS-MI8"/>
</constraints> </constraints>
<searchBar key="tableHeaderView" contentMode="redraw" placeholder="Search for a Song!" id="O3K-BF-fFD"> <searchBar key="tableHeaderView" contentMode="redraw" placeholder="Search for a Song!" id="O3K-BF-fFD">
<rect key="frame" x="0.0" y="0.0" width="289" height="44"/> <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textInputTraits key="textInputTraits"/> <textInputTraits key="textInputTraits"/>
<connections> <connections>
@ -2120,12 +2149,12 @@
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="MfD-Wt-UCx" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="MfD-Wt-UCx" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="2804" y="-2509"/> <point key="canvasLocation" x="2804" y="-3189"/>
</scene> </scene>
<!--Email Detail View Controller--> <!--View Controller-->
<scene sceneID="T2i-zb-czf"> <scene sceneID="T2i-zb-czf">
<objects> <objects>
<viewController id="O66-YD-dIP" customClass="EmailDetailViewController" customModule="GetHip" customModuleProvider="target" sceneMemberID="viewController"> <viewController id="O66-YD-dIP" sceneMemberID="viewController">
<layoutGuides> <layoutGuides>
<viewControllerLayoutGuide type="top" id="wjy-ZS-efu"/> <viewControllerLayoutGuide type="top" id="wjy-ZS-efu"/>
<viewControllerLayoutGuide type="bottom" id="xK7-iE-TXj"/> <viewControllerLayoutGuide type="bottom" id="xK7-iE-TXj"/>
@ -2195,7 +2224,65 @@
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="N0P-rt-lqR" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="N0P-rt-lqR" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="2804" y="-1895"/> <point key="canvasLocation" x="2804" y="-2571"/>
</scene>
<!--Reset Pass Detail View Controller-->
<scene sceneID="KZl-45-aS9">
<objects>
<viewController id="jfk-nm-PpC" customClass="ResetPassDetailViewController" customModule="GetHip" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="3TG-dP-x4P"/>
<viewControllerLayoutGuide type="bottom" id="YHW-O3-1cu"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="2yd-eF-hW1">
<rect key="frame" x="0.0" y="0.0" width="320" height="519"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="48l-nw-nWb">
<rect key="frame" x="16" y="134" width="288" height="30"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" enablesReturnKeyAutomatically="YES" secureTextEntry="YES"/>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Current Password:" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ntB-8T-fse">
<rect key="frame" x="66" y="105" width="166" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="New Password:" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="oXC-FW-97W">
<rect key="frame" x="66" y="193" width="166" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EEr-TK-YIC">
<rect key="frame" x="78" y="270" width="142" height="30"/>
<state key="normal" title="Change Password">
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="changePass:" destination="jfk-nm-PpC" eventType="touchUpInside" id="sWd-FJ-ymS"/>
</connections>
</button>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Jfh-MW-AiA">
<rect key="frame" x="16" y="222" width="288" height="30"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" enablesReturnKeyAutomatically="YES" secureTextEntry="YES"/>
</textField>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
<connections>
<outlet property="chgPassBtn" destination="EEr-TK-YIC" id="ipw-j6-hpi"/>
<outlet property="currPass" destination="48l-nw-nWb" id="atn-jn-wyp"/>
<outlet property="newPass" destination="Jfh-MW-AiA" id="SiF-6I-AVE"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="S8c-gN-a4q" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2804" y="-1907"/>
</scene> </scene>
<!--Profile Detail View Controller--> <!--Profile Detail View Controller-->
<scene sceneID="TTR-UC-Ofu"> <scene sceneID="TTR-UC-Ofu">
@ -2234,7 +2321,7 @@
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="CmL-4D-tiY" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="CmL-4D-tiY" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="2804" y="-1281"/> <point key="canvasLocation" x="2804" y="-1261"/>
</scene> </scene>
</scenes> </scenes>
<resources> <resources>
@ -2264,9 +2351,9 @@
<image name="XMark" width="38" height="38"/> <image name="XMark" width="38" height="38"/>
</resources> </resources>
<inferredMetricsTieBreakers> <inferredMetricsTieBreakers>
<segue reference="GFg-ZD-Dub"/> <segue reference="4Cw-Wg-nXy"/>
<segue reference="bZG-mB-VR5"/> <segue reference="e9T-hD-upE"/>
<segue reference="hjX-RT-64R"/> <segue reference="V9M-LI-d3d"/>
<segue reference="3Qh-V2-6Ee"/> <segue reference="3Qh-V2-6Ee"/>
<segue reference="Imp-mG-tFc"/> <segue reference="Imp-mG-tFc"/>
</inferredMetricsTieBreakers> </inferredMetricsTieBreakers>

View File

@ -152,8 +152,8 @@ class PartyServiceManager: NSObject, AnyObject {
} }
for peer in dataDictionary["friendData"] as! [FriendData] { for peer in dataDictionary["friendData"] as! [FriendData] {
if(peer.username != self.myPeerID.displayName){ if(peer.displayName != self.myPeerID.displayName){
println(peer.username) println(peer.displayName)
self.invitedFriends.append(peer) self.invitedFriends.append(peer)
} }
} }

View File

@ -17,11 +17,12 @@ class PendingRequestViewController: UITableViewController {
@IBAction func didAcceptFriend(sender: AnyObject?){ @IBAction func didAcceptFriend(sender: AnyObject?){
var path:NSIndexPath = self.table.indexPathForCell(sender?.superview!!.superview as! PendingFriendCell)! var path:NSIndexPath = self.table.indexPathForCell(sender?.superview!!.superview as! PendingFriendCell)!
var cell: PendingFriendCell! = self.table.cellForRowAtIndexPath(path) as! PendingFriendCell var cell: PendingFriendCell! = self.table.cellForRowAtIndexPath(path) as! PendingFriendCell
let pending = self.requests[path.row] as! FriendData
var query: PFQuery! = PFQuery(className: "FriendRequest") var query: PFQuery! = PFQuery(className: "FriendRequest")
query.whereKey("username", equalTo: PFUser.currentUser()!.username!) query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query.whereKey("RequestStatus", equalTo: "pending") query.whereKey("RequestStatus", equalTo: "pending")
query.whereKey("inRealtionTo", equalTo: cell.friendName.text!) query.whereKey("inRealtionTo", equalTo: pending.email)
query.includeKey("OtherUser") query.includeKey("OtherUser")
dispatch_async(dispatch_get_main_queue(), { dispatch_async(dispatch_get_main_queue(), {
@ -61,7 +62,14 @@ class PendingRequestViewController: UITableViewController {
object!.save() object!.save()
cell.proImg.hidden = true
cell.acceptButton.hidden = true
cell.denyButton.hidden = true
var tempString = cell.friendName.text!
cell.friendName.text = "You added " + tempString + "!!"
NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshFriendList:", name: "reloadDataF", object: nil)
(self.tabBarController as! HomeTabController).reloadParseData()
} }
}) })
}) })
@ -75,18 +83,21 @@ class PendingRequestViewController: UITableViewController {
}) })
}) })
cell.proImg.hidden = true
cell.acceptButton.hidden = true
cell.denyButton.hidden = true
var tempString = cell.friendName.text!
cell.friendName.text = "You added " + tempString + "!!"
//self.table.reloadData()
} }
@IBAction func didRejectFriend(sender: AnyObject?){ @IBAction func didRejectFriend(sender: AnyObject?){
} }
//local refresh method for friend list view controller table
func refreshFriendList(notification: NSNotification){
((self.parentViewController as! UINavigationController).viewControllers[0] as! FriendsListViewController).viewDidLoad()
((self.parentViewController as! UINavigationController).viewControllers[0] as! FriendsListViewController).table.reloadData()
NSNotificationCenter.defaultCenter().removeObserver(self, name: "reloadDataF", object: nil)
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
self.title = "Friend Requests" self.title = "Friend Requests"
@ -144,6 +155,10 @@ class PendingRequestViewController: UITableViewController {
//rounds uiimage and configures UIImageView //rounds uiimage and configures UIImageView
cell!.proImg.layer.cornerRadius = cell!.proImg.frame.size.width/2 cell!.proImg.layer.cornerRadius = cell!.proImg.frame.size.width/2
cell!.acceptButton.layer.cornerRadius = cell!.acceptButton.frame.size.width/2
cell!.denyButton.layer.cornerRadius = cell!.acceptButton.frame.size.width/2
cell!.denyButton.clipsToBounds = true
cell!.acceptButton.clipsToBounds = true
cell!.proImg.clipsToBounds = true cell!.proImg.clipsToBounds = true
//cell!.proImage.layer.borderColor = UIColor.whiteColor().CGColor //cell!.proImage.layer.borderColor = UIColor.whiteColor().CGColor
//cell!.proImage.layer.masksToBounds = true //cell!.proImage.layer.masksToBounds = true

View File

@ -20,6 +20,7 @@ class DisplayNameCell: UITableViewCell {
} }
} }
/*
class UserNameCell: UITableViewCell { class UserNameCell: UITableViewCell {
@IBOutlet var usrName: UILabel! @IBOutlet var usrName: UILabel!
@ -31,6 +32,7 @@ class UserNameCell: UITableViewCell {
super.setSelected(selected, animated: animated) super.setSelected(selected, animated: animated)
} }
} }
*/
class EmailCell: UITableViewCell { class EmailCell: UITableViewCell {
@IBOutlet var email: UILabel! @IBOutlet var email: UILabel!

View File

@ -36,7 +36,9 @@ class DisplayDetailViewController: UIViewController {
else if let object = object{ else if let object = object{
object.setObject(self.possibleName, forKey: "displayName") object.setObject(self.possibleName, forKey: "displayName")
object.saveInBackground() object.saveInBackground()
//NSNotificationCenter.defaultCenter().postNotificationName("savingName", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshSettings:", name: "reloadDataS", object: nil)
(self.tabBarController as! HomeTabController).reloadParseData()
} }
} }
@ -49,10 +51,6 @@ class DisplayDetailViewController: UIViewController {
self.displayName = display self.displayName = display
} }
func refreshView(notification: NSNotification){
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -63,7 +61,7 @@ class DisplayDetailViewController: UIViewController {
self.ChnDspName.layer.cornerRadius = 5 self.ChnDspName.layer.cornerRadius = 5
self.ChnDspName.layer.borderColor = UIColor.blackColor().CGColor self.ChnDspName.layer.borderColor = UIColor.blackColor().CGColor
// Do any additional setup after loading the view. // Do any additional setup after loading the view.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshView:", name: "savingName", object: nil)
} }
override func didReceiveMemoryWarning() { override func didReceiveMemoryWarning() {
@ -71,6 +69,12 @@ class DisplayDetailViewController: UIViewController {
// Dispose of any resources that can be recreated. // Dispose of any resources that can be recreated.
} }
func refreshSettings(notification: NSNotification){
((self.parentViewController as! UINavigationController).viewControllers[0] as! SettingsTableViewController).viewDidLoad()
((self.parentViewController as! UINavigationController).viewControllers[0] as! SettingsTableViewController).table.reloadData()
NSNotificationCenter.defaultCenter().removeObserver(self, name: "reloadDataS", object: nil)
}
@ -85,6 +89,7 @@ class DisplayDetailViewController: UIViewController {
*/ */
} }
/*
class EmailDetailViewController: UIViewController { class EmailDetailViewController: UIViewController {
var possibleEmail: String! var possibleEmail: String!
@ -97,26 +102,31 @@ class EmailDetailViewController: UIViewController {
self.possibleEmail = self.textfield?.text self.possibleEmail = self.textfield?.text
//sanitize and alert for input and success later //sanitize and alert for input and success later
if(contains(self.possibleEmail, "@")){
var query = PFUser.query() var query = PFUser.query()
var currentUser = PFUser.currentUser() var currentUser = PFUser.currentUser()
query!.whereKey("username", equalTo: (currentUser?.username as String!))
query!.getFirstObjectInBackgroundWithBlock {
(object, error) -> Void in
if error != nil || object == nil { query!.whereKey("username", equalTo: (currentUser?.username as String!))
println("Object request failed")
} query!.getFirstObjectInBackgroundWithBlock {
else if let object = object{ (object, error) -> Void in
object.setObject(self.possibleEmail, forKey: "email")
object.saveInBackground() if error != nil || object == nil {
NSNotificationCenter.defaultCenter().postNotificationName("savingEmail", object: nil) println("Object request failed")
}
else if let object = object{
object.setObject(self.possibleEmail, forKey: "email")
object.saveInBackground()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshSettings:", name: "reloadDataS", object: nil)
(self.tabBarController as! HomeTabController).reloadParseData()
}
} }
println(self.possibleEmail)
} }
println(self.possibleEmail)
} }
@ -135,7 +145,7 @@ class EmailDetailViewController: UIViewController {
self.ChnEmailBtn.layer.cornerRadius = 5 self.ChnEmailBtn.layer.cornerRadius = 5
self.ChnEmailBtn.layer.borderColor = UIColor.blackColor().CGColor self.ChnEmailBtn.layer.borderColor = UIColor.blackColor().CGColor
// Do any additional setup after loading the view. // Do any additional setup after loading the view.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshView:", name: "savingEmail", object: nil)
} }
override func didReceiveMemoryWarning() { override func didReceiveMemoryWarning() {
@ -143,8 +153,10 @@ class EmailDetailViewController: UIViewController {
// Dispose of any resources that can be recreated. // Dispose of any resources that can be recreated.
} }
func refreshView(notification: NSNotification){ func refreshSettings(notification: NSNotification){
((self.parentViewController as! UINavigationController).viewControllers[0] as! SettingsTableViewController).viewDidLoad()
((self.parentViewController as! UINavigationController).viewControllers[0] as! SettingsTableViewController).table.reloadData()
NSNotificationCenter.defaultCenter().removeObserver(self, name: "reloadDataS", object: nil)
} }
/* /*
@ -158,6 +170,69 @@ class EmailDetailViewController: UIViewController {
*/ */
} }
*/
class ResetPassDetailViewController: UIViewController {
@IBOutlet weak var currPass: UITextField!
@IBOutlet weak var newPass: UITextField!
@IBOutlet weak var chgPassBtn: UIButton!
@IBAction func changePass(sender: UIButton){
PFUser.logInWithUsernameInBackground(self.email, password: self.currPass.text! ) {
(user, error) -> Void in
if error == nil {
var query = PFUser.query()
query!.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query?.findObjectsInBackgroundWithBlock({
(objects, error) -> Void in
for object in objects! {
var obj: PFObject = object as! PFObject
obj.setObject(self.newPass.text!, forKey: "password")
obj.save()
let alert = UIAlertController(title: "Password Changed", message: "Your password has been updated", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)}))
self.presentViewController(alert, animated: true, completion: nil)
}
})
} else {
let alert = UIAlertController(title: "Incorrect Password", message: "The password you gave as your current password was incorrect. Please enter the correct password.", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)}))
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
var email: String!
func setData(email: String){
self.email = email
}
override func viewDidLoad() {
super.viewDidLoad()
//rounded border for button
self.chgPassBtn.layer.borderWidth = 1
self.chgPassBtn.layer.cornerRadius = 5
self.chgPassBtn.layer.borderColor = UIColor.blackColor().CGColor
}
}
class ProfileDetailViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate { class ProfileDetailViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
var profileImg: UIImageView! var profileImg: UIImageView!
@ -244,6 +319,31 @@ extension ProfileDetailViewController: UIImagePickerControllerDelegate{
//MARK: -Image Picker Delegate //MARK: -Image Picker Delegate
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) { func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
var img:PFFile = PFFile(data: UIImageJPEGRepresentation(image, 1.0))!
var query = PFUser.query()
var currentUser = PFUser.currentUser()
query!.whereKey("username", equalTo: (currentUser?.username as String!))
query!.getFirstObjectInBackgroundWithBlock {
(object, error) -> Void in
if error != nil || object == nil {
println("Object request failed")
}
else if let object = object{
object.setObject(img, forKey: "profilePicture")
object.saveInBackground()
//NSNotificationCenter.defaultCenter().postNotificationName("", object: nil)
}
}
self.img.image = image
var homeController = self.tabBarController as? HomeTabController
homeController?.userData[0].profileImg.image = image
dismissViewControllerAnimated(true, completion: nil)
} }
func imagePickerControllerDidCancel(picker: UIImagePickerController) { func imagePickerControllerDidCancel(picker: UIImagePickerController) {

View File

@ -68,7 +68,7 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
self.navigationController?.navigationBarHidden = false self.navigationController?.navigationBarHidden = false
self.table.tableFooterView = UIView(frame: CGRectZero) self.table.tableFooterView = UIView(frame: CGRectZero)
self.party.delegate = self self.party.delegate = self
//NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshTable:", name: "refreshSettingsView", object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshTable:", name: "refreshSettingsView", object: nil)
self.table.reloadData() self.table.reloadData()
// Uncomment the following line to preserve selection between presentations // Uncomment the following line to preserve selection between presentations
@ -96,7 +96,7 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation. // #warning Incomplete method implementation.
// Return the number of rows in the section. // Return the number of rows in the section.
return 5 return 4
} }
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
@ -110,7 +110,7 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
} }
return cell return cell
/*
case 1: case 1:
let cell = (self.table.dequeueReusableCellWithIdentifier("UserNameCell", forIndexPath: indexPath) as? UserNameCell)! let cell = (self.table.dequeueReusableCellWithIdentifier("UserNameCell", forIndexPath: indexPath) as? UserNameCell)!
@ -119,8 +119,8 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
} }
return cell return cell
*/
case 2: case 1:
let cell = (self.table.dequeueReusableCellWithIdentifier("EmailCell", forIndexPath: indexPath) as? EmailCell)! let cell = (self.table.dequeueReusableCellWithIdentifier("EmailCell", forIndexPath: indexPath) as? EmailCell)!
if self.user.count > 0 { if self.user.count > 0 {
@ -128,7 +128,7 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
} }
return cell return cell
case 3: case 2:
let cell = (self.table.dequeueReusableCellWithIdentifier("PassCell", forIndexPath: indexPath) as? ResetPassCell)! let cell = (self.table.dequeueReusableCellWithIdentifier("PassCell", forIndexPath: indexPath) as? ResetPassCell)!
if self.user.count > 0 { if self.user.count > 0 {
@ -139,10 +139,6 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
default: default:
let cell = (self.table.dequeueReusableCellWithIdentifier("PictureCell", forIndexPath: indexPath) as? ProfilePicCell)! let cell = (self.table.dequeueReusableCellWithIdentifier("PictureCell", forIndexPath: indexPath) as? ProfilePicCell)!
if self.user.count > 0 {
}
return cell return cell
} }
@ -161,6 +157,7 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
} }
//user name view //user name view
/*
case 1: case 1:
if self.user.count > 0 { if self.user.count > 0 {
@ -169,19 +166,21 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
} }
break break
*/
//email view //email view
case 2: case 1:
break
/*
if self.user.count > 0 { if self.user.count > 0 {
self.performSegueWithIdentifier("EmailSegue", sender: nil) self.performSegueWithIdentifier("EmailSegue", sender: nil)
} }
*/
//reset pass //reset pass
case 3: case 2:
if self.user.count > 0 { if self.user.count > 0 {
self.performSegueWithIdentifier("ResetPassSegue", sender: nil)
} }
break break
@ -210,20 +209,24 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
} }
//email view //email view
case 2: case 1:
break
/*
if self.user.count > 0 { if self.user.count > 0 {
let vc: EmailDetailViewController = (segue.destinationViewController as? EmailDetailViewController)! let vc: EmailDetailViewController = (segue.destinationViewController as? EmailDetailViewController)!
vc.setData((self.user[0] as? UserParseData)!.email) vc.setData((self.user[0] as? UserParseData)!.email)
println(vc.email) println(vc.email)
} }
*/
//reset pass //reset pass
case 3: case 2:
if self.user.count > 0 { if self.user.count > 0 {
let vc: ResetPassDetailViewController = (segue.destinationViewController as? ResetPassDetailViewController)!
vc.setData((self.user[0] as? UserParseData)!.email)
println(vc.email)
} }
//Profile Picture View //Profile Picture View
@ -241,10 +244,10 @@ class SettingsTableViewController: UIViewController, UITableViewDataSource, UITa
} }
/* func refreshTable(notification: NSNotification){ func refreshTable(notification: NSNotification){
self.user = manager.getUser() //self.user = manager.getUser()
self.table.reloadData() self.table.reloadData()
}*/ }
/* /*
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

View File

@ -10,7 +10,7 @@ import UIKit
class SignInController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITextFieldDelegate { class SignInController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITextFieldDelegate {
@IBOutlet var nameField: UITextField! @IBOutlet var nameField: UITextField!
@IBOutlet var userField: UITextField! //@IBOutlet var userField: UITextField!
@IBOutlet var emailField: UITextField! @IBOutlet var emailField: UITextField!
@IBOutlet var passField: UITextField! @IBOutlet var passField: UITextField!
@IBOutlet var saveBtn: UIButton! @IBOutlet var saveBtn: UIButton!
@ -22,7 +22,7 @@ class SignInController: UIViewController, UINavigationControllerDelegate, UIImag
@IBAction func saveNewProfile(sender: UIButton){ @IBAction func saveNewProfile(sender: UIButton){
if(self.nameField.hasText() == false if(self.nameField.hasText() == false
|| self.userField.hasText() == false /*|| self.userField.hasText() == false*/
|| self.emailField.hasText() == false || self.emailField.hasText() == false
|| self.passField.hasText() == false || self.passField.hasText() == false
|| self.profilePic.image == nil){ || self.profilePic.image == nil){
@ -33,9 +33,9 @@ class SignInController: UIViewController, UINavigationControllerDelegate, UIImag
self.presentViewController(alert, animated: true, completion: nil) self.presentViewController(alert, animated: true, completion: nil)
}else{ }else{
if(!(contains(self.userField.text!, "@") || contains(self.nameField.text!, "@"))){ if /*(!(contains(self.userField.text!, "@") ||*/ contains(self.nameField.text!, "@"){
let predicate: NSPredicate = NSPredicate(format: "((username = %@) OR (email = %@))", argumentArray: [self.nameField.text!,self.emailField.text!]) let predicate: NSPredicate = NSPredicate(format: "(email = %@)", argumentArray: [self.emailField.text!])
var userQuery: PFQuery = PFQuery(className: "_User", predicate: predicate) var userQuery: PFQuery = PFQuery(className: "_User", predicate: predicate)
dispatch_async(dispatch_get_main_queue(), { dispatch_async(dispatch_get_main_queue(), {
@ -49,8 +49,8 @@ class SignInController: UIViewController, UINavigationControllerDelegate, UIImag
self.presentViewController(alert, animated: true, completion: nil) self.presentViewController(alert, animated: true, completion: nil)
}else{ }else{
var user = PFUser() var user = PFUser()
var img:PFFile = PFFile(data: UIImagePNGRepresentation(self.profilePic.image))! var img:PFFile = PFFile(data: UIImageJPEGRepresentation(self.profilePic.image, 1.0))!
user.username = self.userField.text! user.username = self.emailField.text!
user.password = self.passField.text! user.password = self.passField.text!
user.email = self.emailField.text! user.email = self.emailField.text!
user.setObject(self.nameField.text!, forKey: "displayName") user.setObject(self.nameField.text!, forKey: "displayName")
@ -63,7 +63,7 @@ class SignInController: UIViewController, UINavigationControllerDelegate, UIImag
if error == nil { if error == nil {
//self.performSegueWithIdentifier("SignedUpSegue", sender: self) //self.performSegueWithIdentifier("SignedUpSegue", sender: self)
let storyboard = UIStoryboard(name: "Main", bundle: nil) let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewControllerWithIdentifier("TabControllerVC") as! UITabBarController let tabBarController = storyboard.instantiateViewControllerWithIdentifier("TabControlVC") as! UITabBarController
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window?.rootViewController = tabBarController appDelegate.window?.rootViewController = tabBarController
} }
@ -132,7 +132,7 @@ class SignInController: UIViewController, UINavigationControllerDelegate, UIImag
self.nameField.delegate = self self.nameField.delegate = self
self.passField.delegate = self self.passField.delegate = self
self.userField.delegate = self //self.userField.delegate = self
self.emailField.delegate = self self.emailField.delegate = self
@ -191,7 +191,7 @@ extension SignInController: UIImagePickerControllerDelegate{
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) { func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
self.profilePic.image = image self.profilePic.image = image
dismissViewControllerAnimated(true, completion: nil)
} }
func imagePickerControllerDidCancel(picker: UIImagePickerController) { func imagePickerControllerDidCancel(picker: UIImagePickerController) {

26
GetHip/TDAudioPlayerConstants.h Executable file
View File

@ -0,0 +1,26 @@
//
// TDAudioPlayerConstants.h
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/5/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "Foundation/Foundation.h"
extern NSString *const TDAudioPlayerDidChangeAudioNotification;
extern NSString *const TDAudioPlayerDidPauseNotification;
extern NSString *const TDAudioPlayerDidPlayNotification;
extern NSString *const TDAudioPlayerDidStopNotification;
extern NSString *const TDAudioPlayerNextTrackRequestNotification;
extern NSString *const TDAudioPlayerPreviousTrackRequestNotification;
extern NSString *const TDAudioStreamDidFinishPlayingNotification;
extern NSString *const TDAudioStreamDidStartPlayingNotification;
extern UInt32 const kTDAudioStreamReadMaxLength;
extern UInt32 const kTDAudioQueueBufferSize;
extern UInt32 const kTDAudioQueueBufferCount;
extern UInt32 const kTDAudioQueueStartMinimumBuffers;

25
GetHip/TDAudioPlayerConstants.m Executable file
View File

@ -0,0 +1,25 @@
//
// TDAudioPlayerConstants.m
// TDAudioPlayer
//
// Created by Tony DiPasquale on 11/5/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioPlayerConstants.h"
NSString *const TDAudioPlayerDidChangeAudioNotification = @"TDAudioPlayerDidChangeAudioNotification";
NSString *const TDAudioPlayerDidPauseNotification = @"TDAudioPlayerDidPauseNotification";
NSString *const TDAudioPlayerDidPlayNotification = @"TDAudioPlayerDidPlayNotification";
NSString *const TDAudioPlayerDidStopNotification = @"TDAudioPlayerDidStopNotification";
NSString *const TDAudioPlayerNextTrackRequestNotification = @"TDAudioPlayerNextTrackRequestNotification";
NSString *const TDAudioPlayerPreviousTrackRequestNotification = @"TDAudioPlayerPreviousTrackRequestNotification";
NSString *const TDAudioStreamDidFinishPlayingNotification = @"TDAudioStreamDidFinishPlayingNotification";
NSString *const TDAudioStreamDidStartPlayingNotification = @"TDAudioStreamDidStartPlayingNotification";
UInt32 const kTDAudioStreamReadMaxLength = 512;
UInt32 const kTDAudioQueueBufferSize = 2048;
UInt32 const kTDAudioQueueBufferCount = 16;
UInt32 const kTDAudioQueueStartMinimumBuffers = 8;

View File

@ -11,15 +11,15 @@ import Foundation
import Foundation import Foundation
class UserParseData { class UserParseData {
var username: String! //var username: String!
var displayName: String! var displayName: String!
var profileImg: UIImageView! var profileImg: UIImageView!
var email: String! var email: String!
init(usrName: String, dispName: String, email: String){ init(dispName: String, email: String){
self.username = usrName //self.username = usrName
self.profileImg = nil //proImage self.profileImg = nil //proImage
self.displayName = dispName self.displayName = dispName
self.email = email self.email = email

View File

@ -16,7 +16,7 @@ class UserParseDataSource{
var query = PFUser.query() var query = PFUser.query()
var currentUser = PFUser.currentUser() var currentUser = PFUser.currentUser()
query!.whereKey("username", equalTo: (currentUser?.username as String!)) query!.whereKey("email", equalTo: (currentUser?.email as String!))
query!.findObjectsInBackgroundWithBlock { query!.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in (objects, error) -> Void in
@ -25,24 +25,23 @@ class UserParseDataSource{
for object in objects! { for object in objects! {
var usr: UserParseData var usr: UserParseData
var usrName: String! //var usrName: String!
var profileImage: UIImageView var profileImage: UIImageView
var displayName: String var displayName: String
var email: String var email: String
usrName = object.objectForKey("username")! as! String //usrName = object.objectForKey("username")! as! String
displayName = object.objectForKey("displayName") as! String displayName = object.objectForKey("displayName") as! String
/*
if displayName.isEmpty { if displayName.isEmpty {
displayName = usrName displayName = usrName
} }
*/
email = object.objectForKey("email")! as! String email = object.objectForKey("email")! as! String
usr = UserParseData(dispName: displayName, email: email)
usr = UserParseData(usrName: usrName, dispName: displayName, email: email)
var img = object.objectForKey("profilePicture")! as? PFFile var img = object.objectForKey("profilePicture")! as? PFFile