mirror of
https://github.com/oonyeje/Get-Hip.git
synced 2025-12-25 03:37:40 +00:00
bug fixes...will detail later, need to fix multipeer party streaming
This commit is contained in:
parent
514b2d2b09
commit
8a16abdd02
17
AudioStreamer/Categories/NSMutableArray+QueueMethods.h
Executable file
17
AudioStreamer/Categories/NSMutableArray+QueueMethods.h
Executable 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
|
||||||
38
AudioStreamer/Categories/NSMutableArray+QueueMethods.m
Executable file
38
AudioStreamer/Categories/NSMutableArray+QueueMethods.m
Executable 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
|
||||||
38
AudioStreamer/Classes/TDAudioFileStream.h
Executable file
38
AudioStreamer/Classes/TDAudioFileStream.h
Executable 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
|
||||||
112
AudioStreamer/Classes/TDAudioFileStream.m
Executable file
112
AudioStreamer/Classes/TDAudioFileStream.m
Executable 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
|
||||||
45
AudioStreamer/Classes/TDAudioQueue.h
Executable file
45
AudioStreamer/Classes/TDAudioQueue.h
Executable 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
|
||||||
141
AudioStreamer/Classes/TDAudioQueue.m
Executable file
141
AudioStreamer/Classes/TDAudioQueue.m
Executable 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
|
||||||
26
AudioStreamer/Classes/TDAudioQueueBuffer.h
Executable file
26
AudioStreamer/Classes/TDAudioQueueBuffer.h
Executable 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
|
||||||
106
AudioStreamer/Classes/TDAudioQueueBuffer.m
Executable file
106
AudioStreamer/Classes/TDAudioQueueBuffer.m
Executable 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
|
||||||
27
AudioStreamer/Classes/TDAudioQueueBufferManager.h
Executable file
27
AudioStreamer/Classes/TDAudioQueueBufferManager.h
Executable 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
|
||||||
114
AudioStreamer/Classes/TDAudioQueueBufferManager.m
Executable file
114
AudioStreamer/Classes/TDAudioQueueBufferManager.m
Executable 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
|
||||||
19
AudioStreamer/Classes/TDAudioQueueController.h
Executable file
19
AudioStreamer/Classes/TDAudioQueueController.h
Executable 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
|
||||||
38
AudioStreamer/Classes/TDAudioQueueController.m
Executable file
38
AudioStreamer/Classes/TDAudioQueueController.m
Executable 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
|
||||||
19
AudioStreamer/Classes/TDAudioQueueFiller.h
Executable file
19
AudioStreamer/Classes/TDAudioQueueFiller.h
Executable 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
|
||||||
41
AudioStreamer/Classes/TDAudioQueueFiller.m
Executable file
41
AudioStreamer/Classes/TDAudioQueueFiller.m
Executable 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
|
||||||
39
AudioStreamer/Classes/TDAudioStream.h
Executable file
39
AudioStreamer/Classes/TDAudioStream.h
Executable 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
|
||||||
93
AudioStreamer/Classes/TDAudioStream.m
Executable file
93
AudioStreamer/Classes/TDAudioStream.m
Executable 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
|
||||||
24
AudioStreamer/TDAudioInputStreamer.h
Executable file
24
AudioStreamer/TDAudioInputStreamer.h
Executable 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
|
||||||
195
AudioStreamer/TDAudioInputStreamer.m
Executable file
195
AudioStreamer/TDAudioInputStreamer.m
Executable 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
|
||||||
21
AudioStreamer/TDAudioOutputStreamer.h
Executable file
21
AudioStreamer/TDAudioOutputStreamer.h
Executable 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
|
||||||
144
AudioStreamer/TDAudioOutputStreamer.m
Executable file
144
AudioStreamer/TDAudioOutputStreamer.m
Executable 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
17
AudioStreamer/TDAudioStreamer.h
Executable 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
13
AudioStreamer/TDAudioStreamer.m
Executable 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
|
||||||
25
AudioStreamer/TDAudioStreamerConstants.h
Executable file
25
AudioStreamer/TDAudioStreamerConstants.h
Executable 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;
|
||||||
25
AudioStreamer/TDAudioStreamerConstants.m
Executable file
25
AudioStreamer/TDAudioStreamerConstants.m
Executable 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;
|
||||||
@ -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;
|
||||||
|
|||||||
@ -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()
|
||||||
|
|
||||||
|
|||||||
15
GetHip/AudioPlayer/Categories/NSInputStream+URLInitialization.h
Executable file
15
GetHip/AudioPlayer/Categories/NSInputStream+URLInitialization.h
Executable 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
|
||||||
47
GetHip/AudioPlayer/Categories/NSInputStream+URLInitialization.m
Executable file
47
GetHip/AudioPlayer/Categories/NSInputStream+URLInitialization.m
Executable 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
|
||||||
17
GetHip/AudioPlayer/Categories/NSMutableArray+QueueMethods.h
Executable file
17
GetHip/AudioPlayer/Categories/NSMutableArray+QueueMethods.h
Executable 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
|
||||||
38
GetHip/AudioPlayer/Categories/NSMutableArray+QueueMethods.m
Executable file
38
GetHip/AudioPlayer/Categories/NSMutableArray+QueueMethods.m
Executable 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
|
||||||
19
GetHip/AudioPlayer/Classes/TDAudioMetaInfo.h
Executable file
19
GetHip/AudioPlayer/Classes/TDAudioMetaInfo.h
Executable 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
|
||||||
13
GetHip/AudioPlayer/Classes/TDAudioMetaInfo.m
Executable file
13
GetHip/AudioPlayer/Classes/TDAudioMetaInfo.m
Executable 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
|
||||||
41
GetHip/AudioPlayer/TDAudioPlayer.h
Executable file
41
GetHip/AudioPlayer/TDAudioPlayer.h
Executable 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
|
||||||
261
GetHip/AudioPlayer/TDAudioPlayer.m
Executable file
261
GetHip/AudioPlayer/TDAudioPlayer.m
Executable 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
|
||||||
17
GetHip/AudioStreamer/Categories/NSMutableArray+QueueMethods.h
Executable file
17
GetHip/AudioStreamer/Categories/NSMutableArray+QueueMethods.h
Executable 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
|
||||||
38
GetHip/AudioStreamer/Categories/NSMutableArray+QueueMethods.m
Executable file
38
GetHip/AudioStreamer/Categories/NSMutableArray+QueueMethods.m
Executable 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
|
||||||
38
GetHip/AudioStreamer/Classes/TDAudioFileStream.h
Executable file
38
GetHip/AudioStreamer/Classes/TDAudioFileStream.h
Executable 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
|
||||||
112
GetHip/AudioStreamer/Classes/TDAudioFileStream.m
Executable file
112
GetHip/AudioStreamer/Classes/TDAudioFileStream.m
Executable 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
|
||||||
45
GetHip/AudioStreamer/Classes/TDAudioQueue.h
Executable file
45
GetHip/AudioStreamer/Classes/TDAudioQueue.h
Executable 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
|
||||||
141
GetHip/AudioStreamer/Classes/TDAudioQueue.m
Executable file
141
GetHip/AudioStreamer/Classes/TDAudioQueue.m
Executable 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
|
||||||
26
GetHip/AudioStreamer/Classes/TDAudioQueueBuffer.h
Executable file
26
GetHip/AudioStreamer/Classes/TDAudioQueueBuffer.h
Executable 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
|
||||||
106
GetHip/AudioStreamer/Classes/TDAudioQueueBuffer.m
Executable file
106
GetHip/AudioStreamer/Classes/TDAudioQueueBuffer.m
Executable 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
|
||||||
27
GetHip/AudioStreamer/Classes/TDAudioQueueBufferManager.h
Executable file
27
GetHip/AudioStreamer/Classes/TDAudioQueueBufferManager.h
Executable 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
|
||||||
114
GetHip/AudioStreamer/Classes/TDAudioQueueBufferManager.m
Executable file
114
GetHip/AudioStreamer/Classes/TDAudioQueueBufferManager.m
Executable 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
|
||||||
19
GetHip/AudioStreamer/Classes/TDAudioQueueController.h
Executable file
19
GetHip/AudioStreamer/Classes/TDAudioQueueController.h
Executable 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
|
||||||
38
GetHip/AudioStreamer/Classes/TDAudioQueueController.m
Executable file
38
GetHip/AudioStreamer/Classes/TDAudioQueueController.m
Executable 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
|
||||||
19
GetHip/AudioStreamer/Classes/TDAudioQueueFiller.h
Executable file
19
GetHip/AudioStreamer/Classes/TDAudioQueueFiller.h
Executable 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
|
||||||
41
GetHip/AudioStreamer/Classes/TDAudioQueueFiller.m
Executable file
41
GetHip/AudioStreamer/Classes/TDAudioQueueFiller.m
Executable 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
|
||||||
39
GetHip/AudioStreamer/Classes/TDAudioStream.h
Executable file
39
GetHip/AudioStreamer/Classes/TDAudioStream.h
Executable 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
|
||||||
93
GetHip/AudioStreamer/Classes/TDAudioStream.m
Executable file
93
GetHip/AudioStreamer/Classes/TDAudioStream.m
Executable 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
|
||||||
24
GetHip/AudioStreamer/TDAudioInputStreamer.h
Executable file
24
GetHip/AudioStreamer/TDAudioInputStreamer.h
Executable 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
|
||||||
195
GetHip/AudioStreamer/TDAudioInputStreamer.m
Executable file
195
GetHip/AudioStreamer/TDAudioInputStreamer.m
Executable 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
|
||||||
21
GetHip/AudioStreamer/TDAudioOutputStreamer.h
Executable file
21
GetHip/AudioStreamer/TDAudioOutputStreamer.h
Executable 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
|
||||||
144
GetHip/AudioStreamer/TDAudioOutputStreamer.m
Executable file
144
GetHip/AudioStreamer/TDAudioOutputStreamer.m
Executable 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
GetHip/AudioStreamer/TDAudioStreamer.h
Executable file
17
GetHip/AudioStreamer/TDAudioStreamer.h
Executable 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
GetHip/AudioStreamer/TDAudioStreamer.m
Executable file
13
GetHip/AudioStreamer/TDAudioStreamer.m
Executable 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
|
||||||
25
GetHip/AudioStreamer/TDAudioStreamerConstants.h
Executable file
25
GetHip/AudioStreamer/TDAudioStreamerConstants.h
Executable 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;
|
||||||
25
GetHip/AudioStreamer/TDAudioStreamerConstants.m
Executable file
25
GetHip/AudioStreamer/TDAudioStreamerConstants.m
Executable 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;
|
||||||
@ -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"
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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,24 +135,48 @@ 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{
|
|
||||||
|
//case where user display name is entered
|
||||||
|
self.searchedEmail = searchBar.text
|
||||||
|
|
||||||
|
for email in self.frnds{
|
||||||
|
if email == self.searchedEmail{
|
||||||
inFriendsList = true
|
inFriendsList = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(inFriendsList == false){
|
|
||||||
|
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
|
||||||
|
|
||||||
|
//put in the checking code after lab today
|
||||||
|
if object == nil {
|
||||||
var query = PFQuery(className: "_User")
|
var query = PFQuery(className: "_User")
|
||||||
query.whereKey("username", equalTo: searchedUsername)
|
query.whereKey("username", equalTo: self.searchedEmail)
|
||||||
|
|
||||||
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.foundName.text = object?.objectForKey("username") as? String
|
self.foundName.text = object?.objectForKey("displayName") as? String
|
||||||
|
|
||||||
//download profile imge
|
//download profile imge
|
||||||
var img = object!.objectForKey("profilePicture")! as? PFFile
|
var img = object!.objectForKey("profilePicture")! as? PFFile
|
||||||
@ -173,12 +197,27 @@ extension FriendRequestViewController: UITextFieldDelegate{
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
}else{
|
}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)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
let alert = UIAlertController(title: "Already Friends", message: "You are already friends with this user!", preferredStyle: .Alert)
|
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)}))
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
|
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
|
||||||
|
|||||||
@ -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!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
//start browsing for peers
|
||||||
self.partyData.setBrowser()
|
self.partyData.setBrowser()
|
||||||
self.partyData.startBrowser()
|
self.partyData.startBrowser()
|
||||||
|
|
||||||
//self.partyData.delegate = self
|
//self.partyData.delegate = self
|
||||||
self.firstTime = false
|
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()
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -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"/>
|
<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"/>
|
||||||
|
<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>
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,6 +62,13 @@ 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
|
||||||
|
|||||||
@ -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!
|
||||||
|
|||||||
@ -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,7 +102,7 @@ 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()
|
||||||
|
|
||||||
@ -112,7 +117,9 @@ class EmailDetailViewController: UIViewController {
|
|||||||
else if let object = object{
|
else if let object = object{
|
||||||
object.setObject(self.possibleEmail, forKey: "email")
|
object.setObject(self.possibleEmail, forKey: "email")
|
||||||
object.saveInBackground()
|
object.saveInBackground()
|
||||||
NSNotificationCenter.defaultCenter().postNotificationName("savingEmail", object: nil)
|
|
||||||
|
NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshSettings:", name: "reloadDataS", object: nil)
|
||||||
|
(self.tabBarController as! HomeTabController).reloadParseData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +127,9 @@ class EmailDetailViewController: UIViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var email: String!
|
var email: String!
|
||||||
|
|
||||||
func setData(email: String){
|
func setData(email: String){
|
||||||
@ -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) {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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
26
GetHip/TDAudioPlayerConstants.h
Executable 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
25
GetHip/TDAudioPlayerConstants.m
Executable 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;
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user