Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Please merge changes from my repo #15

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ build
.DS_Store
*.xcodeproj/*.mode*
*.xcodeproj/*.pbxuser
*.xcodeproj/*.xcworkspace
*.xcodeproj/xcuserdata
*.xcodeproj/*.pbxproj
10 changes: 10 additions & 0 deletions AudioStreamer.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 9 additions & 11 deletions Classes/AudioStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,16 @@
//
#define SHOUTCAST_METADATA

#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32
#endif
#else
#import <Cocoa/Cocoa.h>
#endif TARGET_OS_IPHONE

#import <Foundation/Foundation.h>
#include <pthread.h>
#include <AudioToolbox/AudioToolbox.h>

#define LOG_QUEUED_BUFFERS 0

#define kNumAQBufs 16 // Number of audio queue buffers we allocate.
#define kNumStartsAQBufs 16

#define kNumAQBufs 1500 // Number of audio queue buffers we allocate.
// Needs to be big enough to keep audio pipeline
// busy (non-zero number of queued buffers) but
// not so big that audio takes too long to begin
Expand Down Expand Up @@ -177,17 +172,21 @@ extern NSString * const ASUpdateMetadataNotification;
unsigned int dataBytesRead; // how many bytes of data have been read
NSMutableString *metaDataString; // the metaDataString
#endif
BOOL vbr; // indicates VBR (or not) stream

}

@property AudioStreamerErrorCode errorCode;
@property (readonly) AudioStreamerState state;
@property (readonly) AudioStreamerStopReason stopReason;
@property (readonly) double progress;
@property (readonly) double bufferFillPercentage;
@property (readonly) double duration;
@property (readwrite) UInt32 bitRate;
@property (readonly) NSDictionary *httpHeaders;
@property (readonly) UInt32 numberOfChannels;
@property (assign, getter=isMeteringEnabled) BOOL meteringEnabled;

@property (readonly) BOOL vbr;

- (id)initWithURL:(NSURL *)aURL;
- (void)start;
Expand All @@ -211,4 +210,3 @@ extern NSString * const ASUpdateMetadataNotification;




101 changes: 66 additions & 35 deletions Classes/AudioStreamer.m
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,11 @@ @implementation AudioStreamer

@synthesize errorCode;
@synthesize state;
@synthesize stopReason;
@synthesize bitRate;
@synthesize httpHeaders;
@synthesize numberOfChannels;

@synthesize vbr;

//
// initWithURL
Expand Down Expand Up @@ -264,6 +265,17 @@ - (void)dealloc
[super dealloc];
}

//
// bufferFillPercentage
//
// returns a value between 0 and 1 that represents how full the buffer is
//
-(double)bufferFillPercentage
{
return (double)buffersUsed/(double)(kNumAQBufs - 1);
}


//
// isFinishing
//
Expand Down Expand Up @@ -676,8 +688,8 @@ - (BOOL)openReadStream
if (fileLength > 0 && seekByteOffset > 0)
{
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"),
(CFStringRef)[NSString stringWithFormat:@"bytes=%ld-%ld", seekByteOffset, fileLength]);
discontinuous = YES;
(CFStringRef)[NSString stringWithFormat:@"bytes=%ld-%ld", seekByteOffset, fileLength - 1]);
discontinuous = vbr;
}

//
Expand Down Expand Up @@ -944,6 +956,7 @@ - (void)start
initWithTarget:self
selector:@selector(startInternal)
object:nil];
[internalThread setName:@"InternalThread"];
[internalThread start];
}
}
Expand Down Expand Up @@ -1101,17 +1114,24 @@ - (double)progress
//
- (double)calculatedBitRate
{
if (packetDuration && processedPacketsCount > BitRateEstimationMinPackets)
if (vbr)
{
double averagePacketByteSize = processedPacketsSizeTotal / processedPacketsCount;
return 8.0 * averagePacketByteSize / packetDuration;
}
if (packetDuration && processedPacketsCount > BitRateEstimationMinPackets)
{
double averagePacketByteSize = processedPacketsSizeTotal / processedPacketsCount;
return 8.0 * averagePacketByteSize / packetDuration;
}

if (bitRate)
if (bitRate)
{
return (double)bitRate;
}
}
else
{
return (double)bitRate;
bitRate = 8.0 * asbd.mSampleRate * asbd.mBytesPerPacket * asbd.mFramesPerPacket;
return bitRate;
}

return 0;
}

Expand Down Expand Up @@ -1218,8 +1238,12 @@ - (void)pause
else if (state == AS_PAUSED)
{
err = AudioQueueStart(audioQueue, NULL);
#if TARGET_OS_IPHONE
bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
#if TARGET_OS_IPHONE
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {
if (bgTaskId != UIBackgroundTaskInvalid) {
bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}
}
#endif
if (err)
{
Expand Down Expand Up @@ -1809,13 +1833,15 @@ - (void)enqueueBuffer
// AudioFileStream stays a small amount ahead of the AudioQueue to
// avoid an audio glitch playing streaming files on iPhone SDKs < 3.0
//
if (state == AS_FLUSHING_EOF || buffersUsed == kNumAQBufs - 1)
if (state == AS_FLUSHING_EOF || buffersUsed == kNumStartsAQBufs - 1)
{
if (self.state == AS_BUFFERING)
{
err = AudioQueueStart(audioQueue, NULL);
#if TARGET_OS_IPHONE
bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {
bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}
#endif
if (err)
{
Expand All @@ -1829,8 +1855,10 @@ - (void)enqueueBuffer
self.state = AS_WAITING_FOR_QUEUE_TO_START;

err = AudioQueueStart(audioQueue, NULL);
#if TARGET_OS_IPHONE
bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
#if TARGET_OS_IPHONE
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {
bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}
#endif
if (err)
{
Expand Down Expand Up @@ -1891,18 +1919,25 @@ - (void)createQueue
}

// get the packet size if it is available
UInt32 sizeOfUInt32 = sizeof(UInt32);
err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &packetBufferSize);
if (err || packetBufferSize == 0)
if (vbr)
{
err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &packetBufferSize);
UInt32 sizeOfUInt32 = sizeof(UInt32);
err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &packetBufferSize);
if (err || packetBufferSize == 0)
{
// No packet size available, just use the default
packetBufferSize = kAQDefaultBufSize;
err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &packetBufferSize);
if (err || packetBufferSize == 0)
{
// No packet size available, just use the default
packetBufferSize = kAQDefaultBufSize;
}
}
}

else
{
packetBufferSize = kAQDefaultBufSize;
}

// allocate audio queue buffers
for (unsigned int i = 0; i < kNumAQBufs; ++i)
{
Expand Down Expand Up @@ -2114,6 +2149,7 @@ - (void)handleAudioPackets:(const void *)inInputData

if (!audioQueue)
{
vbr = (inPacketDescriptions != nil);
[self createQueue];
}
}
Expand Down Expand Up @@ -2310,9 +2346,6 @@ - (void)handlePropertyChangeForQueue:(AudioQueueRef)inAQ
propertyID:(AudioQueuePropertyID)inID
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#if TARGET_OS_IPHONE
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
#endif
@synchronized(self)
{
if (inID == kAudioQueueProperty_IsRunning)
Expand All @@ -2337,21 +2370,20 @@ - (void)handlePropertyChangeForQueue:(AudioQueueRef)inAQ
// By creating an NSRunLoop for the AudioQueue thread, it changes the
// thread destruction order and seems to avoid this crash bug -- or
// at least I haven't had it since (nasty hard to reproduce error!)
//
#if TARGET_OS_IPHONE
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
#endif
//

[NSRunLoop currentRunLoop];

self.state = AS_PLAYING;

#if TARGET_OS_IPHONE
if (bgTaskId != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask: bgTaskId];
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {
if (bgTaskId != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask: bgTaskId];
}

bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}

bgTaskId = newTaskId;
#endif
}
else
Expand Down Expand Up @@ -2390,4 +2422,3 @@ - (void)handleInterruptionChangeToState:(AudioQueuePropertyID)inInterruptionStat

@end


2 changes: 1 addition & 1 deletion Classes/MacStreamingPlayerController.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ @implementation MacStreamingPlayerController

- (void)awakeFromNib
{
[downloadSourceField setStringValue:@"http://192.168.1.2/~matt/inside.m4a"];
[downloadSourceField setStringValue:@"http://shoutmedia.abc.net.au:10326"];
}

//
Expand Down
18 changes: 16 additions & 2 deletions Classes/iPhoneStreamingPlayerAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

#import <dispatch/dispatch.h>

#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32
#endif

#import "iPhoneStreamingPlayerAppDelegate.h"
#import "iPhoneStreamingPlayerViewController.h"
#import "AudioStreamer.h"
Expand All @@ -39,6 +43,7 @@ - (void)applicationDidFinishLaunching:(UIApplication *)application {
selector:@selector(presentAlertWithTitle:)
name:ASPresentAlertWithTitleNotification
object:nil];
[[NSThread currentThread] setName:@"Main Thread"];
}


Expand All @@ -50,12 +55,15 @@ - (void)dealloc {

- (void)presentAlertWithTitle:(NSNotification *)notification
{
NSString *title = [[notification userInfo] objectForKey:@"title"];
NSString *message = [[notification userInfo] objectForKey:@"message"];

//NSLog(@"Current Thread = %@", [NSThread currentThread]);
dispatch_queue_t main_queue = dispatch_get_main_queue();

dispatch_async(main_queue, ^{

NSString *title = [[notification userInfo] objectForKey:@"title"];
NSString *message = [[notification userInfo] objectForKey:@"message"];
//NSLog(@"Current Thread (in main queue) = %@", [NSThread currentThread]);
if (!uiIsVisible) {
#ifdef TARGET_OS_IPHONE
if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_0) {
Expand All @@ -77,11 +85,14 @@ - (void)presentAlertWithTitle:(NSNotification *)notification
cancelButtonTitle:NSLocalizedString(@"OK", @"")
otherButtonTitles: nil]
autorelease];
/*
[alert
performSelector:@selector(show)
onThread:[NSThread mainThread]
withObject:nil
waitUntilDone:NO];
*/
[alert show];
#else
NSAlert *alert =
[NSAlert
Expand All @@ -90,11 +101,14 @@ - (void)presentAlertWithTitle:(NSNotification *)notification
alternateButton:nil
otherButton:nil
informativeTextWithFormat:message];
/*
[alert
performSelector:@selector(runModal)
onThread:[NSThread mainThread]
withObject:nil
waitUntilDone:NO];
*/
[alert runModal];
#endif
}
});
Expand Down
1 change: 1 addition & 0 deletions Classes/iPhoneStreamingPlayerViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
IBOutlet UISlider *progressSlider;
IBOutlet UITextField *metadataArtist;
IBOutlet UITextField *metadataTitle;
IBOutlet UITextField *metadataAlbum;
AudioStreamer *streamer;
NSTimer *progressUpdateTimer;
NSTimer *levelMeterUpdateTimer;
Expand Down
Loading