Compare commits

...

196 Commits

Author SHA1 Message Date
Thong Nguyen 4d9cea0a31 Fixed HE-AAC format being stripped 2014-08-20 15:49:36 +01:00
Thong Nguyen acdf65c7cb Merge pull request #128 from kwillick/master
Support adding http headers to a STKHTTPDataSource
2014-08-19 09:56:21 +01:00
Kipp Hickman ac951bfc7a Added ability to add http headers to a STKHTTPDataSource. 2014-08-15 12:00:49 -07:00
Thong Nguyen 8c64914314 Updated test URLs to use abstractpath.com 2014-06-10 16:29:30 +01:00
Thong Nguyen a9dfb2eddf Fixed thread related crashes in OutputRenderCallback 2014-04-07 15:28:34 +01:00
Thong Nguyen 3fcf054a23 Fix STKAudioPlayer.progress property thread-related crash 2014-04-07 15:15:36 +01:00
Thong Nguyen a615419404 Fixed deployment target min should be 4.3 not 6.0 2014-04-05 13:15:43 +01:00
Thong Nguyen e43a4613f8 startInternal now cleans up audio resources when the playback thread is finished. Added fix for undefned DBL_MAX 2014-04-05 13:08:58 +01:00
Thong Nguyen ca928dfe1e Removed buffering work (now in different branch) 2014-03-24 16:32:38 +00:00
Thong Nguyen d7d583c3ba Some chunking/paging buffering data source work 2014-02-24 17:05:54 +00:00
Thong Nguyen 7540045361 Some buffering data source tests/work 2014-02-20 17:10:51 +00:00
Thong Nguyen 972ae0e15b Some more buffering data source work 2014-02-18 19:02:47 +00:00
Thong Nguyen e3ed6c6dee Removed AudioDataSource (for now). Changed all int64_t and long long types to SInt64. Started adding Buffered data source 2014-02-18 13:38:03 +00:00
Thong Nguyen 3398e8c64e Explicitly wakeup playback thread if a delayed seek was queued 2014-02-16 17:07:39 +00:00
Thong Nguyen f99201f54d Explicitly wakeup playback thread if a delayed seek was queued 2014-02-16 17:07:10 +00:00
Thong Nguyen 44b9e7d2d1 Removed errant NSLog 2014-02-16 16:50:54 +00:00
Thong Nguyen 7aae2bcb6b Allow queueing of a seek request for a file before it has loaded 2014-02-16 16:50:12 +00:00
Thong Nguyen 5a8068b859 STKAutoRecoveringHTTPDataSource shouldn't retry if inner data source no longer is registered 2014-02-16 11:57:23 +00:00
Thong Nguyen 728fc5bb21 More controllable grace period for waiting for data after seek 2014-02-16 11:43:01 +00:00
Thong Nguyen c4053c964e Smaller setting for STK_CYCLES_REQUIRED_BEFORE_SEEK_BECOMES_PLAYING 2014-02-16 01:49:23 +00:00
Thong Nguyen c31df15a43 STKAudioPlayerInternalStateWaitingForDataAfterSeek no longer considered a buffering state externally. STKAudioPlayerInternalStateWaitingForDataAfterSeek turns into a playing state after a certain period. Prevents flapping between states when seeking tracks 2014-02-16 01:24:08 +00:00
Thong Nguyen 923baf5b89 STKAudioPlayerInternalStatePendingNext and STKAudioPlayerInternalStateWaitingForDataAfterSeeks are both now considered STKAudioPlayerStateBuffering states externally 2014-02-15 22:02:56 +00:00
Thong Nguyen 9199785202 Better backgroundTask start/stopping using blocks to safely avoid referencing STKAudioPlayer 2014-02-15 17:04:52 +00:00
Thong Nguyen 0618027252 Fixed iOS background task holding onto a reference to STKAudioPlayer and preventing it from being dealloc immediately 2014-02-15 16:55:16 +00:00
Thong Nguyen 188f880f5a Tidied up some warnings 2014-02-14 22:19:41 +00:00
Thong Nguyen ae9cee68f0 Slightly better bitrate calculation for VBR files 2014-02-14 22:06:46 +00:00
Thong Nguyen eeece64417 Changed duration calculation to work better with short files 2014-02-14 18:34:55 +00:00
Thong Nguyen 243dc1f8a2 Fixed STKAudioPlayer:stop sometimes blocking too long 2014-02-14 14:49:08 +00:00
Thong Nguyen 8c608440ae Merge pull request #81 from AndrewKosovich/master
Ported error handling from the previous Audjustable player.
2014-02-14 12:16:10 +00:00
Andrew Kosovich 9aed1b082a Ported error handling from the previous Audjustable player.
STKDataSource is designed to return values < 0 in case of error, but new STKAudioPlayer doesn't handle that, which causes crash few lines later when calling AudioFileStreamParseBytes with read<0.
2014-02-14 13:37:43 +02:00
Thong Nguyen 6eb149f83a Progress now returns 0 if player is stopped 2014-02-13 22:24:26 +00:00
Thong Nguyen 1243dbf0e1 setDataSource now immediately stops whatever is currently playing. STKAutoRecoveringHTTPDataSource watchdog timer improvements 2014-02-13 22:02:48 +00:00
Thong Nguyen a15c2c27ff Fixed stream not set to nil when error occurs when opening 2014-02-13 18:06:24 +00:00
Thong Nguyen aa441045aa Fixed pendingQueue and mostRecentlyQueuedStillPendingItem returning STKQueueEntry instead of queueItemId 2014-02-13 17:54:24 +00:00
Thong Nguyen 569764d869 Added watchdog to STKAutoRecoveringHTTPDataSource to catch TCP timeouts which otherwise would not raise an error since we aren't do any writes to the socket 2014-02-13 17:33:45 +00:00
Thong Nguyen 511b756694 Fixed pendingQueue and mostRecentlyQueuedStillPendingItem returning STKQueueEntry instead of original queueItemId 2014-02-13 11:58:19 +00:00
Thong Nguyen ab0c4d1315 STKAutoRecoveringHTTPDataSource now stops retrying to connect if DataSource no longer has an event loop 2014-02-13 11:34:05 +00:00
Thong Nguyen 6216abb0ab Changed STKCoreFoundationDataSource to not open in registerForEvents (delay open and registration) 2014-02-12 23:09:53 +00:00
Thong Nguyen 8c5b4fb298 Fixed openForSeek on STKHTTPDataSource potentially handling old URLs if URL provider is async 2014-02-12 19:53:21 +00:00
Thong Nguyen 03e9b8b208 Updated README 2014-02-11 23:13:34 +00:00
Thong Nguyen 60d48a0682 Added the ability to dynamically remove or add EQ unit to save battery when EQ unit is not needed 2014-02-11 19:24:41 +00:00
Thong Nguyen dee6322751 Set default kAudioUnitProperty_MaximumFramesPerSlice on all audio units to 4096 to fix playback problems on lockscreen 2014-02-10 23:14:32 +00:00
Thong Nguyen 5e3048a7bf Merge branch 'nbandeq' 2014-02-10 14:15:37 +00:00
Thong Nguyen ac7aabf746 Removed EQ support for OSX < 10.9 2014-02-10 14:14:59 +00:00
Thong Nguyen ce30f0de57 New AudioGraph creation code mostly done. EQ working on iOS and OSX 2014-02-10 13:25:17 +00:00
Thong Nguyen a58269fcdb Got EQ working (iOS5 and OSX 10.9). Changed OSX projects to use 10.9 SDK 2014-02-09 23:32:49 +00:00
Thong Nguyen 3ecba8c8b4 Some more EQ work 2014-02-07 18:30:54 +00:00
Thong Nguyen c98b673064 Refactoring how the graph and nodes are created 2014-02-07 09:43:47 +00:00
Thong Nguyen 13fc64baa2 Merge pull request #77 from AndrewKosovich/master
Fixed crash in the STKHTTPDataSource.
2014-02-06 17:20:17 +00:00
Andrew Kosovich 5e4b500785 Fixed crash in the STKHTTPDataSource. 2014-02-06 18:33:03 +02:00
Thong Nguyen 693c5ed059 Started adding EQ 2014-02-05 20:22:29 +00:00
Thong Nguyen a15405b6c5 Fixed audio thread may set the state to playing even in certain conditions even if the player has been user-paused or stopped (race condition) 2014-02-05 19:05:47 +00:00
Thong Nguyen ce6f2b9512 Fixed audio thread may set the state to playing even in certain conditions even if the player has been user-paused or stopped (race condition) 2014-02-05 18:05:47 +00:00
Thong Nguyen 63bb19747f Changed STKAudioPlayerOptions to be a struct rather than enum. Most values that can be tweaked can be provided in constructor. Fixed deadlock if createAudioGraph fails 2014-02-05 14:18:37 +00:00
Thong Nguyen 0a6e1d4534 Added volume support via volume property using mixer on iOS and mixer or standard output unit volume property on OSX 2014-02-04 16:46:30 +00:00
Thong Nguyen d49e2849eb Removed unnecessary synthesized properties. Made STKFrameFilterEntry public readonly. Removed AudioUnit framework requirement for iOS n podspec 2014-02-03 17:23:53 +00:00
Thong Nguyen f725ed0b2c Added additional queue/play methods 2014-02-03 13:50:15 +00:00
Thong Nguyen 55a96578b4 Updated README 2014-02-03 13:37:10 +00:00
Thong Nguyen 16855e81dc Updated README 2014-02-03 13:33:40 +00:00
Thong Nguyen fed674d774 Updated README 2014-02-02 23:51:44 +00:00
Thong Nguyen c6e1b113dc Updated README 2014-02-02 15:33:15 +00:00
Thong Nguyen 43a9f8b26f Updated README 2014-02-02 15:30:34 +00:00
Thong Nguyen db5b9d92ed Updated README 2014-02-02 15:24:36 +00:00
Thong Nguyen 5398bfcedb Updated podspecs to include OSX 2014-02-02 15:15:48 +00:00
Thong Nguyen d63a99b5fb Merged new AudioUnit based STKAudioPlayer back into master 2014-02-02 14:27:20 +00:00
Thong Nguyen 1c78dc5867 Changed canonical format to fixed point for all platforms. Added metering view on ExampleAppMac 2014-02-02 14:19:12 +00:00
Thong Nguyen 4df5a84569 Added OSX build targets and ExampleAppMac. Added AudioUnit as a dependent framework in podspec 2014-02-02 13:14:37 +00:00
Thong Nguyen 70368a09ba Added pendingQueue, pendingQueueCount, mostRecentlyQueuedStillPendingItem. Added more documentation comments. Changed STKAudioPlayerInternalState to be private/hidden 2014-02-02 12:48:24 +00:00
Thong Nguyen 018da7a2eb Slight layout fix for AudioPlayerView 2014-02-01 23:29:39 +00:00
Thong Nguyen d347e5e80c Added mute/unmute support 2014-02-01 23:24:06 +00:00
Thong Nguyen 4d73784338 Added audio frame filtering and level metering support using Audio Units 2014-02-01 23:04:55 +00:00
Thong Nguyen 98c7d9b8f0 STKAudioPlayer:dataSourceFromURL uses case insensitive scheme compare 2014-02-01 00:29:02 +00:00
Thong Nguyen 56b2dd4ace Better range/length handling in STKHTTPDataSource. Handles out-of-range requests gracefully 2014-02-01 00:23:23 +00:00
Thong Nguyen a9b1e143a0 queueDataSource shold let playback thread automatically start the audio unit 2014-01-31 23:19:29 +00:00
Thong Nguyen c4a7251d19 Fixed potential crash when OutputRenderCallback is called with no items in the queue or playing 2014-01-31 23:07:49 +00:00
Thong Nguyen ae63d04b87 Don't stop audio player immediately when finished playing---wait until next runloop 2014-01-31 23:02:19 +00:00
Thong Nguyen dd7165b3d2 Fixed player somtimes waiting in buffering state for very small files 2014-01-31 22:58:07 +00:00
Thong Nguyen 8c94b9ba5c Added WAV file test to test app 2014-01-31 22:45:17 +00:00
Thong Nguyen c2fe2c68b2 Started adding framefilter support for EQ etc. Fixed seek bug with WAV files 2014-01-31 22:18:09 +00:00
Thong Nguyen 83bc40d5fc More documentation. STKAutoRecoveringHTTPDataSource is now default for HTTP 2014-01-31 20:46:41 +00:00
Thong Nguyen b903ee58cc Formatting fixes 2014-01-31 20:39:51 +00:00
Thong Nguyen 70fe37cd4a Added missing status checks 2014-01-31 20:35:44 +00:00
Thong Nguyen f321f1a0d7 More code tidy-ups 2014-01-31 20:33:15 +00:00
Thong Nguyen a0a9553631 Big refactor to remove remanents of AudioQueue code. Added safety locks when working with 64bit floats and ints across threads 2014-01-31 20:20:20 +00:00
Thong Nguyen ddc6cf4b2f Fixed newly set datasource is not immediately loaded because render callback changes resets the STKAudioPlayerInternalStatePendingNext state 2014-01-31 15:12:30 +00:00
Thong Nguyen 22e954a5e2 Added AudioUnit based progress/seek and queueing support 2014-01-31 14:40:20 +00:00
Thong Nguyen e7a952d248 Progress and seek now supported 2014-01-31 12:22:22 +00:00
Thong Nguyen 511185c929 More Audio Units work 2014-01-30 18:22:31 +00:00
Thong Nguyen 15b18069e3 Started removing legacy AudioQueue code 2014-01-30 12:46:41 +00:00
Thong Nguyen 6df11418f7 Started removing legacy AudioQueue code 2014-01-30 12:46:26 +00:00
Thong Nguyen 9e04cc9e72 Merge branch 'master' of https://github.com/tumtumtum/StreamingKit 2014-01-29 23:31:34 +00:00
Thong Nguyen cdb6f27a53 Disabled input IO when creating Audio Unit 2014-01-29 22:40:34 +00:00
Thong Nguyen b8528e30c5 Added remote control event handling to AppDelegate so that example app will show play icon in status bar 2014-01-29 22:30:52 +00:00
Thong Nguyen d5e531c602 Removed AudioUnit kAudioUnitScope_Output init code 2014-01-29 22:26:31 +00:00
Thong Nguyen 8d61f3a3e3 Removed AudioUnit kAudioUnitScope_Output init code 2014-01-29 22:25:25 +00:00
Thong Nguyen b0466171f6 Removed AudioUnit kAudioUnitScope_Output init code 2014-01-29 22:22:23 +00:00
Thong Nguyen 10d799a35f Got basic playback mostly working using AudioUnits 2014-01-29 22:09:38 +00:00
Thong Nguyen 08eaa7e85b Some more test work with using Audio Units 2014-01-29 18:41:29 +00:00
Thong Nguyen cd0dd97ebf Started experimenting with using AudioUnits rather than AudioQueues 2014-01-29 09:38:24 +00:00
Thong Nguyen b2eeb76c90 Fix STKAutoRecoveringHTTPDataSource not passing on unregisterForEvents. Fix STKCoreFoundationDataSource not unregisteringForEvents on dealloc 2014-01-29 09:27:51 +00:00
Thong Nguyen 5a6d93d7c1 Started experimenting with using AudioUnits rather than AudioQueues 2014-01-28 20:53:03 +00:00
Thong Nguyen 8dd611c2ac Prefixed all enum names and values 2014-01-28 14:04:58 +00:00
Thong Nguyen 4a0f944550 Removed some logging 2014-01-28 13:55:00 +00:00
Thong Nguyen 0b5b6ada88 Return 0 duration and progress if stop was requested 2014-01-27 22:34:25 +00:00
Thong Nguyen f60e16c804 Tidied up some field types. Changed duration to return progress if progress is larger than duration and there is a duration 2014-01-27 21:33:10 +00:00
Thong Nguyen f3f52cf1cd Allow progress to be returned if the duration is 0 2014-01-27 19:46:35 +00:00
Thong Nguyen 53667f8a35 New lower-latecy rebuffering support 2014-01-27 19:38:32 +00:00
Thong Nguyen 6beebca443 Fixed deadlock on stopThread and dataSourceEof not always setting currentlReadingEntry to nil 2014-01-27 16:28:38 +00:00
Thong Nguyen 6af12221e5 Fixed potential crash in handleAudioPackets 2014-01-27 16:22:51 +00:00
Thong Nguyen ca80243083 Optimised seekToTime to avoid using the player thread mutex to allow smoother scrubbing 2014-01-27 02:00:01 +00:00
Thong Nguyen 804aa9dd6e All stopAudioQueue calls are now directed via the playback thread to reduce the need to have locks inside handleAudioQueueOutput. Added autorelease pool around regular processRunLoop call to fix STKDataSources not being freed (amongst other things). Fixed sometimes seeking to the very end of a slow loading track causes the didFinishPlayingQueueItemId event to not be raised 2014-01-27 01:23:18 +00:00
Thong Nguyen 0fdb461d90 Fixed bug in last commit that cuased playback to pause when seeking a file that's already fully buffered 2014-01-27 00:26:36 +00:00
Thong Nguyen 313a55a5ca Added more stable duration calculations 2014-01-26 23:57:00 +00:00
Thong Nguyen ba8b29d106 Fixed progress not correct when skipping a new track and the new track takes a while to buffer 2014-01-26 22:56:24 +00:00
Thong Nguyen 5b629665d6 createAudioQueue creates queues that start off paused by defualt to keep correct time if buffering is required befor the first buffers are rendered 2014-01-26 22:09:21 +00:00
Thong Nguyen 7608a42d29 Fixed dispose call hanging if player or audio thread are doing sync calls to the UI thread. Better rebuffering on 2G 2014-01-26 20:37:06 +00:00
Thong Nguyen 381795fed6 Fixed potential deadlock with clearQueue invokes callback on playback thread that may be blocking/waiting on audio packets 2014-01-26 15:43:39 +00:00
Thong Nguyen bd1d3c9aea A lot more support and fixups for rebuffering including new AudioPlayerStateBuffering state 2014-01-26 15:30:16 +00:00
Thong Nguyen 6ada345b17 Added better rebuffering handling. Pauses while rebuffering and doesn't start until there's a decent number of frames available 2014-01-26 01:04:24 +00:00
Thong Nguyen e495130219 More STKAutoRecoveringHTTPDataSource improvements 2014-01-25 14:30:41 +00:00
Thong Nguyen e843a0b730 Refactor and optimisation of STKHTTPDataSource and STKAutoRecoveringHTTPDataSource 2014-01-25 14:11:32 +00:00
Thong Nguyen b7f87aea98 Fixed next file won't start playing if queued on just before current one finishes 2014-01-25 13:59:11 +00:00
Thong Nguyen ca7abd75c1 Changed DataSources to open on-demand and also for callback registration to be performed before opening 2014-01-25 13:27:25 +00:00
Thong Nguyen 951f905516 Quite a big refactor to fix simplify and fix numerous threading and playback/position/buffering issues. Also all events are now synchronously raised to the UI thread via the playback thread which helps prevent lagged queued operations amongst other things 2014-01-24 19:11:52 +00:00
Thong Nguyen bd8e6a5da9 Fixes for errors when user skips to near the end of a track and another track is queued 2014-01-23 19:15:32 +00:00
Thong Nguyen 48ce1f9e67 Renamed all Http classes to HTTP. Udpated STKHTTPDataSource to accept asynchronous URL providers. Chnaged STKAudioPlaye to always flush upcoming queue when currently playing track is seeked 2014-01-23 16:23:18 +00:00
Thong Nguyen 257532c6c9 Added progress text to example app. Fixed finishedEvent not always being raised when user seeks to the last byte of the track 2014-01-23 12:43:22 +00:00
Thong Nguyen f85464236a Fix potential race/crash in createAudioQueue 2014-01-23 11:47:47 +00:00
Thong Nguyen b47771ae48 Formatting tidy-ups 2014-01-22 23:36:59 +00:00
Thong Nguyen 48e082ab88 Better default buffer sizes 2014-01-22 23:34:45 +00:00
Thong Nguyen b68e813750 Better default buffer sizes. Some code formatting tidy-ups 2014-01-22 23:33:49 +00:00
Thong Nguyen b4948882e4 Fixed async AudioQueue stop method for determing if a queued item has finished not taking into account upcoming queued items that aren't being decoded because they're incompatible 2014-01-22 22:52:51 +00:00
Thong Nguyen c100cb7202 Using a better mechanism for picking up when the last file on the queue is finished. Dont async-stop the AudioQueue unless it's nearing the end (handled in handleAudioQueueOutput rathe than dataSourceEof) 2014-01-22 22:41:24 +00:00
Thong Nguyen 593a08a04f Using a better mechanism for picking up when the last file on the queue is finished. Dont async-stop the AudioQueue unless it's nearing the end (handled in handleAudioQueueOutput rathe than dataSourceEof) 2014-01-22 22:40:23 +00:00
Thong Nguyen 1c9bd328e7 Removed test code and fixed an issue with not properly checking if the current queue should be stopped cause it's the last in the queue 2014-01-22 19:43:36 +00:00
Thong Nguyen dde738dffd Fixed finished event not raised if item is only item in queue. New timeline method of checking whether item has finished playing won't work if item is the only or last item in the queue as handleAudioQueueOutput isn't called once last packet is played (it's gets called if other items are queued). If no items are queued, the queue is stopped and the queue property event is used to figure out if its finished playing 2014-01-22 19:34:17 +00:00
Thong Nguyen a9bd3557a5 Changed progress to by more accurate by using AudioTime/timelines rather than bytes buffered 2014-01-22 16:52:47 +00:00
Thong Nguyen 431dd5d7f3 Moved AudioPlayerDefaultNumberOfAudioQueueBuffers define into source file from header 2014-01-22 10:25:30 +00:00
Thong Nguyen aaaed1f33f Added arm64 build back into StreamingKit. Moved private stuff out of STKAudioPlayer header files 2014-01-22 10:24:33 +00:00
Thong Nguyen 3563fb7ea1 Fixed STKHttpDataSource not copying urlProvider block 2014-01-22 09:38:37 +00:00
Thong Nguyen c9ba30b692 Removed iOS7 specific calls. Changed default target to iOS 4.3 2014-01-21 15:48:12 +00:00
Thong Nguyen c68384ec50 Added play:(NSString*) and playWithURL:(NSURL*) methods 2014-01-21 09:41:14 +00:00
Thong Nguyen 756504f33b Renamed QueueEntry to STKQueueEntry 2014-01-21 00:08:04 +00:00
Thong Nguyen 894dce8761 Updated README 2014-01-20 23:57:45 +00:00
Thong Nguyen c3a35fcdf3 Updated README 2014-01-20 23:57:18 +00:00
Thong Nguyen ce3f938309 Added playWithDataSource method. Updated README 2014-01-20 23:56:32 +00:00
Thong Nguyen 429c156d8b STKHttpDataSource now raises errors when failing to allocate resources for opening a stream 2014-01-20 23:47:55 +00:00
Thong Nguyen 0eb7687a63 Prevent crash when reading unsupported types and raise didEncounterError delegate callback 2014-01-20 23:22:41 +00:00
Thong Nguyen 9b952de734 Updated STKHttpDataSource to support dynamically generated URLs with each 'open' or 'seek') 2014-01-20 23:14:59 +00:00
Thong Nguyen 93e6f4b6d9 Fix namings of DataSources (added STK prefixes) 2014-01-20 22:30:35 +00:00
Thong Nguyen 9ed755cda4 Added kAudioFileAAC_ADTSType support 2014-01-20 21:11:00 +00:00
Thong Nguyen 7cc3f85a59 Fix README wiki link 2014-01-20 20:54:34 +00:00
Thong Nguyen a93d6867c5 Made the SampleApp support background playback. Updated README to point to wiki for background playbackr 2014-01-20 20:53:55 +00:00
Thong Nguyen 4660f0ce80 Fixed hard coded library search path in ExampleApp project 2014-01-20 19:22:48 +00:00
Thong Nguyen 6f37a24d1d Fixed StreamingKit.podspec 2014-01-20 15:54:52 +00:00
Thong Nguyen 18fc7353f9 Renamed project to StreamingKit and addded STK classes prefixes. Separated library and sample app into discrete projects inside a workspace. 2014-01-20 15:42:28 +00:00
Thong Nguyen 97ca05662f Merge pull request #58 from mostafaberg/patch-1
Removed an iOS7 Deprecated function
2014-01-18 04:14:02 -08:00
Mostafa Torbjørn Berg 3780b2a2bd Removed an iOS7 Deprecated function
Minor code change to avoid using CFReadStreamCopyProperty and also fail if an error occurs
2014-01-14 14:30:32 +01:00
Thong Nguyen 7af1dd38aa Merge pull request #48 from johnboiles/master
Fixing playback for short clips (fixes #43)
2013-12-05 02:17:36 -08:00
John Boiles eeab471c42 Fixing playback for short clips 2013-12-03 16:12:43 -08:00
Thong Nguyen d76c1c2160 Fix AutoRecoveringHttpDataSource raising even with wrong source ref 2013-11-18 16:01:41 +00:00
Thong Nguyen 8e90aed1a1 Added logging to catch potential HTTP data source errors 2013-11-18 15:20:42 +00:00
Thong Nguyen 4a38a20c3a Changed AutoRecoveringHttpDataSource to handle and recover from interrupted streams where CoreFoundation returns EOF rather than an error 2013-11-18 15:15:09 +00:00
Thong Nguyen 4a37599866 Added logging support 2013-11-15 15:51:50 +00:00
Thong Nguyen d5e7f986ac Updated Audjustable.podspec to 0.0.9 2013-10-23 11:48:15 +13:00
Thong Nguyen 6ac8851b9e Tidied up code 2013-10-23 11:24:59 +13:00
Thong Nguyen 062a320de6 Merge pull request #37 from johnboiles/master
Adding level metering APIs. Adding casts to get rid of Xcode warnings.
2013-10-22 15:17:43 -07:00
John Boiles 05f50e11d0 Adding level metering APIs, similar to those in AVAudioPlayer. 2013-10-15 18:26:01 -07:00
Thong Nguyen c213f8809a Merge pull request #36 from kevinrenskers/master
Added mute and unmute methods, increased version to 0.0.8
2013-10-15 18:06:54 -07:00
John Boiles 5baa7a07c2 Adding some casts to get rid of Xcode warnings. 2013-10-15 13:49:40 -07:00
Kevin Renskers 01629e7fdf Update podspec version 0.0.8 2013-10-10 13:10:27 +00:00
Kevin Renskers 1283cb31cc Added mute and unmute methods 2013-10-10 13:09:18 +00:00
Thong Nguyen 1a0b463a32 Udpated podspec to 0.0.7 2013-08-30 19:43:53 +02:00
Thong Nguyen aeb1ee1b7c Merge pull request #34 from ablinov/master
Removed test code
2013-08-30 10:40:10 -07:00
Alexey Blinov ec8b82b28f Removed test code 2013-08-30 18:34:57 +01:00
Thong Nguyen c84db3bcab Merge pull request #32 from terryso/master
Fixed AudioPlayer not calling the didEncounterError: method when an error occured
2013-08-04 16:03:26 -07:00
terryso cf14a035f6 Fixed AudioPlayer not calling the didEncounterError: method when an error occured 2013-08-01 10:12:19 +08:00
Thong Nguyen 8da9ea9545 Updated podspec to 0.0.6 2013-07-17 15:59:59 +01:00
Thong Nguyen ee387dc098 Fixed deadlock 2013-07-17 15:48:18 +01:00
Thong Nguyen c2d5d4000d Fixed playerMutex not being released sometimes (bug from last commit) 2013-07-16 16:31:45 +01:00
Thong Nguyen 65c1715269 Fix potential threading crash in [AudioPlayer duration] (I think). Moved to Apple provided spinlock implementation 2013-07-16 16:09:52 +01:00
Thong Nguyen 05965388cc Merge pull request #29 from steveluscher/patch-1
Readme: spelling, etc.
2013-07-10 07:17:54 -07:00
Steven Luscher ba4e44b8a2 Readme: spelling, etc. 2013-07-06 11:59:32 -07:00
Thong Nguyen 08287bc6a7 Merge pull request #24 from gangverk/master
Add support for HE-AAC
2013-05-17 11:26:45 -07:00
Piers dd3bd913b5 Update podspec to version 0.0.5 2013-05-17 17:22:32 +00:00
Piers f8887b7ff1 Add support for HE-AAC
The code for handling HE-AAC has been copied from Matt Gallagher's
AudioStreamer library.

https://github.com/mattgallagher/AudioStreamer/blob/master/Classes/AudioStreamer.m#L1605
2013-05-15 16:29:24 +00:00
Thong Nguyen 6d2b656a58 Updated README 2013-05-03 18:46:34 +01:00
Thong Nguyen 02e87c1221 Merge branch 'master' of https://github.com/tumtumtum/audjustable 2013-04-17 13:07:51 +01:00
Thong Nguyen d52c012514 Some format fixes 2013-04-17 13:07:48 +01:00
Thong Nguyen ea64e5cd71 Merge pull request #20 from gangverk/master
Continual allocation of NSDate objects in [AudioPlayer startInterval]
2013-04-17 05:06:26 -07:00
Piers 7a7ba985b8 Merge pull request #2 from gangverk/bugfix/continuous-date-allocation
Bugfix/continuous date allocation
2013-04-17 03:14:06 -07:00
Piers 91640f6207 Update podspec version 2013-04-17 10:12:07 +00:00
Piers 4a60b768be Merge branch 'master' into bugfix/continuous-date-allocation 2013-04-17 10:11:18 +00:00
Piers 6d5fdd2450 Merge pull request #1 from gangverk/bugfix/continuous-date-allocation
Fix continual allocation of auto-releaseable NSDate objects
2013-04-17 02:53:33 -07:00
Piers 4e019bfcf2 Fix continual allocation of auto-releaseable NSDate objects
The startInterval method of the AudioPlayer module causes a
continually increasing number of NSDate objects to be
allocated. The auto-release pool which wraps this code doesn't
drain frequently enough causing an application's memory
footprint to grow by roughly a megabyte every 5 minutes.
2013-04-17 09:37:57 +00:00
Thong Nguyen bed5fe1f04 Updated podspec for version 0.0.3 2013-04-10 12:28:38 +01:00
79 changed files with 8416 additions and 3853 deletions
-13
View File
@@ -1,13 +0,0 @@
Pod::Spec.new do |s|
s.name = "Audjustable"
s.version = "0.0.2"
s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources."
s.homepage = "http://tumtumtum.github.com/audjustable/"
s.license = 'MIT'
s.author = { "Thong Nguyen" => "tumtumtum@gmail.com" }
s.source = { :git => "https://github.com/gangverk/audjustable.git", :tag => s.version.to_s}
s.platform = :ios
s.requires_arc = true
s.source_files = 'Audjustable/Classes/AudioPlayer/*.{h,m}'
s.frameworks = 'AVFoundation', 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox'
end
-480
View File
@@ -1,480 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
8AC7AD4816E55CD70069BDE7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B4E5157F80E700BD0084 /* Foundation.framework */; };
8AC7AD5416E55D260069BDE7 /* AutoRecoveringHttpDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A16CB9AA162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m */; };
8AC7AD5616E55D260069BDE7 /* DataSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = A16CB9AC162EC4AB00CFD1E8 /* DataSourceWrapper.m */; };
8AC7AD5816E55D260069BDE7 /* AudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B501157F813100BD0084 /* AudioPlayer.m */; };
8AC7AD5A16E55D260069BDE7 /* CoreFoundationDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B503157F813100BD0084 /* CoreFoundationDataSource.m */; };
8AC7AD5C16E55D260069BDE7 /* DataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B505157F813100BD0084 /* DataSource.m */; };
8AC7AD5E16E55D260069BDE7 /* HttpDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B507157F813100BD0084 /* HttpDataSource.m */; };
8AC7AD6016E55D260069BDE7 /* LocalFileDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B509157F813100BD0084 /* LocalFileDataSource.m */; };
A16CB9AD162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A16CB9AA162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m */; };
A16CB9AE162EC4AB00CFD1E8 /* DataSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = A16CB9AC162EC4AB00CFD1E8 /* DataSourceWrapper.m */; };
A16CB9B1162EC5E300CFD1E8 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A16CB9B0162EC5E300CFD1E8 /* SystemConfiguration.framework */; };
A16CB9B3162EC5E900CFD1E8 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A16CB9B2162EC5E900CFD1E8 /* Default-568h@2x.png */; };
A186B4E4157F80E700BD0084 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B4E3157F80E700BD0084 /* UIKit.framework */; };
A186B4E6157F80E700BD0084 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B4E5157F80E700BD0084 /* Foundation.framework */; };
A186B4EE157F80E700BD0084 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A186B4EC157F80E700BD0084 /* InfoPlist.strings */; };
A186B4F0157F80E700BD0084 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B4EF157F80E700BD0084 /* main.m */; };
A186B4F4157F80E700BD0084 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B4F3157F80E700BD0084 /* AppDelegate.m */; };
A186B50C157F813100BD0084 /* AudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B501157F813100BD0084 /* AudioPlayer.m */; };
A186B50D157F813100BD0084 /* CoreFoundationDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B503157F813100BD0084 /* CoreFoundationDataSource.m */; };
A186B50E157F813100BD0084 /* DataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B505157F813100BD0084 /* DataSource.m */; };
A186B50F157F813100BD0084 /* HttpDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B507157F813100BD0084 /* HttpDataSource.m */; };
A186B510157F813100BD0084 /* LocalFileDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B509157F813100BD0084 /* LocalFileDataSource.m */; };
A186B511157F813100BD0084 /* AudioPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = A186B50B157F813100BD0084 /* AudioPlayerView.m */; };
A186B514157F817500BD0084 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B513157F817500BD0084 /* AudioToolbox.framework */; };
A186B518157F818900BD0084 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B517157F818900BD0084 /* CoreFoundation.framework */; };
A186B51A157F819500BD0084 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A186B519157F819500BD0084 /* CFNetwork.framework */; };
A186B51D157F825400BD0084 /* sample.m4a in Resources */ = {isa = PBXBuildFile; fileRef = A186B51C157F820F00BD0084 /* sample.m4a */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
8AC7AD4516E55CD70069BDE7 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "include/${PRODUCT_NAME}";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
8AC7AD4716E55CD70069BDE7 /* libaudjustable.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libaudjustable.a; sourceTree = BUILT_PRODUCTS_DIR; };
A16CB9A9162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoRecoveringHttpDataSource.h; sourceTree = "<group>"; };
A16CB9AA162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoRecoveringHttpDataSource.m; sourceTree = "<group>"; };
A16CB9AB162EC4AB00CFD1E8 /* DataSourceWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataSourceWrapper.h; sourceTree = "<group>"; };
A16CB9AC162EC4AB00CFD1E8 /* DataSourceWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataSourceWrapper.m; sourceTree = "<group>"; };
A16CB9B0162EC5E300CFD1E8 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
A16CB9B2162EC5E900CFD1E8 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = "<group>"; };
A186B4DF157F80E600BD0084 /* Audjustable.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Audjustable.app; sourceTree = BUILT_PRODUCTS_DIR; };
A186B4E3157F80E700BD0084 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
A186B4E5157F80E700BD0084 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
A186B4E7157F80E700BD0084 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
A186B4EB157F80E700BD0084 /* Audjustable-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Audjustable-Info.plist"; sourceTree = "<group>"; };
A186B4ED157F80E700BD0084 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
A186B4EF157F80E700BD0084 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
A186B4F1157F80E700BD0084 /* Audjustable-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Audjustable-Prefix.pch"; sourceTree = "<group>"; };
A186B4F2157F80E700BD0084 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
A186B4F3157F80E700BD0084 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
A186B500157F813100BD0084 /* AudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPlayer.h; sourceTree = "<group>"; };
A186B501157F813100BD0084 /* AudioPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioPlayer.m; sourceTree = "<group>"; };
A186B502157F813100BD0084 /* CoreFoundationDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreFoundationDataSource.h; sourceTree = "<group>"; };
A186B503157F813100BD0084 /* CoreFoundationDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreFoundationDataSource.m; sourceTree = "<group>"; };
A186B504157F813100BD0084 /* DataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataSource.h; sourceTree = "<group>"; };
A186B505157F813100BD0084 /* DataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataSource.m; sourceTree = "<group>"; };
A186B506157F813100BD0084 /* HttpDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpDataSource.h; sourceTree = "<group>"; };
A186B507157F813100BD0084 /* HttpDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpDataSource.m; sourceTree = "<group>"; };
A186B508157F813100BD0084 /* LocalFileDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalFileDataSource.h; sourceTree = "<group>"; };
A186B509157F813100BD0084 /* LocalFileDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalFileDataSource.m; sourceTree = "<group>"; };
A186B50A157F813100BD0084 /* AudioPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPlayerView.h; sourceTree = "<group>"; };
A186B50B157F813100BD0084 /* AudioPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioPlayerView.m; sourceTree = "<group>"; };
A186B513157F817500BD0084 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
A186B517157F818900BD0084 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
A186B519157F819500BD0084 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
A186B51C157F820F00BD0084 /* sample.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = sample.m4a; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8AC7AD4416E55CD70069BDE7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8AC7AD4816E55CD70069BDE7 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A186B4DC157F80E600BD0084 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A16CB9B1162EC5E300CFD1E8 /* SystemConfiguration.framework in Frameworks */,
A186B51A157F819500BD0084 /* CFNetwork.framework in Frameworks */,
A186B518157F818900BD0084 /* CoreFoundation.framework in Frameworks */,
A186B514157F817500BD0084 /* AudioToolbox.framework in Frameworks */,
A186B4E4157F80E700BD0084 /* UIKit.framework in Frameworks */,
A186B4E6157F80E700BD0084 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
A186B4D4157F80E600BD0084 = {
isa = PBXGroup;
children = (
A186B4E9157F80E700BD0084 /* Audjustable */,
A186B4E2157F80E700BD0084 /* Frameworks */,
A186B4E0157F80E600BD0084 /* Products */,
);
sourceTree = "<group>";
};
A186B4E0157F80E600BD0084 /* Products */ = {
isa = PBXGroup;
children = (
A186B4DF157F80E600BD0084 /* Audjustable.app */,
8AC7AD4716E55CD70069BDE7 /* libaudjustable.a */,
);
name = Products;
sourceTree = "<group>";
};
A186B4E2157F80E700BD0084 /* Frameworks */ = {
isa = PBXGroup;
children = (
A16CB9B0162EC5E300CFD1E8 /* SystemConfiguration.framework */,
A186B519157F819500BD0084 /* CFNetwork.framework */,
A186B517157F818900BD0084 /* CoreFoundation.framework */,
A186B513157F817500BD0084 /* AudioToolbox.framework */,
A186B4E3157F80E700BD0084 /* UIKit.framework */,
A186B4E5157F80E700BD0084 /* Foundation.framework */,
A186B4E7157F80E700BD0084 /* CoreGraphics.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
A186B4E9157F80E700BD0084 /* Audjustable */ = {
isa = PBXGroup;
children = (
A186B4FE157F813100BD0084 /* Classes */,
A186B4F2157F80E700BD0084 /* AppDelegate.h */,
A186B4F3157F80E700BD0084 /* AppDelegate.m */,
A186B4EA157F80E700BD0084 /* Supporting Files */,
);
path = Audjustable;
sourceTree = "<group>";
};
A186B4EA157F80E700BD0084 /* Supporting Files */ = {
isa = PBXGroup;
children = (
A186B51B157F81D900BD0084 /* Resources */,
A186B4EB157F80E700BD0084 /* Audjustable-Info.plist */,
A186B4EC157F80E700BD0084 /* InfoPlist.strings */,
A16CB9B2162EC5E900CFD1E8 /* Default-568h@2x.png */,
A186B4EF157F80E700BD0084 /* main.m */,
A186B4F1157F80E700BD0084 /* Audjustable-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
A186B4FE157F813100BD0084 /* Classes */ = {
isa = PBXGroup;
children = (
A186B4FF157F813100BD0084 /* AudioPlayer */,
A186B50A157F813100BD0084 /* AudioPlayerView.h */,
A186B50B157F813100BD0084 /* AudioPlayerView.m */,
);
path = Classes;
sourceTree = "<group>";
};
A186B4FF157F813100BD0084 /* AudioPlayer */ = {
isa = PBXGroup;
children = (
A16CB9A9162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.h */,
A16CB9AA162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m */,
A16CB9AB162EC4AB00CFD1E8 /* DataSourceWrapper.h */,
A16CB9AC162EC4AB00CFD1E8 /* DataSourceWrapper.m */,
A186B500157F813100BD0084 /* AudioPlayer.h */,
A186B501157F813100BD0084 /* AudioPlayer.m */,
A186B502157F813100BD0084 /* CoreFoundationDataSource.h */,
A186B503157F813100BD0084 /* CoreFoundationDataSource.m */,
A186B504157F813100BD0084 /* DataSource.h */,
A186B505157F813100BD0084 /* DataSource.m */,
A186B506157F813100BD0084 /* HttpDataSource.h */,
A186B507157F813100BD0084 /* HttpDataSource.m */,
A186B508157F813100BD0084 /* LocalFileDataSource.h */,
A186B509157F813100BD0084 /* LocalFileDataSource.m */,
);
path = AudioPlayer;
sourceTree = "<group>";
};
A186B51B157F81D900BD0084 /* Resources */ = {
isa = PBXGroup;
children = (
A186B51C157F820F00BD0084 /* sample.m4a */,
);
name = Resources;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
8AC7AD4616E55CD70069BDE7 /* audjustable */ = {
isa = PBXNativeTarget;
buildConfigurationList = 8AC7AD5016E55CD70069BDE7 /* Build configuration list for PBXNativeTarget "audjustable" */;
buildPhases = (
8AC7AD4316E55CD70069BDE7 /* Sources */,
8AC7AD4416E55CD70069BDE7 /* Frameworks */,
8AC7AD4516E55CD70069BDE7 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = audjustable;
productName = audjustable;
productReference = 8AC7AD4716E55CD70069BDE7 /* libaudjustable.a */;
productType = "com.apple.product-type.library.static";
};
A186B4DE157F80E600BD0084 /* Audjustable */ = {
isa = PBXNativeTarget;
buildConfigurationList = A186B4F7157F80E700BD0084 /* Build configuration list for PBXNativeTarget "Audjustable" */;
buildPhases = (
A186B4DB157F80E600BD0084 /* Sources */,
A186B4DC157F80E600BD0084 /* Frameworks */,
A186B4DD157F80E600BD0084 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Audjustable;
productName = Audjustable;
productReference = A186B4DF157F80E600BD0084 /* Audjustable.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A186B4D6157F80E600BD0084 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0460;
};
buildConfigurationList = A186B4D9157F80E600BD0084 /* Build configuration list for PBXProject "Audjustable" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = A186B4D4157F80E600BD0084;
productRefGroup = A186B4E0157F80E600BD0084 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
A186B4DE157F80E600BD0084 /* Audjustable */,
8AC7AD4616E55CD70069BDE7 /* audjustable */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
A186B4DD157F80E600BD0084 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A186B4EE157F80E700BD0084 /* InfoPlist.strings in Resources */,
A186B51D157F825400BD0084 /* sample.m4a in Resources */,
A16CB9B3162EC5E900CFD1E8 /* Default-568h@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8AC7AD4316E55CD70069BDE7 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8AC7AD5416E55D260069BDE7 /* AutoRecoveringHttpDataSource.m in Sources */,
8AC7AD5616E55D260069BDE7 /* DataSourceWrapper.m in Sources */,
8AC7AD5816E55D260069BDE7 /* AudioPlayer.m in Sources */,
8AC7AD5A16E55D260069BDE7 /* CoreFoundationDataSource.m in Sources */,
8AC7AD5C16E55D260069BDE7 /* DataSource.m in Sources */,
8AC7AD5E16E55D260069BDE7 /* HttpDataSource.m in Sources */,
8AC7AD6016E55D260069BDE7 /* LocalFileDataSource.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A186B4DB157F80E600BD0084 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A186B4F0157F80E700BD0084 /* main.m in Sources */,
A186B4F4157F80E700BD0084 /* AppDelegate.m in Sources */,
A186B50C157F813100BD0084 /* AudioPlayer.m in Sources */,
A186B50D157F813100BD0084 /* CoreFoundationDataSource.m in Sources */,
A186B50E157F813100BD0084 /* DataSource.m in Sources */,
A186B50F157F813100BD0084 /* HttpDataSource.m in Sources */,
A186B510157F813100BD0084 /* LocalFileDataSource.m in Sources */,
A186B511157F813100BD0084 /* AudioPlayerView.m in Sources */,
A16CB9AD162EC4AB00CFD1E8 /* AutoRecoveringHttpDataSource.m in Sources */,
A16CB9AE162EC4AB00CFD1E8 /* DataSourceWrapper.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
A186B4EC157F80E700BD0084 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
A186B4ED157F80E700BD0084 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
8AC7AD5116E55CD70069BDE7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DSTROOT = /tmp/audjustable.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "audjustable/audjustable-Prefix.pch";
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
8AC7AD5216E55CD70069BDE7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DSTROOT = /tmp/audjustable.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "audjustable/audjustable-Prefix.pch";
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
A186B4F5157F80E700BD0084 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
A186B4F6157F80E700BD0084 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
A186B4F8157F80E700BD0084 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Audjustable/Audjustable-Prefix.pch";
INFOPLIST_FILE = "Audjustable/Audjustable-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
A186B4F9157F80E700BD0084 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Audjustable/Audjustable-Prefix.pch";
INFOPLIST_FILE = "Audjustable/Audjustable-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
8AC7AD5016E55CD70069BDE7 /* Build configuration list for PBXNativeTarget "audjustable" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8AC7AD5116E55CD70069BDE7 /* Debug */,
8AC7AD5216E55CD70069BDE7 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A186B4D9157F80E600BD0084 /* Build configuration list for PBXProject "Audjustable" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A186B4F5157F80E700BD0084 /* Debug */,
A186B4F6157F80E700BD0084 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A186B4F7157F80E700BD0084 /* Build configuration list for PBXNativeTarget "Audjustable" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A186B4F8157F80E700BD0084 /* Debug */,
A186B4F9157F80E700BD0084 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = A186B4D6157F80E600BD0084 /* Project object */;
}
@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0460"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A186B4DE157F80E600BD0084"
BuildableName = "Audjustable.app"
BlueprintName = "Audjustable"
ReferencedContainer = "container:Audjustable.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A186B4DE157F80E600BD0084"
BuildableName = "Audjustable.app"
BlueprintName = "Audjustable"
ReferencedContainer = "container:Audjustable.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A186B4DE157F80E600BD0084"
BuildableName = "Audjustable.app"
BlueprintName = "Audjustable"
ReferencedContainer = "container:Audjustable.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A186B4DE157F80E600BD0084"
BuildableName = "Audjustable.app"
BlueprintName = "Audjustable"
ReferencedContainer = "container:Audjustable.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0460"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8AC7AD4616E55CD70069BDE7"
BuildableName = "libaudjustable.a"
BlueprintName = "audjustable"
ReferencedContainer = "container:Audjustable.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
-50
View File
@@ -1,50 +0,0 @@
//
// AppDelegate.m
// BlueCucumber-AudioPlayer
//
// Created by Thong Nguyen on 01/06/2012.
// Copyright (c) 2012 Thong Nguyen All rights reserved.
//
#import "AppDelegate.h"
#import "AudioPlayerView.h"
@implementation AppDelegate
@synthesize window = _window;
-(BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
audioPlayer = [[AudioPlayer alloc] init];
AudioPlayerView* audioPlayerView = [[AudioPlayerView alloc] initWithFrame:self.window.bounds];
audioPlayerView.delegate = self;
audioPlayerView.audioPlayer = audioPlayer;
[self.window addSubview:audioPlayerView];
[self.window makeKeyAndVisible];
return YES;
}
-(void) audioPlayerViewPlayFromHTTPSelected:(AudioPlayerView*)audioPlayerView
{
NSURL* url = [NSURL URLWithString:@"http://fs.bloom.fm/oss/audiosamples/sample.mp3"];
[audioPlayer setDataSource:[audioPlayer dataSourceFromURL:url] withQueueItemId:url];
}
-(void) audioPlayerViewPlayFromLocalFileSelected:(AudioPlayerView*)audioPlayerView
{
NSString * path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"m4a"];
NSURL* url = [NSURL fileURLWithPath:path];
[audioPlayer setDataSource:[audioPlayer dataSourceFromURL:url] withQueueItemId:url];
}
@end
@@ -1,197 +0,0 @@
/**********************************************************************************
AudioPlayer.m
Created by Thong Nguyen on 14/05/2012.
https://github.com/tumtumtum/audjustable
Inspired by Matt Gallagher's AudioStreamer:
https://github.com/mattgallagher/AudioStreamer
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import <Foundation/Foundation.h>
#import <pthread.h>
#import "DataSource.h"
#include <AudioToolbox/AudioToolbox.h>
#define AudioPlayerDefaultNumberOfAudioQueueBuffers (2 * 1024)
typedef enum
{
AudioPlayerInternalStateInitialised = 0,
AudioPlayerInternalStateRunning = 1,
AudioPlayerInternalStatePlaying = (1 << 1) | AudioPlayerInternalStateRunning,
AudioPlayerInternalStateStartingThread = (1 << 2) | AudioPlayerInternalStateRunning,
AudioPlayerInternalStateWaitingForData = (1 << 3) | AudioPlayerInternalStateRunning,
AudioPlayerInternalStateWaitingForQueueToStart = (1 << 4) | AudioPlayerInternalStateRunning,
AudioPlayerInternalStatePaused = (1 << 5) | AudioPlayerInternalStateRunning,
AudioPlayerInternalStateRebuffering = (1 << 6) | AudioPlayerInternalStateRunning,
AudioPlayerInternalStateStopping = (1 << 7),
AudioPlayerInternalStateStopped = (1 << 8),
AudioPlayerInternalStateDisposed = (1 << 9),
AudioPlayerInternalStateError = (1 << 10)
}
AudioPlayerInternalState;
typedef enum
{
AudioPlayerStateReady,
AudioPlayerStateRunning = 1,
AudioPlayerStatePlaying = (1 << 1) | AudioPlayerStateRunning,
AudioPlayerStatePaused = (1 << 2) | AudioPlayerStateRunning,
AudioPlayerStateStopped = (1 << 3),
AudioPlayerStateError = (1 << 4),
AudioPlayerStateDisposed = (1 << 5)
}
AudioPlayerState;
typedef enum
{
AudioPlayerStopReasonNoStop = 0,
AudioPlayerStopReasonEof,
AudioPlayerStopReasonUserAction,
AudioPlayerStopReasonUserActionFlushStop
}
AudioPlayerStopReason;
typedef enum
{
AudioPlayerErrorNone = 0,
AudioPlayerErrorDataSource,
AudioPlayerErrorStreamParseBytesFailed,
AudioPlayerErrorDataNotFound,
AudioPlayerErrorQueueStartFailed,
AudioPlayerErrorQueuePauseFailed,
AudioPlayerErrorUnknownBuffer,
AudioPlayerErrorQueueStopFailed,
AudioPlayerErrorOther
}
AudioPlayerErrorCode;
@class AudioPlayer;
@protocol AudioPlayerDelegate <NSObject>
-(void) audioPlayer:(AudioPlayer*)audioPlayer stateChanged:(AudioPlayerState)state;
-(void) audioPlayer:(AudioPlayer*)audioPlayer didEncounterError:(AudioPlayerErrorCode)errorCode;
-(void) audioPlayer:(AudioPlayer*)audioPlayer didStartPlayingQueueItemId:(NSObject*)queueItemId;
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId;
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(AudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration;
@optional
-(void) audioPlayer:(AudioPlayer*)audioPlayer internalStateChanged:(AudioPlayerInternalState)state;
-(void) audioPlayer:(AudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems;
@end
@class QueueEntry;
typedef struct
{
AudioQueueBufferRef ref;
int bufferIndex;
}
AudioQueueBufferRefLookupEntry;
@interface AudioPlayer : NSObject<DataSourceDelegate>
{
@private
UInt8* readBuffer;
int readBufferSize;
NSOperationQueue* fastApiQueue;
QueueEntry* currentlyPlayingEntry;
QueueEntry* currentlyReadingEntry;
NSMutableArray* upcomingQueue;
NSMutableArray* bufferingQueue;
AudioQueueBufferRef* audioQueueBuffer;
AudioQueueBufferRefLookupEntry* audioQueueBufferLookup;
unsigned int audioQueueBufferRefLookupCount;
unsigned int audioQueueBufferCount;
AudioStreamPacketDescription* packetDescs;
bool* bufferUsed;
int numberOfBuffersUsed;
AudioQueueRef audioQueue;
AudioStreamBasicDescription currentAudioStreamBasicDescription;
NSThread* playbackThread;
NSRunLoop* playbackThreadRunLoop;
NSConditionLock* threadFinishedCondLock;
AudioFileStreamID audioFileStream;
BOOL discontinuous;
int bytesFilled;
int packetsFilled;
int fillBufferIndex;
UIBackgroundTaskIdentifier backgroundTaskId;
AudioPlayerErrorCode errorCode;
AudioPlayerStopReason stopReason;
int currentlyPlayingLock;
pthread_mutex_t playerMutex;
pthread_mutex_t queueBuffersMutex;
pthread_cond_t queueBufferReadyCondition;
volatile BOOL waiting;
volatile BOOL disposeWasRequested;
volatile BOOL seekToTimeWasRequested;
volatile BOOL newFileToPlay;
volatile double requestedSeekTime;
volatile BOOL audioQueueFlushing;
volatile SInt64 audioPacketsReadCount;
volatile SInt64 audioPacketsPlayedCount;
}
@property (readonly) double duration;
@property (readonly) double progress;
@property (readwrite) AudioPlayerState state;
@property (readonly) AudioPlayerStopReason stopReason;
@property (readwrite, unsafe_unretained) id<AudioPlayerDelegate> delegate;
-(id) init;
-(id) initWithNumberOfAudioQueueBuffers:(int)numberOfAudioQueueBuffers andReadBufferSize:(int)readBufferSizeIn;
-(DataSource*) dataSourceFromURL:(NSURL*)url;
-(void) play:(NSURL*)url;
-(void) queueDataSource:(DataSource*)dataSource withQueueItemId:(NSObject*)queueItemId;
-(void) setDataSource:(DataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId;
-(void) seekToTime:(double)value;
-(void) pause;
-(void) resume;
-(void) stop;
-(void) flushStop;
-(void) dispose;
-(NSObject*) currentlyPlayingQueueItemId;
@end
File diff suppressed because it is too large Load Diff
@@ -1,200 +0,0 @@
/**********************************************************************************
AudioPlayer.m
Created by Thong Nguyen on 16/10/2012.
https://github.com/tumtumtum/audjustable
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import <sys/socket.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import "AutoRecoveringHttpDataSource.h"
#define MAX_IMMEDIATE_RECONNECT_ATTEMPTS (8)
@interface AutoRecoveringHttpDataSource()
{
int reconnectAttempts;
BOOL waitingForNetwork;
SCNetworkReachabilityRef reachabilityRef;
}
-(void) reachabilityChanged;
@end
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
@autoreleasepool
{
AutoRecoveringHttpDataSource* dataSource = (__bridge AutoRecoveringHttpDataSource*)info;
[dataSource reachabilityChanged];
}
}
@implementation AutoRecoveringHttpDataSource
-(HttpDataSource*) innerHttpDataSource
{
return (HttpDataSource*)self.innerDataSource;
}
-(id) initWithHttpDataSource:(HttpDataSource*)innerDataSourceIn
{
if (self = [super initWithDataSource:innerDataSourceIn])
{
self.innerDataSource.delegate = self;
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
reachabilityRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
}
return self;
}
-(BOOL) startNotifierOnRunLoop:(NSRunLoop*)runLoop
{
BOOL retVal = NO;
SCNetworkReachabilityContext context = { 0, (__bridge void*)self, NULL, NULL, NULL };
if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
{
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, runLoop.getCFRunLoop, kCFRunLoopDefaultMode))
{
retVal = YES;
}
}
return retVal;
}
-(BOOL) registerForEvents:(NSRunLoop*)runLoop
{
[super registerForEvents:runLoop];
[self startNotifierOnRunLoop:runLoop];
return YES;
}
-(void) unregisterForEvents
{
[self stopNotifier];
}
-(void) stopNotifier
{
if (reachabilityRef != NULL)
{
SCNetworkReachabilitySetCallback(reachabilityRef, NULL, NULL);
SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
}
-(BOOL) hasGotNetworkConnection
{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
return ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
}
return NO;
}
-(void) dealloc
{
self.innerDataSource.delegate = nil;
[self stopNotifier];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if (reachabilityRef!= NULL)
{
CFRelease(reachabilityRef);
}
}
-(void) reachabilityChanged
{
if (waitingForNetwork)
{
waitingForNetwork = NO;
[self attemptReconnect];
}
}
-(void) dataSourceDataAvailable:(DataSource*)dataSource
{
reconnectAttempts = 0;
[super dataSourceDataAvailable:dataSource];
}
-(void) attemptReconnect
{
reconnectAttempts++;
[self seekToOffset:self.position];
}
-(void) dataSourceErrorOccured:(DataSource*)dataSource
{
if (![self hasGotNetworkConnection])
{
waitingForNetwork = YES;
return;
}
if (reconnectAttempts > MAX_IMMEDIATE_RECONNECT_ATTEMPTS)
{
[self performSelector:@selector(attemptReconnect) withObject:nil afterDelay:5];
}
else
{
[self attemptReconnect];
}
}
@end
@@ -1,236 +0,0 @@
/**********************************************************************************
AudioPlayer.m
Created by Thong Nguyen on 14/05/2012.
https://github.com/tumtumtum/audjustable
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "HttpDataSource.h"
#import "LocalFileDataSource.h"
@interface HttpDataSource()
-(void) open;
@end
@implementation HttpDataSource
@synthesize url;
-(id) initWithURL:(NSURL*)urlIn
{
if (self = [super init])
{
seekStart = 0;
relativePosition = 0;
fileLength = -1;
self.url = urlIn;
[self open];
audioFileTypeHint = [LocalFileDataSource audioFileTypeHintFromFileExtension:urlIn.pathExtension];
}
return self;
}
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)mimeType
{
static dispatch_once_t onceToken;
static NSDictionary* fileTypesByMimeType;
dispatch_once(&onceToken, ^
{
fileTypesByMimeType =
@{
@"audio/mp3": @(kAudioFileMP3Type),
@"audio/mpg": @(kAudioFileMP3Type),
@"audio/mpeg": @(kAudioFileMP3Type),
@"audio/wav": @(kAudioFileWAVEType),
@"audio/aifc": @(kAudioFileAIFCType),
@"audio/aiff": @(kAudioFileAIFFType),
@"audio/x-m4a": @(kAudioFileM4AType),
@"audio/x-mp4": @(kAudioFileMPEG4Type),
@"audio/m4a": @(kAudioFileM4AType),
@"audio/mp4": @(kAudioFileMPEG4Type),
@"audio/caf": @(kAudioFileCAFType),
@"audio/aac": @(kAudioFileAAC_ADTSType),
@"audio/ac3": @(kAudioFileAC3Type),
@"audio/3gp": @(kAudioFile3GPType)
};
});
NSNumber* number = [fileTypesByMimeType objectForKey:mimeType];
if (!number)
{
return 0;
}
return (AudioFileTypeID)number.intValue;
}
-(AudioFileTypeID) audioFileTypeHint
{
return audioFileTypeHint;
}
-(void) dataAvailable
{
if (fileLength < 0)
{
CFTypeRef copyPropertyMessage = CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
httpHeaders = (__bridge_transfer NSDictionary*)CFHTTPMessageCopyAllHeaderFields((CFHTTPMessageRef)copyPropertyMessage);
CFRelease(copyPropertyMessage);
if (seekStart == 0)
{
fileLength = [[httpHeaders objectForKey:@"Content-Length"] integerValue];
}
NSString* contentType = [httpHeaders objectForKey:@"Content-Type"];
AudioFileTypeID typeIdFromMimeType = [HttpDataSource audioFileTypeHintFromMimeType:contentType];
if (typeIdFromMimeType != 0)
{
audioFileTypeHint = typeIdFromMimeType;
}
}
[super dataAvailable];
}
-(long long) position
{
return seekStart + relativePosition;
}
-(long long) length
{
return fileLength >= 0 ? fileLength : 0;
}
-(void) seekToOffset:(long long)offset
{
if (eventsRunLoop)
{
[self unregisterForEvents];
}
if (stream)
{
CFReadStreamClose(stream);
CFRelease(stream);
}
stream = 0;
relativePosition = 0;
seekStart = offset;
[self open];
[self reregisterForEvents];
}
-(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size
{
if (size == 0)
{
return 0;
}
int read = CFReadStreamRead(stream, buffer, size);
if (read < 0)
{
return read;
}
relativePosition += read;
return read;
}
-(void) open
{
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)self.url, kCFHTTPVersion1_1);
if (seekStart > 0)
{
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), (__bridge CFStringRef)[NSString stringWithFormat:@"bytes=%d-", seekStart]);
discontinuous = YES;
}
stream = CFReadStreamCreateForHTTPRequest(NULL, message);
if (!CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue))
{
CFRelease(message);
return;
}
// Proxy support
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPProxy, proxySettings);
CFRelease(proxySettings);
// SSL support
if ([url.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)
{
NSDictionary* sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
[NSNull null], kCFStreamSSLPeerName,
nil];
CFReadStreamSetProperty(stream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)sslSettings);
}
// Open
if (!CFReadStreamOpen(stream))
{
CFRelease(stream);
CFRelease(message);
return;
}
CFRelease(message);
}
@end
-207
View File
@@ -1,207 +0,0 @@
/**********************************************************************************
AudioPlayer.m
Created by Thong Nguyen on 14/05/2012.
https://github.com/tumtumtum/audjustable
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "AudioPlayerView.h"
@interface AudioPlayerView()
-(void) setupTimer;
-(void) updateControls;
@end
@implementation AudioPlayerView
@synthesize audioPlayer, delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
CGSize size = CGSizeMake(180, 50);
playFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playFromHTTPButton.frame = CGRectMake((320 - size.width) / 2, 60, size.width, size.height);
[playFromHTTPButton addTarget:self action:@selector(playFromHTTPButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[playFromHTTPButton setTitle:@"Play from HTTP" forState:UIControlStateNormal];
playFromLocalFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playFromLocalFileButton.frame = CGRectMake((320 - size.width) / 2, 120, size.width, size.height);
[playFromLocalFileButton addTarget:self action:@selector(playFromLocalFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[playFromLocalFileButton setTitle:@"Play from Local File" forState:UIControlStateNormal];
playButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playButton.frame = CGRectMake((320 - size.width) / 2, 350, size.width, size.height);
[playButton addTarget:self action:@selector(playButtonPressed) forControlEvents:UIControlEventTouchUpInside];
slider = [[UISlider alloc] initWithFrame:CGRectMake(20, 290, 280, 20)];
slider.continuous = YES;
[slider addTarget:self action:@selector(sliderChanged) forControlEvents:UIControlEventValueChanged];
[self addSubview:slider];
[self addSubview:playButton];
[self addSubview:playFromHTTPButton];
[self addSubview:playFromLocalFileButton];
[self setupTimer];
[self updateControls];
}
return self;
}
-(void) sliderChanged
{
if (!audioPlayer)
{
return;
}
NSLog(@"Slider Changed: %f", slider.value);
[audioPlayer seekToTime:slider.value];
}
-(void) setupTimer
{
timer = [NSTimer timerWithTimeInterval:0.25 target:self selector:@selector(tick) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
-(void) tick
{
if (!audioPlayer || audioPlayer.duration == 0)
{
slider.value = 0;
return;
}
slider.minimumValue = 0;
slider.maximumValue = audioPlayer.duration;
slider.value = audioPlayer.progress;
}
-(void) playFromHTTPButtonTouched
{
[self.delegate audioPlayerViewPlayFromHTTPSelected:self];
}
-(void) playFromLocalFileButtonTouched
{
[self.delegate audioPlayerViewPlayFromLocalFileSelected:self];
}
-(void) playButtonPressed
{
if (!audioPlayer)
{
return;
}
if (audioPlayer.state == AudioPlayerStatePaused)
{
[audioPlayer resume];
}
else
{
[audioPlayer pause];
}
}
-(void) updateControls
{
if (audioPlayer == nil)
{
[playButton setTitle:@"Play" forState:UIControlStateNormal];
}
else if (audioPlayer.state == AudioPlayerStatePaused)
{
[playButton setTitle:@"Resume" forState:UIControlStateNormal];
}
else if (audioPlayer.state == AudioPlayerStatePlaying)
{
[playButton setTitle:@"Pause" forState:UIControlStateNormal];
}
else
{
[playButton setTitle:@"Play" forState:UIControlStateNormal];
}
}
-(void) setAudioPlayer:(AudioPlayer*)value
{
if (audioPlayer)
{
audioPlayer.delegate = nil;
}
audioPlayer = value;
audioPlayer.delegate = self;
[self updateControls];
}
-(AudioPlayer*) audioPlayer
{
return audioPlayer;
}
-(void) audioPlayer:(AudioPlayer*)audioPlayer stateChanged:(AudioPlayerState)state
{
[self updateControls];
}
-(void) audioPlayer:(AudioPlayer*)audioPlayer didEncounterError:(AudioPlayerErrorCode)errorCode
{
[self updateControls];
}
-(void) audioPlayer:(AudioPlayer*)audioPlayer didStartPlayingQueueItemId:(NSObject*)queueItemId
{
[self updateControls];
}
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId
{
[self updateControls];
}
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(AudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration
{
[self updateControls];
}
@end
-18
View File
@@ -1,18 +0,0 @@
//
// main.m
// Audjustable
//
// Created by Thong Nguyen on 06/06/2012.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

@@ -0,0 +1,519 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
A1115935188D686000641365 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1115934188D686000641365 /* Foundation.framework */; };
A1115937188D686000641365 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1115936188D686000641365 /* CoreGraphics.framework */; };
A1115939188D686000641365 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1115938188D686000641365 /* UIKit.framework */; };
A111593F188D686000641365 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A111593D188D686000641365 /* InfoPlist.strings */; };
A1115941188D686000641365 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A1115940188D686000641365 /* main.m */; };
A1115945188D686000641365 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A1115944188D686000641365 /* AppDelegate.m */; };
A1115947188D686000641365 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1115946188D686000641365 /* Images.xcassets */; };
A111594E188D686000641365 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A111594D188D686000641365 /* XCTest.framework */; };
A111594F188D686000641365 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1115934188D686000641365 /* Foundation.framework */; };
A1115950188D686000641365 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1115938188D686000641365 /* UIKit.framework */; };
A1115958188D686000641365 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1115956188D686000641365 /* InfoPlist.strings */; };
A111595A188D686000641365 /* ExampleAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A1115959188D686000641365 /* ExampleAppTests.m */; };
A1115964188D691500641365 /* libStreamingKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A1115963188D691500641365 /* libStreamingKit.a */; };
A1115967188D6AEE00641365 /* AudioPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1115966188D6AEE00641365 /* AudioPlayerView.m */; };
A111596C188D6C8100641365 /* sample.m4a in Resources */ = {isa = PBXBuildFile; fileRef = A111596B188D6C8100641365 /* sample.m4a */; };
A111596F188D6DB100641365 /* SampleQueueId.m in Sources */ = {isa = PBXBuildFile; fileRef = A111596E188D6DB100641365 /* SampleQueueId.m */; };
A142571D189079BE005F0129 /* airplane.aac in Resources */ = {isa = PBXBuildFile; fileRef = A142571C18907861005F0129 /* airplane.aac */; };
A17FFB6318A0028300BAA7FF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A17FFB6218A0028300BAA7FF /* AudioToolbox.framework */; };
A17FFB6918A002E400BAA7FF /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F5E491189EB3F20070B03F /* AVFoundation.framework */; };
A1EBEE64188DE34500681B04 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1EBEE63188DE34500681B04 /* SystemConfiguration.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
A1115951188D686000641365 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A1115929188D686000641365 /* Project object */;
proxyType = 1;
remoteGlobalIDString = A1115930188D686000641365;
remoteInfo = ExampleApp;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
A1115931188D686000641365 /* ExampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ExampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
A1115934188D686000641365 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
A1115936188D686000641365 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
A1115938188D686000641365 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
A111593C188D686000641365 /* ExampleApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleApp-Info.plist"; sourceTree = "<group>"; };
A111593E188D686000641365 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
A1115940188D686000641365 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
A1115942188D686000641365 /* ExampleApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-Prefix.pch"; sourceTree = "<group>"; };
A1115943188D686000641365 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
A1115944188D686000641365 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
A1115946188D686000641365 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
A111594C188D686000641365 /* ExampleAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A111594D188D686000641365 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
A1115955188D686000641365 /* ExampleAppTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleAppTests-Info.plist"; sourceTree = "<group>"; };
A1115957188D686000641365 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
A1115959188D686000641365 /* ExampleAppTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleAppTests.m; sourceTree = "<group>"; };
A1115963188D691500641365 /* libStreamingKit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libStreamingKit.a; path = "../../../Library/Developer/Xcode/DerivedData/StreamingKit-dabtccqthoyywldsgcvllbcjcmma/Build/Products/Debug-iphoneos/libStreamingKit.a"; sourceTree = "<group>"; };
A1115965188D6AEE00641365 /* AudioPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPlayerView.h; sourceTree = "<group>"; };
A1115966188D6AEE00641365 /* AudioPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioPlayerView.m; sourceTree = "<group>"; };
A111596B188D6C8100641365 /* sample.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; name = sample.m4a; path = Resources/sample.m4a; sourceTree = "<group>"; };
A111596D188D6DB100641365 /* SampleQueueId.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleQueueId.h; sourceTree = "<group>"; };
A111596E188D6DB100641365 /* SampleQueueId.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SampleQueueId.m; sourceTree = "<group>"; };
A142571C18907861005F0129 /* airplane.aac */ = {isa = PBXFileReference; lastKnownFileType = file; path = airplane.aac; sourceTree = "<group>"; };
A17FFB6218A0028300BAA7FF /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
A1EBEE63188DE34500681B04 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
A1F5E48F189EB3CB0070B03F /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
A1F5E491189EB3F20070B03F /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
A111592E188D686000641365 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A17FFB6918A002E400BAA7FF /* AVFoundation.framework in Frameworks */,
A17FFB6318A0028300BAA7FF /* AudioToolbox.framework in Frameworks */,
A1EBEE64188DE34500681B04 /* SystemConfiguration.framework in Frameworks */,
A1115964188D691500641365 /* libStreamingKit.a in Frameworks */,
A1115937188D686000641365 /* CoreGraphics.framework in Frameworks */,
A1115939188D686000641365 /* UIKit.framework in Frameworks */,
A1115935188D686000641365 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1115949188D686000641365 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A111594E188D686000641365 /* XCTest.framework in Frameworks */,
A1115950188D686000641365 /* UIKit.framework in Frameworks */,
A111594F188D686000641365 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
A1115928188D686000641365 = {
isa = PBXGroup;
children = (
A111593A188D686000641365 /* ExampleApp */,
A1115953188D686000641365 /* ExampleAppTests */,
A1115933188D686000641365 /* Frameworks */,
A1115932188D686000641365 /* Products */,
);
sourceTree = "<group>";
};
A1115932188D686000641365 /* Products */ = {
isa = PBXGroup;
children = (
A1115931188D686000641365 /* ExampleApp.app */,
A111594C188D686000641365 /* ExampleAppTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
A1115933188D686000641365 /* Frameworks */ = {
isa = PBXGroup;
children = (
A17FFB6218A0028300BAA7FF /* AudioToolbox.framework */,
A1F5E491189EB3F20070B03F /* AVFoundation.framework */,
A1F5E48F189EB3CB0070B03F /* AudioUnit.framework */,
A1EBEE63188DE34500681B04 /* SystemConfiguration.framework */,
A1115963188D691500641365 /* libStreamingKit.a */,
A1115934188D686000641365 /* Foundation.framework */,
A1115936188D686000641365 /* CoreGraphics.framework */,
A1115938188D686000641365 /* UIKit.framework */,
A111594D188D686000641365 /* XCTest.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
A111593A188D686000641365 /* ExampleApp */ = {
isa = PBXGroup;
children = (
A111596A188D6C4B00641365 /* Resources */,
A1115943188D686000641365 /* AppDelegate.h */,
A1115944188D686000641365 /* AppDelegate.m */,
A1115965188D6AEE00641365 /* AudioPlayerView.h */,
A1115966188D6AEE00641365 /* AudioPlayerView.m */,
A111596D188D6DB100641365 /* SampleQueueId.h */,
A111596E188D6DB100641365 /* SampleQueueId.m */,
A1115946188D686000641365 /* Images.xcassets */,
A111593B188D686000641365 /* Supporting Files */,
);
path = ExampleApp;
sourceTree = "<group>";
};
A111593B188D686000641365 /* Supporting Files */ = {
isa = PBXGroup;
children = (
A111593C188D686000641365 /* ExampleApp-Info.plist */,
A111593D188D686000641365 /* InfoPlist.strings */,
A1115940188D686000641365 /* main.m */,
A1115942188D686000641365 /* ExampleApp-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
A1115953188D686000641365 /* ExampleAppTests */ = {
isa = PBXGroup;
children = (
A1115959188D686000641365 /* ExampleAppTests.m */,
A1115954188D686000641365 /* Supporting Files */,
);
path = ExampleAppTests;
sourceTree = "<group>";
};
A1115954188D686000641365 /* Supporting Files */ = {
isa = PBXGroup;
children = (
A1115955188D686000641365 /* ExampleAppTests-Info.plist */,
A1115956188D686000641365 /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
A111596A188D6C4B00641365 /* Resources */ = {
isa = PBXGroup;
children = (
A142571C18907861005F0129 /* airplane.aac */,
A111596B188D6C8100641365 /* sample.m4a */,
);
name = Resources;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
A1115930188D686000641365 /* ExampleApp */ = {
isa = PBXNativeTarget;
buildConfigurationList = A111595D188D686000641365 /* Build configuration list for PBXNativeTarget "ExampleApp" */;
buildPhases = (
A111592D188D686000641365 /* Sources */,
A111592E188D686000641365 /* Frameworks */,
A111592F188D686000641365 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = ExampleApp;
productName = ExampleApp;
productReference = A1115931188D686000641365 /* ExampleApp.app */;
productType = "com.apple.product-type.application";
};
A111594B188D686000641365 /* ExampleAppTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1115960188D686000641365 /* Build configuration list for PBXNativeTarget "ExampleAppTests" */;
buildPhases = (
A1115948188D686000641365 /* Sources */,
A1115949188D686000641365 /* Frameworks */,
A111594A188D686000641365 /* Resources */,
);
buildRules = (
);
dependencies = (
A1115952188D686000641365 /* PBXTargetDependency */,
);
name = ExampleAppTests;
productName = ExampleAppTests;
productReference = A111594C188D686000641365 /* ExampleAppTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A1115929188D686000641365 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0510;
ORGANIZATIONNAME = "Thong Nguyen";
TargetAttributes = {
A111594B188D686000641365 = {
TestTargetID = A1115930188D686000641365;
};
};
};
buildConfigurationList = A111592C188D686000641365 /* Build configuration list for PBXProject "ExampleApp" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = A1115928188D686000641365;
productRefGroup = A1115932188D686000641365 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
A1115930188D686000641365 /* ExampleApp */,
A111594B188D686000641365 /* ExampleAppTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
A111592F188D686000641365 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A111593F188D686000641365 /* InfoPlist.strings in Resources */,
A111596C188D6C8100641365 /* sample.m4a in Resources */,
A1115947188D686000641365 /* Images.xcassets in Resources */,
A142571D189079BE005F0129 /* airplane.aac in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A111594A188D686000641365 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1115958188D686000641365 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
A111592D188D686000641365 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1115945188D686000641365 /* AppDelegate.m in Sources */,
A1115941188D686000641365 /* main.m in Sources */,
A111596F188D6DB100641365 /* SampleQueueId.m in Sources */,
A1115967188D6AEE00641365 /* AudioPlayerView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1115948188D686000641365 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A111595A188D686000641365 /* ExampleAppTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
A1115952188D686000641365 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A1115930188D686000641365 /* ExampleApp */;
targetProxy = A1115951188D686000641365 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
A111593D188D686000641365 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
A111593E188D686000641365 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
A1115956188D686000641365 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
A1115957188D686000641365 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
A111595B188D686000641365 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../StreamingKit/StreamingKit",
);
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
A111595C188D686000641365 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../StreamingKit/StreamingKit",
);
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
A111595E188D686000641365 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
INFOPLIST_FILE = "ExampleApp/ExampleApp-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
LLVM_LTO = YES;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
A111595F188D686000641365 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
INFOPLIST_FILE = "ExampleApp/ExampleApp-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
LLVM_LTO = YES;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
A1115961188D686000641365 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ExampleApp.app/ExampleApp";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "ExampleAppTests/ExampleAppTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
A1115962188D686000641365 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ExampleApp.app/ExampleApp";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
INFOPLIST_FILE = "ExampleAppTests/ExampleAppTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A111592C188D686000641365 /* Build configuration list for PBXProject "ExampleApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A111595B188D686000641365 /* Debug */,
A111595C188D686000641365 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A111595D188D686000641365 /* Build configuration list for PBXNativeTarget "ExampleApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A111595E188D686000641365 /* Debug */,
A111595F188D686000641365 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1115960188D686000641365 /* Build configuration list for PBXNativeTarget "ExampleAppTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1115961188D686000641365 /* Debug */,
A1115962188D686000641365 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = A1115929188D686000641365 /* Project object */;
}
@@ -1,19 +1,16 @@
//
// AppDelegate.h
// BlueCucumber-AudioPlayer
// ExampleApp
//
// Created by Thong Nguyen on 01/06/2012.
// Copyright (c) 2012 Thong Nguyen All rights reserved.
// Created by Thong Nguyen on 20/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "STKAudioPlayer.h"
#import "AudioPlayerView.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate, AudioPlayerViewDelegate>
{
@private
AudioPlayer* audioPlayer;
}
@property (strong, nonatomic) UIWindow *window;
+100
View File
@@ -0,0 +1,100 @@
//
// AppDelegate.m
// ExampleApp
//
// Created by Thong Nguyen on 20/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import "AppDelegate.h"
#import "STKAudioPlayer.h"
#import "AudioPlayerView.h"
#import "STKAutoRecoveringHTTPDataSource.h"
#import "SampleQueueId.h"
#import <AVFoundation/AVFoundation.h>
@interface AppDelegate()
{
STKAudioPlayer* audioPlayer;
}
@end
@implementation AppDelegate
-(BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
NSError* error;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
Float32 bufferLength = 0.1;
AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(bufferLength), &bufferLength);
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
audioPlayer = [[STKAudioPlayer alloc] initWithOptions:(STKAudioPlayerOptions){ .flushQueueOnSeek = YES, .enableVolumeMixer = NO, .equalizerBandFrequencies = {50, 100, 200, 400, 800, 1600, 2600, 16000} }];
audioPlayer.meteringEnabled = YES;
audioPlayer.volume = 1;
AudioPlayerView* audioPlayerView = [[AudioPlayerView alloc] initWithFrame:self.window.bounds andAudioPlayer:audioPlayer];
audioPlayerView.delegate = self;
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
[self.window addSubview:audioPlayerView];
[self.window makeKeyAndVisible];
return YES;
}
-(BOOL) canBecomeFirstResponder
{
return YES;
}
-(void) audioPlayerViewPlayFromHTTPSelected:(AudioPlayerView*)audioPlayerView
{
NSURL* url = [NSURL URLWithString:@"file:///Users/tum/Temp/airplane-cut.aac"];
STKDataSource* dataSource = [STKAudioPlayer dataSourceFromURL:url];
[audioPlayer setDataSource:dataSource withQueueItemId:[[SampleQueueId alloc] initWithUrl:url andCount:0]];
}
-(void) audioPlayerViewQueueShortFileSelected:(AudioPlayerView*)audioPlayerView
{
NSString* path = [[NSBundle mainBundle] pathForResource:@"airplane" ofType:@"aac"];
NSURL* url = [NSURL fileURLWithPath:path];
STKDataSource* dataSource = [STKAudioPlayer dataSourceFromURL:url];
[audioPlayer queueDataSource:dataSource withQueueItemId:[[SampleQueueId alloc] initWithUrl:url andCount:0]];
}
-(void) audioPlayerViewPlayFromLocalFileSelected:(AudioPlayerView*)audioPlayerView
{
NSString* path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"m4a"];
NSURL* url = [NSURL fileURLWithPath:path];
STKDataSource* dataSource = [STKAudioPlayer dataSourceFromURL:url];
[audioPlayer setDataSource:dataSource withQueueItemId:[[SampleQueueId alloc] initWithUrl:url andCount:0]];
}
-(void) audioPlayerViewQueuePcmWaveFileSelected:(AudioPlayerView*)audioPlayerView
{
NSURL* url = [NSURL URLWithString:@"http://www.abstractpath.com/files/audiosamples/perfectly.wav"];
STKDataSource* dataSource = [STKAudioPlayer dataSourceFromURL:url];
[audioPlayer queueDataSource:dataSource withQueueItemId:[[SampleQueueId alloc] initWithUrl:url andCount:0]];
}
@end
@@ -15,15 +15,15 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@@ -33,26 +33,39 @@
**********************************************************************************/
#import <UIKit/UIKit.h>
#import "AudioPlayer.h"
#import "STKAudioPlayer.h"
@class AudioPlayerView;
@protocol AudioPlayerViewDelegate<NSObject>
-(void) audioPlayerViewPlayFromHTTPSelected:(AudioPlayerView*)audioPlayerView;
-(void) audioPlayerViewQueueShortFileSelected:(AudioPlayerView*)audioPlayerView;
-(void) audioPlayerViewPlayFromLocalFileSelected:(AudioPlayerView*)audioPlayerView;
-(void) audioPlayerViewQueuePcmWaveFileSelected:(AudioPlayerView*)audioPlayerView;
@end
@interface AudioPlayerView : UIView<AudioPlayerDelegate>
@interface AudioPlayerView : UIView<STKAudioPlayerDelegate>
{
@private
NSTimer* timer;
UILabel* label;
UILabel* statusLabel;
UISlider* slider;
UISwitch* enableEqSwitch;
UISwitch* repeatSwitch;
UIButton* muteButton;
UIButton* playButton;
UIButton* stopButton;
UIButton* playFromHTTPButton;
UIButton* queueShortFileButton;
UIButton* queuePcmWaveFileFromHTTPButton;
UIButton* playFromLocalFileButton;
UIView* meter;
}
@property (readwrite, retain) AudioPlayer* audioPlayer;
@property (readwrite, retain) STKAudioPlayer* audioPlayer;
@property (readwrite, unsafe_unretained) id<AudioPlayerViewDelegate> delegate;
- (id)initWithFrame:(CGRect)frame andAudioPlayer:(STKAudioPlayer*)audioPlayer;
@end
+356
View File
@@ -0,0 +1,356 @@
/**********************************************************************************
AudioPlayer.m
Created by Thong Nguyen on 14/05/2012.
https://github.com/tumtumtum/audjustable
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "AudioPlayerView.h"
#import "SampleQueueId.h"
///
/// This sample media player will play a local or an HTTP stream in repeat (gapless)
///
@interface AudioPlayerView()
-(void) setupTimer;
-(void) updateControls;
@end
@implementation AudioPlayerView
@synthesize audioPlayer, delegate;
- (id)initWithFrame:(CGRect)frame andAudioPlayer:(STKAudioPlayer*)audioPlayerIn
{
self = [super initWithFrame:frame];
if (self)
{
self.audioPlayer = audioPlayerIn;
CGSize size = CGSizeMake(220, 50);
playFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playFromHTTPButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10, size.width, size.height);
[playFromHTTPButton addTarget:self action:@selector(playFromHTTPButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[playFromHTTPButton setTitle:@"Play from HTTP" forState:UIControlStateNormal];
playFromLocalFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playFromLocalFileButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 50, size.width, size.height);
[playFromLocalFileButton addTarget:self action:@selector(playFromLocalFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[playFromLocalFileButton setTitle:@"Play from Local File" forState:UIControlStateNormal];
queueShortFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
queueShortFileButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 100, size.width, size.height);
[queueShortFileButton addTarget:self action:@selector(queueShortFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[queueShortFileButton setTitle:@"Queue short file" forState:UIControlStateNormal];
queuePcmWaveFileFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
queuePcmWaveFileFromHTTPButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 150, size.width, size.height);
[queuePcmWaveFileFromHTTPButton addTarget:self action:@selector(queuePcmWaveFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[queuePcmWaveFileFromHTTPButton setTitle:@"Queue PCM/WAVE from HTTP" forState:UIControlStateNormal];
size = CGSizeMake(90, 40);
playButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playButton.frame = CGRectMake(30, 380, size.width, size.height);
[playButton addTarget:self action:@selector(playButtonPressed) forControlEvents:UIControlEventTouchUpInside];
stopButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
stopButton.frame = CGRectMake((320 - size.width) - 30, 380, size.width, size.height);
[stopButton addTarget:self action:@selector(stopButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[stopButton setTitle:@"Stop" forState:UIControlStateNormal];
muteButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
muteButton.frame = CGRectMake((320 - size.width) - 30, 410, size.width, size.height);
[muteButton addTarget:self action:@selector(muteButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[muteButton setTitle:@"Mute" forState:UIControlStateNormal];
slider = [[UISlider alloc] initWithFrame:CGRectMake(20, 320, 280, 20)];
slider.continuous = YES;
[slider addTarget:self action:@selector(sliderChanged) forControlEvents:UIControlEventValueChanged];
size = CGSizeMake(80, 50);
repeatSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(30, frame.size.height * 0.15 + 180, size.width, size.height)];
enableEqSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(320 - size.width - 30, frame.size.height * 0.15 + 180, size.width, size.height)];
enableEqSwitch.on = audioPlayer.equalizerEnabled;
[enableEqSwitch addTarget:self action:@selector(onEnableEqSwitch) forControlEvents:UIControlEventAllTouchEvents];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, slider.frame.origin.y + slider.frame.size.height + 10, frame.size.width, 25)];
label.textAlignment = NSTextAlignmentCenter;
statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, slider.frame.origin.y + slider.frame.size.height + label.frame.size.height + 8, frame.size.width, 50)];
statusLabel.textAlignment = NSTextAlignmentCenter;
meter = [[UIView alloc] initWithFrame:CGRectMake(0, 450, 0, 20)];
meter.backgroundColor = [UIColor greenColor];
[self addSubview:slider];
[self addSubview:playButton];
[self addSubview:playFromHTTPButton];
[self addSubview:playFromLocalFileButton];
[self addSubview:queueShortFileButton];
[self addSubview:queuePcmWaveFileFromHTTPButton];
[self addSubview:repeatSwitch];
[self addSubview:label];
[self addSubview:statusLabel];
[self addSubview:stopButton];
[self addSubview:meter];
[self addSubview:muteButton];
[self addSubview:enableEqSwitch];
[self setupTimer];
[self updateControls];
}
return self;
}
-(void) onEnableEqSwitch
{
audioPlayer.equalizerEnabled = self->enableEqSwitch.on;
}
-(void) sliderChanged
{
if (!audioPlayer)
{
return;
}
NSLog(@"Slider Changed: %f", slider.value);
[audioPlayer seekToTime:slider.value];
}
-(void) setupTimer
{
timer = [NSTimer timerWithTimeInterval:0.001 target:self selector:@selector(tick) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
-(void) tick
{
if (!audioPlayer)
{
slider.value = 0;
label.text = @"";
statusLabel.text = @"";
return;
}
if (audioPlayer.duration != 0)
{
slider.minimumValue = 0;
slider.maximumValue = audioPlayer.duration;
slider.value = audioPlayer.progress;
label.text = [NSString stringWithFormat:@"%@ - %@", [self formatTimeFromSeconds:audioPlayer.progress], [self formatTimeFromSeconds:audioPlayer.duration]];
}
else
{
slider.value = 0;
slider.minimumValue = 0;
slider.maximumValue = 0;
label.text = @"";
}
statusLabel.text = audioPlayer.state == STKAudioPlayerStateBuffering ? @"buffering" : @"";
CGFloat newWidth = 320 * (([audioPlayer averagePowerInDecibelsForChannel:1] + 60) / 60);
meter.frame = CGRectMake(0, 460, newWidth, 20);
}
-(void) playFromHTTPButtonTouched
{
[self.delegate audioPlayerViewPlayFromHTTPSelected:self];
}
-(void) playFromLocalFileButtonTouched
{
[self.delegate audioPlayerViewPlayFromLocalFileSelected:self];
}
-(void) queueShortFileButtonTouched
{
[self.delegate audioPlayerViewQueueShortFileSelected:self];
}
-(void) queuePcmWaveFileButtonTouched
{
[self.delegate audioPlayerViewQueuePcmWaveFileSelected:self];
}
-(void) muteButtonPressed
{
audioPlayer.muted = !audioPlayer.muted;
if (audioPlayer.muted)
{
[muteButton setTitle:@"Unmute" forState:UIControlStateNormal];
}
else
{
[muteButton setTitle:@"Mute" forState:UIControlStateNormal];
}
}
-(void) stopButtonPressed
{
[audioPlayer stop];
}
-(void) playButtonPressed
{
if (!audioPlayer)
{
return;
}
if (audioPlayer.state == STKAudioPlayerStatePaused)
{
[audioPlayer resume];
}
else
{
[audioPlayer pause];
}
}
-(NSString*) formatTimeFromSeconds:(int)totalSeconds
{
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
return [NSString stringWithFormat:@"%02d:%02d:%02d", hours, minutes, seconds];
}
-(void) updateControls
{
if (audioPlayer == nil)
{
[playButton setTitle:@"" forState:UIControlStateNormal];
}
else if (audioPlayer.state == STKAudioPlayerStatePaused)
{
[playButton setTitle:@"Resume" forState:UIControlStateNormal];
}
else if (audioPlayer.state & STKAudioPlayerStatePlaying)
{
[playButton setTitle:@"Pause" forState:UIControlStateNormal];
}
else
{
[playButton setTitle:@"" forState:UIControlStateNormal];
}
[self tick];
}
-(void) setAudioPlayer:(STKAudioPlayer*)value
{
if (audioPlayer)
{
audioPlayer.delegate = nil;
}
audioPlayer = value;
audioPlayer.delegate = self;
[self updateControls];
}
-(STKAudioPlayer*) audioPlayer
{
return audioPlayer;
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer stateChanged:(STKAudioPlayerState)state previousState:(STKAudioPlayerState)previousState
{
[self updateControls];
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer unexpectedError:(STKAudioPlayerErrorCode)errorCode
{
[self updateControls];
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didStartPlayingQueueItemId:(NSObject*)queueItemId
{
SampleQueueId* queueId = (SampleQueueId*)queueItemId;
NSLog(@"Started: %@", [queueId.url description]);
[self updateControls];
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId
{
[self updateControls];
// This queues on the currently playing track to be buffered and played immediately after (gapless)
if (repeatSwitch.on)
{
SampleQueueId* queueId = (SampleQueueId*)queueItemId;
NSLog(@"Requeuing: %@", [queueId.url description]);
[self->audioPlayer queueDataSource:[STKAudioPlayer dataSourceFromURL:queueId.url] withQueueItemId:[[SampleQueueId alloc] initWithUrl:queueId.url andCount:queueId.count + 1]];
}
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(STKAudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration
{
[self updateControls];
SampleQueueId* queueId = (SampleQueueId*)queueItemId;
NSLog(@"Finished: %@", [queueId.url description]);
}
-(void) audioPlayer:(STKAudioPlayer *)audioPlayer logInfo:(NSString *)line
{
NSLog(@"%@", line);
}
@end
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>AbstractPath.${PRODUCT_NAME:rfc1034identifier}</string>
<string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -24,6 +24,10 @@
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
@@ -1,5 +1,7 @@
//
// Prefix header for all source files of the 'Audjustable' target in the 'Audjustable' project
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#import <Availability.h>
@@ -0,0 +1,53 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,51 @@
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"subtype" : "retina4",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
+17
View File
@@ -0,0 +1,17 @@
//
// SampleQueueId.h
// ExampleApp
//
// Created by Thong Nguyen on 20/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SampleQueueId : NSObject
@property (readwrite) int count;
@property (readwrite) NSURL* url;
-(id) initWithUrl:(NSURL*)url andCount:(int)count;
@end
+44
View File
@@ -0,0 +1,44 @@
//
// SampleQueueId.m
// ExampleApp
//
// Created by Thong Nguyen on 20/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import "SampleQueueId.h"
@implementation SampleQueueId
-(id) initWithUrl:(NSURL*)url andCount:(int)count
{
if (self = [super init])
{
self.url = url;
self.count = count;
}
return self;
}
-(BOOL) isEqual:(id)object
{
if (object == nil)
{
return NO;
}
if ([object class] != [SampleQueueId class])
{
return NO;
}
return [((SampleQueueId*)object).url isEqual: self.url] && ((SampleQueueId*)object).count == self.count;
}
-(NSString*) description
{
return [self.url description];
}
@end
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
//
// main.m
// ExampleApp
//
// Created by Thong Nguyen on 20/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool
{
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
@@ -0,0 +1,34 @@
//
// ExampleAppTests.m
// ExampleAppTests
//
// Created by Thong Nguyen on 20/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface ExampleAppTests : XCTestCase
@end
@implementation ExampleAppTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
@@ -0,0 +1,537 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
A17FFB6818A002BC00BAA7FF /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499ED189E793700E2A2E2 /* AudioUnit.framework */; };
A1A499A5189E765800E2A2E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499A4189E765800E2A2E2 /* Cocoa.framework */; };
A1A499AF189E765800E2A2E2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A499AD189E765800E2A2E2 /* InfoPlist.strings */; };
A1A499B1189E765800E2A2E2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A499B0189E765800E2A2E2 /* main.m */; };
A1A499B5189E765800E2A2E2 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = A1A499B3189E765800E2A2E2 /* Credits.rtf */; };
A1A499B8189E765800E2A2E2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A499B7189E765800E2A2E2 /* AppDelegate.m */; };
A1A499BB189E765800E2A2E2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A499B9189E765800E2A2E2 /* MainMenu.xib */; };
A1A499BD189E765800E2A2E2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1A499BC189E765800E2A2E2 /* Images.xcassets */; };
A1A499C4189E765800E2A2E2 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499C3189E765800E2A2E2 /* XCTest.framework */; };
A1A499C5189E765800E2A2E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499A4189E765800E2A2E2 /* Cocoa.framework */; };
A1A499CD189E765800E2A2E2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A499CB189E765800E2A2E2 /* InfoPlist.strings */; };
A1A499CF189E765800E2A2E2 /* ExampleAppMacTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A499CE189E765800E2A2E2 /* ExampleAppMacTests.m */; };
A1A499EC189E793300E2A2E2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499A9189E765800E2A2E2 /* Foundation.framework */; };
A1A499F0189E793D00E2A2E2 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499EF189E793D00E2A2E2 /* CoreAudio.framework */; };
A1A499F2189E799400E2A2E2 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499F1189E799400E2A2E2 /* AudioToolbox.framework */; };
A1A499F3189E799F00E2A2E2 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499ED189E793700E2A2E2 /* AudioUnit.framework */; };
A1A499F5189E79CB00E2A2E2 /* CoreAudioKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499F4189E79CB00E2A2E2 /* CoreAudioKit.framework */; };
A1A499F9189E7A3500E2A2E2 /* libStreamingKitMac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499F8189E7A3500E2A2E2 /* libStreamingKitMac.a */; };
A1A499FA189E7A5600E2A2E2 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499F1189E799400E2A2E2 /* AudioToolbox.framework */; };
A1A499FC189E7A6D00E2A2E2 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */; };
A1A49A01189E82EC00E2A2E2 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A49A00189E82EC00E2A2E2 /* QuartzCore.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
A1A499C6189E765800E2A2E2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A1A49999189E765800E2A2E2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = A1A499A0189E765800E2A2E2;
remoteInfo = ExampleAppMac;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
A17FFB6618A002AD00BAA7FF /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
A1A499A1189E765800E2A2E2 /* ExampleAppMac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ExampleAppMac.app; sourceTree = BUILT_PRODUCTS_DIR; };
A1A499A4189E765800E2A2E2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
A1A499A7189E765800E2A2E2 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
A1A499A8189E765800E2A2E2 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
A1A499A9189E765800E2A2E2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
A1A499AC189E765800E2A2E2 /* ExampleAppMac-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleAppMac-Info.plist"; sourceTree = "<group>"; };
A1A499AE189E765800E2A2E2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
A1A499B0189E765800E2A2E2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
A1A499B2189E765800E2A2E2 /* ExampleAppMac-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleAppMac-Prefix.pch"; sourceTree = "<group>"; };
A1A499B4189E765800E2A2E2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
A1A499B6189E765800E2A2E2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
A1A499B7189E765800E2A2E2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
A1A499BA189E765800E2A2E2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
A1A499BC189E765800E2A2E2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
A1A499C2189E765800E2A2E2 /* ExampleAppMacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleAppMacTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A1A499C3189E765800E2A2E2 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
A1A499CA189E765800E2A2E2 /* ExampleAppMacTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleAppMacTests-Info.plist"; sourceTree = "<group>"; };
A1A499CC189E765800E2A2E2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
A1A499CE189E765800E2A2E2 /* ExampleAppMacTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleAppMacTests.m; sourceTree = "<group>"; };
A1A499EA189E76BD00E2A2E2 /* libStreamingKitMac.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libStreamingKitMac.a; path = ../StreamingKit/build/Debug/libStreamingKitMac.a; sourceTree = "<group>"; };
A1A499ED189E793700E2A2E2 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
A1A499EF189E793D00E2A2E2 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
A1A499F1189E799400E2A2E2 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
A1A499F4189E79CB00E2A2E2 /* CoreAudioKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = System/Library/Frameworks/CoreAudioKit.framework; sourceTree = SDKROOT; };
A1A499F8189E7A3500E2A2E2 /* libStreamingKitMac.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libStreamingKitMac.a; path = ../StreamingKit/build/Debug/libStreamingKitMac.a; sourceTree = "<group>"; };
A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
A1A499FE189E82DD00E2A2E2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
A1A49A00189E82EC00E2A2E2 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
A1A4999E189E765800E2A2E2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A17FFB6818A002BC00BAA7FF /* AudioUnit.framework in Frameworks */,
A1A49A01189E82EC00E2A2E2 /* QuartzCore.framework in Frameworks */,
A1A499FC189E7A6D00E2A2E2 /* SystemConfiguration.framework in Frameworks */,
A1A499FA189E7A5600E2A2E2 /* AudioToolbox.framework in Frameworks */,
A1A499F9189E7A3500E2A2E2 /* libStreamingKitMac.a in Frameworks */,
A1A499F0189E793D00E2A2E2 /* CoreAudio.framework in Frameworks */,
A1A499EC189E793300E2A2E2 /* Foundation.framework in Frameworks */,
A1A499A5189E765800E2A2E2 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1A499BF189E765800E2A2E2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A1A499F5189E79CB00E2A2E2 /* CoreAudioKit.framework in Frameworks */,
A1A499F3189E799F00E2A2E2 /* AudioUnit.framework in Frameworks */,
A1A499F2189E799400E2A2E2 /* AudioToolbox.framework in Frameworks */,
A1A499C5189E765800E2A2E2 /* Cocoa.framework in Frameworks */,
A1A499C4189E765800E2A2E2 /* XCTest.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
A1A49998189E765800E2A2E2 = {
isa = PBXGroup;
children = (
A1A499AA189E765800E2A2E2 /* ExampleAppMac */,
A1A499C8189E765800E2A2E2 /* ExampleAppMacTests */,
A1A499A3189E765800E2A2E2 /* Frameworks */,
A1A499A2189E765800E2A2E2 /* Products */,
);
sourceTree = "<group>";
};
A1A499A2189E765800E2A2E2 /* Products */ = {
isa = PBXGroup;
children = (
A1A499A1189E765800E2A2E2 /* ExampleAppMac.app */,
A1A499C2189E765800E2A2E2 /* ExampleAppMacTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
A1A499A3189E765800E2A2E2 /* Frameworks */ = {
isa = PBXGroup;
children = (
A17FFB6618A002AD00BAA7FF /* AVFoundation.framework */,
A1A49A00189E82EC00E2A2E2 /* QuartzCore.framework */,
A1A499FE189E82DD00E2A2E2 /* CoreGraphics.framework */,
A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */,
A1A499F8189E7A3500E2A2E2 /* libStreamingKitMac.a */,
A1A499F4189E79CB00E2A2E2 /* CoreAudioKit.framework */,
A1A499F1189E799400E2A2E2 /* AudioToolbox.framework */,
A1A499EF189E793D00E2A2E2 /* CoreAudio.framework */,
A1A499ED189E793700E2A2E2 /* AudioUnit.framework */,
A1A499EA189E76BD00E2A2E2 /* libStreamingKitMac.a */,
A1A499A4189E765800E2A2E2 /* Cocoa.framework */,
A1A499C3189E765800E2A2E2 /* XCTest.framework */,
A1A499A6189E765800E2A2E2 /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
A1A499A6189E765800E2A2E2 /* Other Frameworks */ = {
isa = PBXGroup;
children = (
A1A499A7189E765800E2A2E2 /* AppKit.framework */,
A1A499A8189E765800E2A2E2 /* CoreData.framework */,
A1A499A9189E765800E2A2E2 /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
A1A499AA189E765800E2A2E2 /* ExampleAppMac */ = {
isa = PBXGroup;
children = (
A1A499B6189E765800E2A2E2 /* AppDelegate.h */,
A1A499B7189E765800E2A2E2 /* AppDelegate.m */,
A1A499B9189E765800E2A2E2 /* MainMenu.xib */,
A1A499BC189E765800E2A2E2 /* Images.xcassets */,
A1A499AB189E765800E2A2E2 /* Supporting Files */,
);
path = ExampleAppMac;
sourceTree = "<group>";
};
A1A499AB189E765800E2A2E2 /* Supporting Files */ = {
isa = PBXGroup;
children = (
A1A499AC189E765800E2A2E2 /* ExampleAppMac-Info.plist */,
A1A499AD189E765800E2A2E2 /* InfoPlist.strings */,
A1A499B0189E765800E2A2E2 /* main.m */,
A1A499B2189E765800E2A2E2 /* ExampleAppMac-Prefix.pch */,
A1A499B3189E765800E2A2E2 /* Credits.rtf */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
A1A499C8189E765800E2A2E2 /* ExampleAppMacTests */ = {
isa = PBXGroup;
children = (
A1A499CE189E765800E2A2E2 /* ExampleAppMacTests.m */,
A1A499C9189E765800E2A2E2 /* Supporting Files */,
);
path = ExampleAppMacTests;
sourceTree = "<group>";
};
A1A499C9189E765800E2A2E2 /* Supporting Files */ = {
isa = PBXGroup;
children = (
A1A499CA189E765800E2A2E2 /* ExampleAppMacTests-Info.plist */,
A1A499CB189E765800E2A2E2 /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
A1A499A0189E765800E2A2E2 /* ExampleAppMac */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1A499D2189E765800E2A2E2 /* Build configuration list for PBXNativeTarget "ExampleAppMac" */;
buildPhases = (
A1A4999D189E765800E2A2E2 /* Sources */,
A1A4999E189E765800E2A2E2 /* Frameworks */,
A1A4999F189E765800E2A2E2 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = ExampleAppMac;
productName = ExampleAppMac;
productReference = A1A499A1189E765800E2A2E2 /* ExampleAppMac.app */;
productType = "com.apple.product-type.application";
};
A1A499C1189E765800E2A2E2 /* ExampleAppMacTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1A499D5189E765800E2A2E2 /* Build configuration list for PBXNativeTarget "ExampleAppMacTests" */;
buildPhases = (
A1A499BE189E765800E2A2E2 /* Sources */,
A1A499BF189E765800E2A2E2 /* Frameworks */,
A1A499C0189E765800E2A2E2 /* Resources */,
);
buildRules = (
);
dependencies = (
A1A499C7189E765800E2A2E2 /* PBXTargetDependency */,
);
name = ExampleAppMacTests;
productName = ExampleAppMacTests;
productReference = A1A499C2189E765800E2A2E2 /* ExampleAppMacTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A1A49999189E765800E2A2E2 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = "Thong Nguyen";
TargetAttributes = {
A1A499C1189E765800E2A2E2 = {
TestTargetID = A1A499A0189E765800E2A2E2;
};
};
};
buildConfigurationList = A1A4999C189E765800E2A2E2 /* Build configuration list for PBXProject "ExampleAppMac" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = A1A49998189E765800E2A2E2;
productRefGroup = A1A499A2189E765800E2A2E2 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
A1A499A0189E765800E2A2E2 /* ExampleAppMac */,
A1A499C1189E765800E2A2E2 /* ExampleAppMacTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
A1A4999F189E765800E2A2E2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1A499AF189E765800E2A2E2 /* InfoPlist.strings in Resources */,
A1A499BD189E765800E2A2E2 /* Images.xcassets in Resources */,
A1A499B5189E765800E2A2E2 /* Credits.rtf in Resources */,
A1A499BB189E765800E2A2E2 /* MainMenu.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1A499C0189E765800E2A2E2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1A499CD189E765800E2A2E2 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
A1A4999D189E765800E2A2E2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1A499B8189E765800E2A2E2 /* AppDelegate.m in Sources */,
A1A499B1189E765800E2A2E2 /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1A499BE189E765800E2A2E2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1A499CF189E765800E2A2E2 /* ExampleAppMacTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
A1A499C7189E765800E2A2E2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A1A499A0189E765800E2A2E2 /* ExampleAppMac */;
targetProxy = A1A499C6189E765800E2A2E2 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
A1A499AD189E765800E2A2E2 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
A1A499AE189E765800E2A2E2 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
A1A499B3189E765800E2A2E2 /* Credits.rtf */ = {
isa = PBXVariantGroup;
children = (
A1A499B4189E765800E2A2E2 /* en */,
);
name = Credits.rtf;
sourceTree = "<group>";
};
A1A499B9189E765800E2A2E2 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
A1A499BA189E765800E2A2E2 /* Base */,
);
name = MainMenu.xib;
sourceTree = "<group>";
};
A1A499CB189E765800E2A2E2 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
A1A499CC189E765800E2A2E2 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
A1A499D0189E765800E2A2E2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
A1A499D1189E765800E2A2E2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
SDKROOT = macosx;
};
name = Release;
};
A1A499D3189E765800E2A2E2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleAppMac/ExampleAppMac-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../StreamingKit/StreamingKit",
);
INFOPLIST_FILE = "ExampleAppMac/ExampleAppMac-Info.plist";
MACOSX_DEPLOYMENT_TARGET = "";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
A1A499D4189E765800E2A2E2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleAppMac/ExampleAppMac-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../StreamingKit/StreamingKit",
);
INFOPLIST_FILE = "ExampleAppMac/ExampleAppMac-Info.plist";
MACOSX_DEPLOYMENT_TARGET = "";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
A1A499D6189E765800E2A2E2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ExampleAppMac.app/Contents/MacOS/ExampleAppMac";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleAppMac/ExampleAppMac-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "ExampleAppMacTests/ExampleAppMacTests-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.8;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
A1A499D7189E765800E2A2E2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ExampleAppMac.app/Contents/MacOS/ExampleAppMac";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleAppMac/ExampleAppMac-Prefix.pch";
INFOPLIST_FILE = "ExampleAppMacTests/ExampleAppMacTests-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.8;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A1A4999C189E765800E2A2E2 /* Build configuration list for PBXProject "ExampleAppMac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1A499D0189E765800E2A2E2 /* Debug */,
A1A499D1189E765800E2A2E2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1A499D2189E765800E2A2E2 /* Build configuration list for PBXNativeTarget "ExampleAppMac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1A499D3189E765800E2A2E2 /* Debug */,
A1A499D4189E765800E2A2E2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1A499D5189E765800E2A2E2 /* Build configuration list for PBXNativeTarget "ExampleAppMacTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1A499D6189E765800E2A2E2 /* Debug */,
A1A499D7189E765800E2A2E2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = A1A49999189E765800E2A2E2 /* Project object */;
}
@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:Audjustable.xcodeproj">
location = "self:ExampleAppMac.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>B1180E29-F9F8-4232-A985-F8E21716EF14</string>
<key>IDESourceControlProjectName</key>
<string>ExampleAppMac</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</key>
<string>https://github.com/tumtumtum/StreamingKit.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>ExampleAppMac/ExampleAppMac.xcodeproj/project.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</key>
<string>../../..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>https://github.com/tumtumtum/StreamingKit.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</string>
<key>IDESourceControlWCCName</key>
<string>StreamingKit</string>
</dict>
</array>
</dict>
</plist>
+16
View File
@@ -0,0 +1,16 @@
//
// AppDelegate.h
// ExampleAppMac
//
// Created by Thong Nguyen on 02/02/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "STKAudioPlayer.h"
@interface AppDelegate : NSObject <NSApplicationDelegate, STKAudioPlayerDelegate>
@property (assign) IBOutlet NSWindow *window;
@end
+129
View File
@@ -0,0 +1,129 @@
//
// AppDelegate.m
// ExampleAppMac
//
// Created by Thong Nguyen on 02/02/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import "AppDelegate.h"
#import "STKAudioPlayer.h"
@interface AppDelegate()
{
NSView* meter;
NSSlider* slider;
STKAudioPlayer* audioPlayer;
}
@end
@implementation AppDelegate
-(void) applicationDidFinishLaunching:(NSNotification *)aNotification
{
CGRect frame = [self.window.contentView frame];
NSButton* playFromHTTPButton = [[NSButton alloc] initWithFrame:CGRectMake(10, 10, frame.size.width - 20, 100)];
[playFromHTTPButton setTitle:@"Play from HTTP"];
[playFromHTTPButton setAction:@selector(playFromHTTP)];
slider = [[NSSlider alloc] initWithFrame:CGRectMake(10, 140, frame.size.width - 20, 20)];
[slider setAction:@selector(sliderChanged:)];
meter = [[NSView alloc] initWithFrame:CGRectMake(10, 200, 0, 20)];
[meter setLayer:[CALayer new]];
[meter setWantsLayer:YES];
meter.layer.backgroundColor = [NSColor greenColor].CGColor;
[[self.window contentView] addSubview:slider];
[[self.window contentView] addSubview:playFromHTTPButton];
[[self.window contentView] addSubview:meter];
audioPlayer = [[STKAudioPlayer alloc] initWithOptions:(STKAudioPlayerOptions){ .enableVolumeMixer = NO, .equalizerBandFrequencies = {50, 100, 200, 400, 800, 1600, 2600, 16000} } ];
audioPlayer.delegate = self;
audioPlayer.meteringEnabled = YES;
audioPlayer.volume = 0.1;
[self performSelector:@selector(test) withObject:nil afterDelay:4];
[self performSelector:@selector(test) withObject:nil afterDelay:8];
[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
-(void) test
{
audioPlayer.equalizerEnabled = !audioPlayer.equalizerEnabled;
}
-(void) playFromHTTP
{
[audioPlayer play:@"http://www.abstractpath.com/files/audiosamples/sample.mp3"];
}
-(void) tick:(NSTimer*)timer
{
if (!audioPlayer)
{
slider.doubleValue = 0;
return;
}
CGFloat meterWidth = 0;
if (audioPlayer.duration != 0)
{
slider.minValue = 0;
slider.maxValue = audioPlayer.duration;
slider.doubleValue = audioPlayer.progress;
meterWidth = [self.window.contentView frame].size.width - 20;
meterWidth *= (([audioPlayer averagePowerInDecibelsForChannel:0] + 60) / 60);
}
else
{
slider.doubleValue = 0;
slider.minValue = 0;
slider.maxValue = 0;
meterWidth = 0;
}
CGRect frame = meter.frame;
frame.size.width = meterWidth;
meter.frame = frame;
}
-(void) sliderChanged:(NSSlider*)sliderIn
{
[audioPlayer seekToTime:sliderIn.doubleValue];
}
-(void) updateControls
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didStartPlayingQueueItemId:(NSObject*)queueItemId
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer stateChanged:(STKAudioPlayerState)state previousState:(STKAudioPlayerState)previousState
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(STKAudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer unexpectedError:(STKAudioPlayerErrorCode)errorCode
{
}
@end
@@ -0,0 +1,467 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4439" systemVersion="13A451" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4439"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<action selector="orderFrontStandardAboutPanel:" destination="58" id="142"/>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder">
<connections>
<action selector="alignCenter:" destination="499" id="518"/>
<action selector="alignJustified:" destination="500" id="523"/>
<action selector="alignLeft:" destination="498" id="524"/>
<action selector="alignRight:" destination="501" id="521"/>
<action selector="arrangeInFront:" destination="5" id="39"/>
<action selector="capitalizeWord:" destination="466" id="467"/>
<action selector="centerSelectionInVisibleArea:" destination="210" id="245"/>
<action selector="checkSpelling:" destination="201" id="225"/>
<action selector="clearRecentDocuments:" destination="126" id="127"/>
<action selector="copy:" destination="197" id="224"/>
<action selector="copyFont:" destination="403" id="428"/>
<action selector="copyRuler:" destination="506" id="522"/>
<action selector="cut:" destination="199" id="228"/>
<action selector="delete:" destination="202" id="235"/>
<action selector="hide:" destination="134" id="367"/>
<action selector="hideOtherApplications:" destination="145" id="368"/>
<action selector="loosenKerning:" destination="419" id="435"/>
<action selector="lowerBaseline:" destination="410" id="427"/>
<action selector="lowercaseWord:" destination="465" id="468"/>
<action selector="makeBaseWritingDirectionLeftToRight:" destination="511" id="526"/>
<action selector="makeBaseWritingDirectionNatural:" destination="510" id="525"/>
<action selector="makeBaseWritingDirectionRightToLeft:" destination="512" id="527"/>
<action selector="makeTextWritingDirectionLeftToRight:" destination="516" id="529"/>
<action selector="makeTextWritingDirectionNatural:" destination="515" id="528"/>
<action selector="makeTextWritingDirectionRightToLeft:" destination="517" id="530"/>
<action selector="newDocument:" destination="82" id="373"/>
<action selector="openDocument:" destination="72" id="374"/>
<action selector="orderFrontColorPanel:" destination="401" id="433"/>
<action selector="orderFrontSubstitutionsPanel:" destination="457" id="458"/>
<action selector="paste:" destination="203" id="226"/>
<action selector="pasteAsPlainText:" destination="485" id="486"/>
<action selector="pasteFont:" destination="404" id="436"/>
<action selector="pasteRuler:" destination="507" id="519"/>
<action selector="performClose:" destination="73" id="193"/>
<action selector="performFindPanelAction:" destination="209" id="241"/>
<action selector="performFindPanelAction:" destination="208" id="487"/>
<action selector="performFindPanelAction:" destination="213" id="488"/>
<action selector="performFindPanelAction:" destination="221" id="489"/>
<action selector="performFindPanelAction:" destination="534" id="535"/>
<action selector="performMiniaturize:" destination="23" id="37"/>
<action selector="performZoom:" destination="239" id="240"/>
<action selector="print:" destination="78" id="86"/>
<action selector="raiseBaseline:" destination="409" id="426"/>
<action selector="redo:" destination="215" id="231"/>
<action selector="revertDocumentToSaved:" destination="112" id="364"/>
<action selector="runPageLayout:" destination="77" id="87"/>
<action selector="runToolbarCustomizationPalette:" destination="298" id="365"/>
<action selector="saveDocument:" destination="75" id="362"/>
<action selector="selectAll:" destination="198" id="232"/>
<action selector="showGuessPanel:" destination="204" id="230"/>
<action selector="showHelp:" destination="492" id="493"/>
<action selector="startSpeaking:" destination="196" id="233"/>
<action selector="stopSpeaking:" destination="195" id="227"/>
<action selector="subscript:" destination="408" id="429"/>
<action selector="superscript:" destination="407" id="430"/>
<action selector="tightenKerning:" destination="418" id="431"/>
<action selector="toggleAutomaticDashSubstitution:" destination="460" id="461"/>
<action selector="toggleAutomaticLinkDetection:" destination="354" id="357"/>
<action selector="toggleAutomaticQuoteSubstitution:" destination="351" id="356"/>
<action selector="toggleAutomaticSpellingCorrection:" destination="454" id="456"/>
<action selector="toggleAutomaticTextReplacement:" destination="462" id="463"/>
<action selector="toggleContinuousSpellChecking:" destination="219" id="222"/>
<action selector="toggleGrammarChecking:" destination="346" id="347"/>
<action selector="toggleRuler:" destination="505" id="520"/>
<action selector="toggleSmartInsertDelete:" destination="350" id="355"/>
<action selector="toggleToolbarShown:" destination="297" id="366"/>
<action selector="turnOffKerning:" destination="417" id="441"/>
<action selector="turnOffLigatures:" destination="413" id="440"/>
<action selector="underline:" destination="392" id="432"/>
<action selector="undo:" destination="207" id="223"/>
<action selector="unhideAllApplications:" destination="150" id="370"/>
<action selector="unscript:" destination="406" id="437"/>
<action selector="uppercaseWord:" destination="452" id="464"/>
<action selector="useAllLigatures:" destination="414" id="434"/>
<action selector="useStandardKerning:" destination="416" id="438"/>
<action selector="useStandardLigatures:" destination="412" id="439"/>
</connections>
</customObject>
<customObject id="-3" userLabel="Application">
<connections>
<action selector="terminate:" destination="136" id="449"/>
</connections>
</customObject>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="ExampleAppMac" id="56">
<menu key="submenu" title="ExampleAppMac" systemMenu="apple" id="57">
<items>
<menuItem title="About ExampleAppMac" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="236">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
<menuItem isSeparatorItem="YES" id="143">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Services" id="131">
<menu key="submenu" title="Services" systemMenu="services" id="130"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide ExampleAppMac" keyEquivalent="h" id="134"/>
<menuItem title="Hide Others" keyEquivalent="h" id="145">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
</menuItem>
<menuItem title="Show All" id="150"/>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit ExampleAppMac" keyEquivalent="q" id="136"/>
</items>
</menu>
</menuItem>
<menuItem title="File" id="83">
<menu key="submenu" title="File" id="81">
<items>
<menuItem title="New" keyEquivalent="n" id="82"/>
<menuItem title="Open…" keyEquivalent="o" id="72"/>
<menuItem title="Open Recent" id="124">
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
<items>
<menuItem title="Clear Menu" id="126"/>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="79">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Close" keyEquivalent="w" id="73"/>
<menuItem title="Save…" keyEquivalent="s" id="75"/>
<menuItem title="Revert to Saved" id="112">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="74">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Page Setup..." keyEquivalent="P" id="77">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="78"/>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207"/>
<menuItem title="Redo" keyEquivalent="Z" id="215">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="206">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Cut" keyEquivalent="x" id="199"/>
<menuItem title="Copy" keyEquivalent="c" id="197"/>
<menuItem title="Paste" keyEquivalent="v" id="203"/>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="485">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
</menuItem>
<menuItem title="Delete" id="202"/>
<menuItem title="Select All" keyEquivalent="a" id="198"/>
<menuItem isSeparatorItem="YES" id="214">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Find" id="218">
<menu key="submenu" title="Find" id="220">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209"/>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="534">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208"/>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210"/>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="216">
<menu key="submenu" title="Spelling and Grammar" id="200">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204"/>
<menuItem title="Check Document Now" keyEquivalent=";" id="201"/>
<menuItem isSeparatorItem="YES" id="453"/>
<menuItem title="Check Spelling While Typing" id="219"/>
<menuItem title="Check Grammar With Spelling" id="346"/>
<menuItem title="Correct Spelling Automatically" id="454">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="348">
<menu key="submenu" title="Substitutions" id="349">
<items>
<menuItem title="Show Substitutions" id="457">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="459"/>
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350"/>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351"/>
<menuItem title="Smart Dashes" id="460">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
</menuItem>
<menuItem title="Text Replacement" id="462">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="450">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="451">
<items>
<menuItem title="Make Upper Case" id="452">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Make Lower Case" id="465">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Capitalize" id="466">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196"/>
<menuItem title="Stop Speaking" id="195"/>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Format" id="375">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="376">
<items>
<menuItem title="Font" id="377">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="388">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="389"/>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390"/>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391"/>
<menuItem title="Underline" keyEquivalent="u" id="392"/>
<menuItem isSeparatorItem="YES" id="393"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="394"/>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395"/>
<menuItem isSeparatorItem="YES" id="396"/>
<menuItem title="Kern" id="397">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="415">
<items>
<menuItem title="Use Default" id="416">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Use None" id="417">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Tighten" id="418">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Loosen" id="419">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="398">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="411">
<items>
<menuItem title="Use Default" id="412">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Use None" id="413">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Use All" id="414">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="399">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="405">
<items>
<menuItem title="Use Default" id="406">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Superscript" id="407">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Subscript" id="408">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Raise" id="409">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Lower" id="410">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="400"/>
<menuItem title="Show Colors" keyEquivalent="C" id="401"/>
<menuItem isSeparatorItem="YES" id="402"/>
<menuItem title="Copy Style" keyEquivalent="c" id="403">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="404">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="496">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="497">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="498"/>
<menuItem title="Center" keyEquivalent="|" id="499"/>
<menuItem title="Justify" id="500">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="501"/>
<menuItem isSeparatorItem="YES" id="502"/>
<menuItem title="Writing Direction" id="503">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="508">
<items>
<menuItem title="Paragraph" enabled="NO" id="509">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="510">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="511">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="512">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="513"/>
<menuItem title="Selection" enabled="NO" id="514">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="515">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="516">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="517">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="504"/>
<menuItem title="Show Ruler" id="505">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="506">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="507">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="295">
<menu key="submenu" title="View" id="296">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="297">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
</menuItem>
<menuItem title="Customize Toolbar…" id="298"/>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="19">
<menu key="submenu" title="Window" systemMenu="window" id="24">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="23"/>
<menuItem title="Zoom" id="239"/>
<menuItem isSeparatorItem="YES" id="92">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Bring All to Front" id="5"/>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="490">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="ExampleAppMac Help" keyEquivalent="?" id="492"/>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="ExampleAppMac" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1418"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</window>
<customObject id="494" customClass="AppDelegate">
<connections>
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager">
<connections>
<action selector="addFontTrait:" destination="390" id="421"/>
<action selector="addFontTrait:" destination="391" id="422"/>
<action selector="modifyFont:" destination="395" id="423"/>
<action selector="modifyFont:" destination="394" id="425"/>
<action selector="orderFrontFontPanel:" destination="389" id="424"/>
</connections>
</customObject>
</objects>
</document>
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.abstractpath.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 Thong Nguyen. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
@@ -0,0 +1,9 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
@@ -0,0 +1,58 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,29 @@
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw9840\paperh8400
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
\f0\b\fs24 \cf0 Engineering:
\b0 \
Some people\
\
\b Human Interface Design:
\b0 \
Some other people\
\
\b Testing:
\b0 \
Hopefully not nobody\
\
\b Documentation:
\b0 \
Whoever\
\
\b With special thanks to:
\b0 \
Mom\
}
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
+14
View File
@@ -0,0 +1,14 @@
//
// main.m
// ExampleAppMac
//
// Created by Thong Nguyen on 02/02/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[])
{
return NSApplicationMain(argc, argv);
}
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.abstractpath.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
@@ -0,0 +1,34 @@
//
// ExampleAppMacTests.m
// ExampleAppMacTests
//
// Created by Thong Nguyen on 02/02/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface ExampleAppMacTests : XCTestCase
@end
@implementation ExampleAppMacTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
+44 -26
View File
@@ -1,48 +1,66 @@
### Audjustable Audio Streamer
## StreamingKit
[Homepage](http://tumtumtum.github.com/audjustable)
StreamingKit (formally Audjustable) is an audio playback and streaming library for iOS and Mac OSX. StreamingKit uses CoreAudio to decompress and playback audio (using hardware or software codecs) whilst providing a clean and simple object-oriented API.
Audjustable is audio streaming class for iOS and OSX. Audjustable uses CoreAudio to decompress and playback audio whilst providing a clean and simple object-oriented API.
The primary motivation of this project was to decouple the input data sources from the actual player logic in order to allow advanced customizable input handling such as HTTP progressive download based streaming, encryption/decryption, auto-recovery, dynamic-buffering. StreamingKit is the only streaming and playback library that supports dead-easy [gapless playback](https://github.com/tumtumtum/StreamingKit/wiki/Gapless-playback) between audio files of differing formats.
The primary motivation of this project was to decouple the input (DataSource/InputStreams) from the actual player logic in order to allow advanced customizable input handling such as: HTTP streaming, encryption, auto-recovery, dynamic-buffering. Along the way other features such as gapless playback were added as the opportunity arose.
## Main Features
## Features
* Free OSS.
* Simple API.
* Easy to read source.
* Carefully multi-threaded to provide a responsive API that won't block your UI thread nor starve the audio buffers.
* Buffered and gapless playback between all format types.
* Easy to implement audio data sources (Local, HTTP, AutoRecoveryingHTTP DataSources are provided).
* Easy to extend DataSource to support adaptive buffering, encryption, etc.
* Optimised for low CPU/battery usage (0% - 1% CPU usage when streaming).
* Optimised for linear data sources. Random access sources are required only for seeking.
* StreamingKit 0.2.0 uses the AudioUnit API rather than the slower AudioQueues API which allows real-time interception of the raw PCM data for features such as level metering, EQ, etc.
* Power metering
* Inbuilt equalizer/EQ (iOS 5.0 and above, OSX 10.9 Mavericks and above) with support for dynamically changing/enabling/disabling EQ while playing.
* Example apps for iOS and Mac OSX provided.
* Simple OOP API
* Easy to read source
* Adjustable audio buffering
* Mostly asynchronous API
* Buffered and gapless playback
* Easy to implement audio data sources (HTTP and local file system DataSources provided)
* Easy to extend DataSource to support adaptive buffering, encryption etc
* Optimised for low CPU/battery usage
## Installation
## Usage
StreamingKit is available as a [Cocoapod](http://cocoapods.org/?q=StreamingKit). You can also simply copy all the source files located inside StreamingKit/StreamingKit/* into your Xcode project.
Download the [source](https://github.com/tumtumtum/audjustable/zipball/master) which includes a simple audio player project that streams audio over HTTP or locally using the `HttpDataSource` or `LocalFileDataSource` classes respectively.
## Example
If you would like to integrate the AudioPlayer directly into your project you only need to copy the files inside the `/Audjustable/Classes/AudioPlayer` [directory](https://github.com/tumtumtum/audjustable/tree/master/Audjustable/Classes/AudioPlayer) into your project.
There are two main classes. The `STKDataSource` class which is the abstract base class for the various compressed audio data sources. The `STKAudioPlayer` class manages and renders audio from a queue DataSources. By default `STKAudioPlayer` will automatically parse URLs and create the appropriate data source internally.
## Code
### Play an MP3 over HTTP
There are two main classes. The `DataSource` class which is the abstract base class for the various compressed audio data sources (HTTP, local file are provided). The `AudioPlayer` class manages and renders audio from a queue DataSources.
```objective-c
STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];
// Create AudioPlayer
[audioPlayer play:@"http://www.abstractpath.com/files/audiosamples/sample.mp3"];
```
AudioPlayer* audioPlayer = [[AudioPlayer alloc] init];
audioPlayer.delegate = self;
### Gapless playback
// Queue on a URL to play. Each queue item has a unique ID (item1) that to identify the related file in delegate callbacks
```objective-c
STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];
[audioPlayer setDataSource:[audioPlayer dataSourceFromURL:@"https://github.com/downloads/tumtumtum/audjustable/sample.m4a"] withQueueItemId:@"item1"];
[audioPlayer queue:@"http://www.abstractpath.com/files/audiosamples/sample.mp3"];
[audioPlayer queue:@"http://www.abstractpath.com/files/audiosamples/airplane.aac"];
```
## Other
Background playback on iOS is easily added to your application by calling the `AudioSessionInitialize` in your AppDelegate.
### Intercept PCM data just before its played
```objective-c
[audioPlayer appendFrameFilterWithName:@"MyCustomFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames)
{
...
}];
````
## More
More documentation is available on the project [Wiki](https://github.com/tumtumtum/StreamingKit/wiki/_pages)
### Authors and Contributors
Copyright 2012, Thong Nguyen (@tumtumtum)
Copyright (c) 2012-2014, Thong Nguyen ([@tumtumtum](http://www.twitter.com/tumtumtum))
+16
View File
@@ -0,0 +1,16 @@
Pod::Spec.new do |s|
s.name = "StreamingKit"
s.version = "0.0.0"
s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources."
s.homepage = "https://github.com/tumtumtum/StreamingKit/"
s.license = 'MIT'
s.author = { "Thong Nguyen" => "tumtumtum@gmail.com" }
s.source = { :git => "https://github.com/tumtumtum/StreamingKit.git" }
s.platform = :ios
s.requires_arc = true
s.source_files = 'StreamingKit/StreamingKit/*.{h,m}'
s.ios.deployment_target = '4.3'
s.ios.frameworks = 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox'
s.osx.deployment_target = '10.7'
s.osx.frameworks = 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox', 'AudioUnit'
end
+16
View File
@@ -0,0 +1,16 @@
Pod::Spec.new do |s|
s.name = "StreamingKit"
s.version = "0.1.23"
s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources."
s.homepage = "https://github.com/tumtumtum/StreamingKit/"
s.license = 'MIT'
s.author = { "Thong Nguyen" => "tumtumtum@gmail.com" }
s.source = { :git => "https://github.com/tumtumtum/StreamingKit.git", :tag => s.version.to_s}
s.platform = :ios
s.requires_arc = true
s.source_files = 'StreamingKit/StreamingKit/*.{h,m}'
s.ios.deployment_target = '4.3'
s.ios.frameworks = 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox'
s.osx.deployment_target = '10.7'
s.osx.frameworks = 'SystemConfiguration', 'CFNetwork', 'CoreFoundation', 'AudioToolbox', 'AudioUnit'
end
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:ExampleApp/ExampleApp.xcodeproj">
</FileRef>
<FileRef
location = "group:StreamingKit/../ExampleAppMac/ExampleAppMac.xcodeproj">
</FileRef>
<FileRef
location = "group:StreamingKit/StreamingKit.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>64C9BE2D-7DAD-476A-B9AC-1C4603CD4124</string>
<key>IDESourceControlProjectName</key>
<string>StreamingKit</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</key>
<string>https://github.com/tumtumtum/StreamingKit.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>StreamingKit.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</key>
<string>..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>https://github.com/tumtumtum/StreamingKit.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>DD310C30-B3D0-4BD7-9565-9F29F09CC4F8</string>
<key>IDESourceControlWCCName</key>
<string>StreamingKit</string>
</dict>
</array>
</dict>
</plist>
@@ -0,0 +1,821 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
A1A4996B189E744400E2A2E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A4996A189E744400E2A2E2 /* Cocoa.framework */; };
A1A49975189E744500E2A2E2 /* StreamingKitMac.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A49974189E744500E2A2E2 /* StreamingKitMac.m */; };
A1A4997B189E744500E2A2E2 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E7C4D9188D57F60010896F /* XCTest.framework */; };
A1A4997C189E744500E2A2E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A4996A189E744400E2A2E2 /* Cocoa.framework */; };
A1A4997F189E744500E2A2E2 /* libStreamingKitMac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A49969189E744400E2A2E2 /* libStreamingKitMac.a */; };
A1A49985189E744500E2A2E2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A49983189E744500E2A2E2 /* InfoPlist.strings */; };
A1A49987189E744500E2A2E2 /* StreamingKitMacTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A49986189E744500E2A2E2 /* StreamingKitMacTests.m */; };
A1A4998E189E745900E2A2E2 /* STKAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */; };
A1A4998F189E745C00E2A2E2 /* STKAutoRecoveringHTTPDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F4188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m */; };
A1A49991189E746000E2A2E2 /* STKCoreFoundationDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F6188D5E550010896F /* STKCoreFoundationDataSource.m */; };
A1A49992189E746300E2A2E2 /* STKDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F8188D5E550010896F /* STKDataSource.m */; };
A1A49993189E746500E2A2E2 /* STKDataSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FA188D5E550010896F /* STKDataSourceWrapper.m */; };
A1A49994189E746900E2A2E2 /* STKHTTPDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */; };
A1A49995189E746B00E2A2E2 /* STKLocalFileDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */; };
A1A49996189E746E00E2A2E2 /* STKQueueEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = A1BF65D1189A6582004DD08C /* STKQueueEntry.m */; };
A1A49997189E747000E2A2E2 /* NSMutableArray+STKAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1BF65D4189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m */; };
A1BF65D2189A6582004DD08C /* STKQueueEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = A1BF65D1189A6582004DD08C /* STKQueueEntry.m */; };
A1BF65D5189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1BF65D4189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m */; };
A1E7C4DA188D57F60010896F /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E7C4D9188D57F60010896F /* XCTest.framework */; };
A1E7C4DB188D57F60010896F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E7C4CB188D57F50010896F /* Foundation.framework */; };
A1E7C4E0188D57F60010896F /* libStreamingKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E7C4C8188D57F50010896F /* libStreamingKit.a */; };
A1E7C4E6188D57F60010896F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1E7C4E4188D57F60010896F /* InfoPlist.strings */; };
A1E7C4E8188D57F60010896F /* StreamingKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4E7188D57F60010896F /* StreamingKitTests.m */; };
A1E7C4FF188D5E550010896F /* STKAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */; };
A1E7C500188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F4188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m */; };
A1E7C501188D5E550010896F /* STKCoreFoundationDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F6188D5E550010896F /* STKCoreFoundationDataSource.m */; };
A1E7C502188D5E550010896F /* STKDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4F8188D5E550010896F /* STKDataSource.m */; };
A1E7C503188D5E550010896F /* STKDataSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FA188D5E550010896F /* STKDataSourceWrapper.m */; };
A1E7C504188D5E550010896F /* STKHTTPDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */; };
A1E7C505188D5E550010896F /* STKLocalFileDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
A1A4997D189E744500E2A2E2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A1E7C4C0188D57F50010896F /* Project object */;
proxyType = 1;
remoteGlobalIDString = A1A49968189E744400E2A2E2;
remoteInfo = StreamingKitMac;
};
A1A499E6189E769A00E2A2E2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A1A499E1189E769A00E2A2E2 /* ExampleAppMac.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = A1A499A1189E765800E2A2E2;
remoteInfo = ExampleAppMac;
};
A1A499E8189E769A00E2A2E2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A1A499E1189E769A00E2A2E2 /* ExampleAppMac.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = A1A499C2189E765800E2A2E2;
remoteInfo = ExampleAppMacTests;
};
A1E7C4DE188D57F60010896F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A1E7C4C0188D57F50010896F /* Project object */;
proxyType = 1;
remoteGlobalIDString = A1E7C4C7188D57F50010896F;
remoteInfo = StreamingKit;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
A1E7C4C6188D57F50010896F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "include/$(PRODUCT_NAME)";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
A1A49969189E744400E2A2E2 /* libStreamingKitMac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libStreamingKitMac.a; sourceTree = BUILT_PRODUCTS_DIR; };
A1A4996A189E744400E2A2E2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; };
A1A4996D189E744500E2A2E2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
A1A4996E189E744500E2A2E2 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
A1A4996F189E744500E2A2E2 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
A1A49972189E744500E2A2E2 /* StreamingKitMac-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StreamingKitMac-Prefix.pch"; sourceTree = "<group>"; };
A1A49973189E744500E2A2E2 /* StreamingKitMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StreamingKitMac.h; sourceTree = "<group>"; };
A1A49974189E744500E2A2E2 /* StreamingKitMac.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StreamingKitMac.m; sourceTree = "<group>"; };
A1A4997A189E744500E2A2E2 /* StreamingKitMacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StreamingKitMacTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A1A49982189E744500E2A2E2 /* StreamingKitMacTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "StreamingKitMacTests-Info.plist"; sourceTree = "<group>"; };
A1A49984189E744500E2A2E2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
A1A49986189E744500E2A2E2 /* StreamingKitMacTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StreamingKitMacTests.m; sourceTree = "<group>"; };
A1A499E1189E769A00E2A2E2 /* ExampleAppMac.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ExampleAppMac.xcodeproj; path = ../ExampleAppMac/ExampleAppMac.xcodeproj; sourceTree = "<group>"; };
A1A499F6189E79EA00E2A2E2 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
A1BF65D0189A6582004DD08C /* STKQueueEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKQueueEntry.h; sourceTree = "<group>"; };
A1BF65D1189A6582004DD08C /* STKQueueEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKQueueEntry.m; sourceTree = "<group>"; };
A1BF65D3189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+STKAudioPlayer.h"; sourceTree = "<group>"; };
A1BF65D4189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+STKAudioPlayer.m"; sourceTree = "<group>"; };
A1C9767618981BFE0057F881 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
A1E7C4C8188D57F50010896F /* libStreamingKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libStreamingKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
A1E7C4CB188D57F50010896F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
A1E7C4CF188D57F50010896F /* StreamingKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StreamingKit-Prefix.pch"; sourceTree = "<group>"; };
A1E7C4D8188D57F60010896F /* StreamingKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StreamingKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A1E7C4D9188D57F60010896F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
A1E7C4E3188D57F60010896F /* StreamingKitTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "StreamingKitTests-Info.plist"; sourceTree = "<group>"; };
A1E7C4E5188D57F60010896F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
A1E7C4E7188D57F60010896F /* StreamingKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StreamingKitTests.m; sourceTree = "<group>"; };
A1E7C4F1188D5E550010896F /* STKAudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKAudioPlayer.h; sourceTree = "<group>"; };
A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKAudioPlayer.m; sourceTree = "<group>"; };
A1E7C4F3188D5E550010896F /* STKAutoRecoveringHTTPDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKAutoRecoveringHTTPDataSource.h; sourceTree = "<group>"; };
A1E7C4F4188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKAutoRecoveringHTTPDataSource.m; sourceTree = "<group>"; };
A1E7C4F5188D5E550010896F /* STKCoreFoundationDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKCoreFoundationDataSource.h; sourceTree = "<group>"; };
A1E7C4F6188D5E550010896F /* STKCoreFoundationDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKCoreFoundationDataSource.m; sourceTree = "<group>"; };
A1E7C4F7188D5E550010896F /* STKDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKDataSource.h; sourceTree = "<group>"; };
A1E7C4F8188D5E550010896F /* STKDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKDataSource.m; sourceTree = "<group>"; };
A1E7C4F9188D5E550010896F /* STKDataSourceWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKDataSourceWrapper.h; sourceTree = "<group>"; };
A1E7C4FA188D5E550010896F /* STKDataSourceWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKDataSourceWrapper.m; sourceTree = "<group>"; };
A1E7C4FB188D5E550010896F /* STKHTTPDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKHTTPDataSource.h; sourceTree = "<group>"; };
A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKHTTPDataSource.m; sourceTree = "<group>"; };
A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKLocalFileDataSource.h; sourceTree = "<group>"; };
A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKLocalFileDataSource.m; sourceTree = "<group>"; };
A1E7C507188D62D20010896F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
A1A49966189E744400E2A2E2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A1A4996B189E744400E2A2E2 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1A49977189E744500E2A2E2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A1A4997C189E744500E2A2E2 /* Cocoa.framework in Frameworks */,
A1A4997B189E744500E2A2E2 /* XCTest.framework in Frameworks */,
A1A4997F189E744500E2A2E2 /* libStreamingKitMac.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1E7C4C5188D57F50010896F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
A1E7C4D5188D57F60010896F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A1E7C4DA188D57F60010896F /* XCTest.framework in Frameworks */,
A1E7C4E0188D57F60010896F /* libStreamingKit.a in Frameworks */,
A1E7C4DB188D57F60010896F /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
A1A4996C189E744500E2A2E2 /* Other Frameworks */ = {
isa = PBXGroup;
children = (
A1A4996D189E744500E2A2E2 /* Foundation.framework */,
A1A4996E189E744500E2A2E2 /* CoreData.framework */,
A1A4996F189E744500E2A2E2 /* AppKit.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
A1A49970189E744500E2A2E2 /* StreamingKitMac */ = {
isa = PBXGroup;
children = (
A1A49973189E744500E2A2E2 /* StreamingKitMac.h */,
A1A49974189E744500E2A2E2 /* StreamingKitMac.m */,
A1A49971189E744500E2A2E2 /* Supporting Files */,
);
path = StreamingKitMac;
sourceTree = "<group>";
};
A1A49971189E744500E2A2E2 /* Supporting Files */ = {
isa = PBXGroup;
children = (
A1A49972189E744500E2A2E2 /* StreamingKitMac-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
A1A49980189E744500E2A2E2 /* StreamingKitMacTests */ = {
isa = PBXGroup;
children = (
A1A49986189E744500E2A2E2 /* StreamingKitMacTests.m */,
A1A49981189E744500E2A2E2 /* Supporting Files */,
);
path = StreamingKitMacTests;
sourceTree = "<group>";
};
A1A49981189E744500E2A2E2 /* Supporting Files */ = {
isa = PBXGroup;
children = (
A1A49982189E744500E2A2E2 /* StreamingKitMacTests-Info.plist */,
A1A49983189E744500E2A2E2 /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
A1A499E2189E769A00E2A2E2 /* Products */ = {
isa = PBXGroup;
children = (
A1A499E7189E769A00E2A2E2 /* ExampleAppMac.app */,
A1A499E9189E769A00E2A2E2 /* ExampleAppMacTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
A1E7C4BF188D57F50010896F = {
isa = PBXGroup;
children = (
A1E7C4CD188D57F50010896F /* StreamingKit */,
A1E7C4E1188D57F60010896F /* StreamingKitTests */,
A1A49970189E744500E2A2E2 /* StreamingKitMac */,
A1A49980189E744500E2A2E2 /* StreamingKitMacTests */,
A1E7C4CA188D57F50010896F /* Frameworks */,
A1E7C4C9188D57F50010896F /* Products */,
A1A499E1189E769A00E2A2E2 /* ExampleAppMac.xcodeproj */,
);
sourceTree = "<group>";
};
A1E7C4C9188D57F50010896F /* Products */ = {
isa = PBXGroup;
children = (
A1E7C4C8188D57F50010896F /* libStreamingKit.a */,
A1E7C4D8188D57F60010896F /* StreamingKitTests.xctest */,
A1A49969189E744400E2A2E2 /* libStreamingKitMac.a */,
A1A4997A189E744500E2A2E2 /* StreamingKitMacTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
A1E7C4CA188D57F50010896F /* Frameworks */ = {
isa = PBXGroup;
children = (
A1A499F6189E79EA00E2A2E2 /* AudioToolbox.framework */,
A1C9767618981BFE0057F881 /* AudioUnit.framework */,
A1E7C507188D62D20010896F /* UIKit.framework */,
A1E7C4CB188D57F50010896F /* Foundation.framework */,
A1E7C4D9188D57F60010896F /* XCTest.framework */,
A1A4996A189E744400E2A2E2 /* Cocoa.framework */,
A1A4996C189E744500E2A2E2 /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
A1E7C4CD188D57F50010896F /* StreamingKit */ = {
isa = PBXGroup;
children = (
A1E7C4F1188D5E550010896F /* STKAudioPlayer.h */,
A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */,
A1E7C4F3188D5E550010896F /* STKAutoRecoveringHTTPDataSource.h */,
A1E7C4F4188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m */,
A1E7C4F5188D5E550010896F /* STKCoreFoundationDataSource.h */,
A1E7C4F6188D5E550010896F /* STKCoreFoundationDataSource.m */,
A1E7C4F7188D5E550010896F /* STKDataSource.h */,
A1E7C4F8188D5E550010896F /* STKDataSource.m */,
A1E7C4F9188D5E550010896F /* STKDataSourceWrapper.h */,
A1E7C4FA188D5E550010896F /* STKDataSourceWrapper.m */,
A1E7C4FB188D5E550010896F /* STKHTTPDataSource.h */,
A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */,
A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */,
A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */,
A1BF65D0189A6582004DD08C /* STKQueueEntry.h */,
A1BF65D1189A6582004DD08C /* STKQueueEntry.m */,
A1BF65D3189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.h */,
A1BF65D4189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m */,
A1E7C4CE188D57F50010896F /* Supporting Files */,
);
path = StreamingKit;
sourceTree = "<group>";
};
A1E7C4CE188D57F50010896F /* Supporting Files */ = {
isa = PBXGroup;
children = (
A1E7C4CF188D57F50010896F /* StreamingKit-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
A1E7C4E1188D57F60010896F /* StreamingKitTests */ = {
isa = PBXGroup;
children = (
A1E7C4E7188D57F60010896F /* StreamingKitTests.m */,
A1E7C4E2188D57F60010896F /* Supporting Files */,
);
path = StreamingKitTests;
sourceTree = "<group>";
};
A1E7C4E2188D57F60010896F /* Supporting Files */ = {
isa = PBXGroup;
children = (
A1E7C4E3188D57F60010896F /* StreamingKitTests-Info.plist */,
A1E7C4E4188D57F60010896F /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
A1A49967189E744400E2A2E2 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
A1A49968189E744400E2A2E2 /* StreamingKitMac */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1A4998C189E744500E2A2E2 /* Build configuration list for PBXNativeTarget "StreamingKitMac" */;
buildPhases = (
A1A49965189E744400E2A2E2 /* Sources */,
A1A49966189E744400E2A2E2 /* Frameworks */,
A1A49967189E744400E2A2E2 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = StreamingKitMac;
productName = StreamingKitMac;
productReference = A1A49969189E744400E2A2E2 /* libStreamingKitMac.a */;
productType = "com.apple.product-type.library.static";
};
A1A49979189E744500E2A2E2 /* StreamingKitMacTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1A4998D189E744500E2A2E2 /* Build configuration list for PBXNativeTarget "StreamingKitMacTests" */;
buildPhases = (
A1A49976189E744500E2A2E2 /* Sources */,
A1A49977189E744500E2A2E2 /* Frameworks */,
A1A49978189E744500E2A2E2 /* Resources */,
);
buildRules = (
);
dependencies = (
A1A4997E189E744500E2A2E2 /* PBXTargetDependency */,
);
name = StreamingKitMacTests;
productName = StreamingKitMacTests;
productReference = A1A4997A189E744500E2A2E2 /* StreamingKitMacTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
A1E7C4C7188D57F50010896F /* StreamingKit */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1E7C4EB188D57F60010896F /* Build configuration list for PBXNativeTarget "StreamingKit" */;
buildPhases = (
A1E7C4C4188D57F50010896F /* Sources */,
A1E7C4C5188D57F50010896F /* Frameworks */,
A1E7C4C6188D57F50010896F /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = StreamingKit;
productName = StreamingKit;
productReference = A1E7C4C8188D57F50010896F /* libStreamingKit.a */;
productType = "com.apple.product-type.library.static";
};
A1E7C4D7188D57F60010896F /* StreamingKitTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1E7C4EE188D57F60010896F /* Build configuration list for PBXNativeTarget "StreamingKitTests" */;
buildPhases = (
A1E7C4D4188D57F60010896F /* Sources */,
A1E7C4D5188D57F60010896F /* Frameworks */,
A1E7C4D6188D57F60010896F /* Resources */,
);
buildRules = (
);
dependencies = (
A1E7C4DF188D57F60010896F /* PBXTargetDependency */,
);
name = StreamingKitTests;
productName = StreamingKitTests;
productReference = A1E7C4D8188D57F60010896F /* StreamingKitTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A1E7C4C0188D57F50010896F /* Project object */ = {
isa = PBXProject;
attributes = {
CLASSPREFIX = STK;
LastUpgradeCheck = 0510;
ORGANIZATIONNAME = "Thong Nguyen";
};
buildConfigurationList = A1E7C4C3188D57F50010896F /* Build configuration list for PBXProject "StreamingKit" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = A1E7C4BF188D57F50010896F;
productRefGroup = A1E7C4C9188D57F50010896F /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = A1A499E2189E769A00E2A2E2 /* Products */;
ProjectRef = A1A499E1189E769A00E2A2E2 /* ExampleAppMac.xcodeproj */;
},
);
projectRoot = "";
targets = (
A1E7C4C7188D57F50010896F /* StreamingKit */,
A1E7C4D7188D57F60010896F /* StreamingKitTests */,
A1A49968189E744400E2A2E2 /* StreamingKitMac */,
A1A49979189E744500E2A2E2 /* StreamingKitMacTests */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
A1A499E7189E769A00E2A2E2 /* ExampleAppMac.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
path = ExampleAppMac.app;
remoteRef = A1A499E6189E769A00E2A2E2 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
A1A499E9189E769A00E2A2E2 /* ExampleAppMacTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = ExampleAppMacTests.xctest;
remoteRef = A1A499E8189E769A00E2A2E2 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
A1A49978189E744500E2A2E2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1A49985189E744500E2A2E2 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1E7C4D6188D57F60010896F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1E7C4E6188D57F60010896F /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
A1A49965189E744400E2A2E2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1A4998F189E745C00E2A2E2 /* STKAutoRecoveringHTTPDataSource.m in Sources */,
A1A49994189E746900E2A2E2 /* STKHTTPDataSource.m in Sources */,
A1A49991189E746000E2A2E2 /* STKCoreFoundationDataSource.m in Sources */,
A1A49995189E746B00E2A2E2 /* STKLocalFileDataSource.m in Sources */,
A1A49997189E747000E2A2E2 /* NSMutableArray+STKAudioPlayer.m in Sources */,
A1A4998E189E745900E2A2E2 /* STKAudioPlayer.m in Sources */,
A1A49993189E746500E2A2E2 /* STKDataSourceWrapper.m in Sources */,
A1A49992189E746300E2A2E2 /* STKDataSource.m in Sources */,
A1A49975189E744500E2A2E2 /* StreamingKitMac.m in Sources */,
A1A49996189E746E00E2A2E2 /* STKQueueEntry.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1A49976189E744500E2A2E2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1A49987189E744500E2A2E2 /* StreamingKitMacTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1E7C4C4188D57F50010896F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1E7C501188D5E550010896F /* STKCoreFoundationDataSource.m in Sources */,
A1E7C4FF188D5E550010896F /* STKAudioPlayer.m in Sources */,
A1E7C505188D5E550010896F /* STKLocalFileDataSource.m in Sources */,
A1BF65D2189A6582004DD08C /* STKQueueEntry.m in Sources */,
A1E7C504188D5E550010896F /* STKHTTPDataSource.m in Sources */,
A1E7C503188D5E550010896F /* STKDataSourceWrapper.m in Sources */,
A1E7C502188D5E550010896F /* STKDataSource.m in Sources */,
A1BF65D5189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m in Sources */,
A1E7C500188D5E550010896F /* STKAutoRecoveringHTTPDataSource.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1E7C4D4188D57F60010896F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1E7C4E8188D57F60010896F /* StreamingKitTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
A1A4997E189E744500E2A2E2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A1A49968189E744400E2A2E2 /* StreamingKitMac */;
targetProxy = A1A4997D189E744500E2A2E2 /* PBXContainerItemProxy */;
};
A1E7C4DF188D57F60010896F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A1E7C4C7188D57F50010896F /* StreamingKit */;
targetProxy = A1E7C4DE188D57F60010896F /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
A1A49983189E744500E2A2E2 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
A1A49984189E744500E2A2E2 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
A1E7C4E4188D57F60010896F /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
A1E7C4E5188D57F60010896F /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
A1A49988189E744500E2A2E2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKitMac/StreamingKitMac-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
MACOSX_DEPLOYMENT_TARGET = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
name = Debug;
};
A1A49989189E744500E2A2E2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKitMac/StreamingKitMac-Prefix.pch";
MACOSX_DEPLOYMENT_TARGET = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
name = Release;
};
A1A4998A189E744500E2A2E2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKitMac/StreamingKitMac-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "StreamingKitMacTests/StreamingKitMacTests-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.8;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
A1A4998B189E744500E2A2E2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKitMac/StreamingKitMac-Prefix.pch";
INFOPLIST_FILE = "StreamingKitMacTests/StreamingKitMacTests-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.8;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
A1E7C4E9188D57F60010896F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
A1E7C4EA188D57F60010896F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
A1E7C4EC188D57F60010896F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DSTROOT = /tmp/StreamingKit.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
A1E7C4ED188D57F60010896F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DSTROOT = /tmp/StreamingKit.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
A1E7C4EF188D57F60010896F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "StreamingKitTests/StreamingKitTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
A1E7C4F0188D57F60010896F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch";
INFOPLIST_FILE = "StreamingKitTests/StreamingKitTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A1A4998C189E744500E2A2E2 /* Build configuration list for PBXNativeTarget "StreamingKitMac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1A49988189E744500E2A2E2 /* Debug */,
A1A49989189E744500E2A2E2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1A4998D189E744500E2A2E2 /* Build configuration list for PBXNativeTarget "StreamingKitMacTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1A4998A189E744500E2A2E2 /* Debug */,
A1A4998B189E744500E2A2E2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1E7C4C3188D57F50010896F /* Build configuration list for PBXProject "StreamingKit" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1E7C4E9188D57F60010896F /* Debug */,
A1E7C4EA188D57F60010896F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1E7C4EB188D57F60010896F /* Build configuration list for PBXNativeTarget "StreamingKit" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1E7C4EC188D57F60010896F /* Debug */,
A1E7C4ED188D57F60010896F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1E7C4EE188D57F60010896F /* Build configuration list for PBXNativeTarget "StreamingKitTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1E7C4EF188D57F60010896F /* Debug */,
A1E7C4F0188D57F60010896F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = A1E7C4C0188D57F50010896F /* Project object */;
}
@@ -0,0 +1,17 @@
//
// NSMutableArray+STKAudioPlayer.h
// StreamingKit
//
// Created by Thong Nguyen on 30/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSMutableArray (STKAudioPlayer)
-(void) enqueue:(id)obj;
-(void) skipQueue:(id)obj;
-(void) skipQueueWithQueue:(NSMutableArray*)queue;
-(id) dequeue;
-(id) peek;
@end
@@ -0,0 +1,50 @@
//
// NSMutableArray+STKAudioPlayer.m
// StreamingKit
//
// Created by Thong Nguyen on 30/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import "NSMutableArray+STKAudioPlayer.h"
@implementation NSMutableArray (STKAudioPlayer)
-(void) enqueue:(id)obj
{
[self insertObject:obj atIndex:0];
}
-(void) skipQueue:(id)obj
{
[self addObject:obj];
}
-(void) skipQueueWithQueue:(NSMutableArray*)queue
{
for (id item in queue)
{
[self addObject:item];
}
}
-(id) dequeue
{
if ([self count] == 0)
{
return nil;
}
id retval = [self lastObject];
[self removeLastObject];
return retval;
}
-(id) peek
{
return [self lastObject];
}
@end
+266
View File
@@ -0,0 +1,266 @@
/**********************************************************************************
AudioPlayer.m
Created by Thong Nguyen on 14/05/2012.
https://github.com/tumtumtum/StreamingKit
Inspired by Matt Gallagher's AudioStreamer:
https://github.com/mattgallagher/AudioStreamer
Copyright (c) 2012-2014 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import <Foundation/Foundation.h>
#import <pthread.h>
#import "STKDataSource.h"
#import <AudioToolbox/AudioToolbox.h>
#if TARGET_OS_IPHONE
#include "UIKit/UIApplication.h"
#endif
typedef enum
{
STKAudioPlayerStateReady,
STKAudioPlayerStateRunning = 1,
STKAudioPlayerStatePlaying = (1 << 1) | STKAudioPlayerStateRunning,
STKAudioPlayerStateBuffering = (1 << 2) | STKAudioPlayerStateRunning,
STKAudioPlayerStatePaused = (1 << 3) | STKAudioPlayerStateRunning,
STKAudioPlayerStateStopped = (1 << 4),
STKAudioPlayerStateError = (1 << 5),
STKAudioPlayerStateDisposed = (1 << 6)
}
STKAudioPlayerState;
typedef enum
{
STKAudioPlayerStopReasonNone = 0,
STKAudioPlayerStopReasonEof,
STKAudioPlayerStopReasonUserAction,
STKAudioPlayerStopReasonPendingNext,
STKAudioPlayerStopReasonDisposed,
STKAudioPlayerStopReasonError = 0xffff
}
STKAudioPlayerStopReason;
typedef enum
{
STKAudioPlayerErrorNone = 0,
STKAudioPlayerErrorDataSource,
STKAudioPlayerErrorStreamParseBytesFailed,
STKAudioPlayerErrorAudioSystemError,
STKAudioPlayerErrorCodecError,
STKAudioPlayerErrorDataNotFound,
STKAudioPlayerErrorOther = 0xffff
}
STKAudioPlayerErrorCode;
typedef struct
{
/// If YES then seeking a track will cause all pending items to be flushed from the queue
BOOL flushQueueOnSeek;
/// If YES then volume control will be enabled on iOS
BOOL enableVolumeMixer;
/// A pointer to a 0 terminated array of band frequencies (iOS 5.0 and later, OSX 10.9 and later)
Float32 equalizerBandFrequencies[24];
/// The size of the internal I/O read buffer. This data in this buffer is transient and does not need to be larger.
UInt32 readBufferSize;
/// The size of the decompressed buffer (Default is 10 seconds which uses about 1.7MB of RAM)
UInt32 bufferSizeInSeconds;
/// Number of seconds of decompressed audio is required before playback first starts for each item (Default is 0.5 seconds. Must be larger than bufferSizeInSeconds)
Float32 secondsRequiredToStartPlaying;
/// Seconds after a seek is performed before data needs to come in (after which the state will change to playing/buffering)
Float32 gracePeriodAfterSeekInSeconds;
/// Number of seconds of decompressed audio required before playback resumes after a buffer underrun (Default is 5 seconds. Must be larger than bufferSizeinSeconds)
Float32 secondsRequiredToStartPlayingAfterBufferUnderun;
}
STKAudioPlayerOptions;
typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames);
@interface STKFrameFilterEntry : NSObject
@property (readonly) NSString* name;
@property (readonly) STKFrameFilter filter;
@end
@class STKAudioPlayer;
@protocol STKAudioPlayerDelegate <NSObject>
/// Raised when an item has started playing
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didStartPlayingQueueItemId:(NSObject*)queueItemId;
/// Raised when an item has finished buffering (may or may not be the currently playing item)
/// This event may be raised multiple times for the same item if seek is invoked on the player
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId;
/// Raised when the state of the player has changed
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer stateChanged:(STKAudioPlayerState)state previousState:(STKAudioPlayerState)previousState;
/// Raised when an item has finished playing
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(STKAudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration;
/// Raised when an unexpected and possibly unrecoverable error has occured (usually best to recreate the STKAudioPlauyer)
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer unexpectedError:(STKAudioPlayerErrorCode)errorCode;
@optional
/// Optionally implemented to get logging information from the STKAudioPlayer (used internally for debugging)
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer logInfo:(NSString*)line;
/// Raised when items queued items are cleared (usually because of a call to play, setDataSource or stop)
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems;
@end
@interface STKAudioPlayer : NSObject<STKDataSourceDelegate>
/// Gets or sets the volume (ranges 0 - 1.0).
/// On iOS the STKAudioPlayerOptionEnableMultichannelMixer option must be enabled for volume to work.
@property (readwrite) Float32 volume;
/// Gets or sets the player muted state
@property (readwrite) BOOL muted;
/// Gets the current item duration in seconds
@property (readonly) double duration;
/// Gets the current item progress in seconds
@property (readonly) double progress;
/// Enables or disables peak and average decibel meteting
@property (readwrite) BOOL meteringEnabled;
/// Enables or disables the EQ
@property (readwrite) BOOL equalizerEnabled;
/// Returns an array of STKFrameFilterEntry objects representing the filters currently in use
@property (readonly) NSArray* frameFilters;
/// Returns the items pending to be played (includes buffering and upcoming items but does not include the current item)
@property (readonly) NSArray* pendingQueue;
/// The number of items pending to be played (includes buffering and upcoming items but does not include the current item)
@property (readonly) NSUInteger pendingQueueCount;
/// Gets the most recently queued item that is still pending to play
@property (readonly) NSObject* mostRecentlyQueuedStillPendingItem;
/// Gets the current state of the player
@property (readwrite) STKAudioPlayerState state;
/// Gets the options provided to the player on startup
@property (readonly) STKAudioPlayerOptions options;
/// Gets the reason why the player is stopped (if any)
@property (readonly) STKAudioPlayerStopReason stopReason;
/// Gets and sets the delegate used for receiving events from the STKAudioPlayer
@property (readwrite, unsafe_unretained) id<STKAudioPlayerDelegate> delegate;
/// Creates a datasource from a given URL.
/// URLs with FILE schemes will return an STKLocalFileDataSource.
/// URLs with HTTP schemes will return an STKHTTPDataSource wrapped within an STKAutoRecoveringHTTPDataSource.
/// URLs with unrecognised schemes will return nil.
+(STKDataSource*) dataSourceFromURL:(NSURL*)url;
/// Initializes a new STKAudioPlayer with the default options
-(id) init;
/// Initializes a new STKAudioPlayer with the given options
-(id) initWithOptions:(STKAudioPlayerOptions)optionsIn;
/// Plays an item from the given URL string (all pending queued items are removed).
/// The NSString is used as the queue item ID
-(void) play:(NSString*)urlString;
/// Plays an item from the given URL (all pending queued items are removed)
-(void) play:(NSString*)urlString withQueueItemID:(NSObject*)queueItemId;
/// Plays an item from the given URL (all pending queued items are removed)
/// The NSURL is used as the queue item ID
-(void) playURL:(NSURL*)url;
/// Plays an item from the given URL (all pending queued items are removed)
-(void) playURL:(NSURL*)url withQueueItemID:(NSObject*)queueItemId;
/// Plays the given item (all pending queued items are removed)
/// The STKDataSource is used as the queue item ID
-(void) playDataSource:(STKDataSource*)dataSource;
/// Plays the given item (all pending queued items are removed)
-(void) playDataSource:(STKDataSource*)dataSource withQueueItemID:(NSObject*)queueItemId;
/// Queues the URL string for playback and uses the NSString as the queueItemID
-(void) queue:(NSString*)urlString;
/// Queues the URL string for playback with the given queueItemID
-(void) queue:(NSString*)urlString withQueueItemId:(NSObject*)queueItemId;
/// Queues the URL for playback and uses the NSURL as the queueItemID
-(void) queueURL:(NSURL*)url;
/// Queues the URL for playback with the given queueItemID
-(void) queueURL:(NSURL*)url withQueueItemId:(NSObject*)queueItemId;
/// Queues a DataSource with the given queueItemId
-(void) queueDataSource:(STKDataSource*)dataSource withQueueItemId:(NSObject*)queueItemId;
/// Plays the given item (all pending queued items are removed)
-(void) setDataSource:(STKDataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId;
/// Seeks to a specific time (in seconds)
-(void) seekToTime:(double)value;
/// Clears any upcoming items already queued for playback (does not stop the current item).
/// The didCancelItems event will be raised for the items removed from the queue.
-(void) clearQueue;
/// Pauses playback
-(void) pause;
/// Resumes playback from pause
-(void) resume;
/// Stops playback of the current file, flushes all the buffers and removes any pending queued items
-(void) stop;
/// Mutes playback
-(void) mute;
/// Unmutes playback
-(void) unmute;
/// Disposes the STKAudioPlayer and frees up all resources before returning
-(void) dispose;
/// The QueueItemId of the currently playing item
-(NSObject*) currentlyPlayingQueueItemId;
/// Removes a frame filter with the given name
-(void) removeFrameFilterWithName:(NSString*)name;
/// Appends a frame filter with the given name and filter block to the end of the filter chain
-(void) appendFrameFilterWithName:(NSString*)name block:(STKFrameFilter)block;
/// Appends a frame filter with the given name and filter block just after the filter with the given name.
/// If the given name is nil, the filter will be inserted at the beginning of the filter change
-(void) addFrameFilterWithName:(NSString*)name afterFilterWithName:(NSString*)afterFilterWithName block:(STKFrameFilter)block;
/// Reads the peak power in decibals for the given channel (0 or 1).
/// Return values are between -60 (low) and 0 (high).
-(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber;
/// Reads the average power in decibals for the given channel (0 or 1)
/// Return values are between -60 (low) and 0 (high).
-(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber;
/// Sets the gain value (from -96 low to +24 high) for an equalizer band (0 based index)
-(void) setGain:(float)gain forEqualizerBand:(int)bandIndex;
@end
File diff suppressed because it is too large Load Diff
@@ -4,8 +4,8 @@
Created by Thong Nguyen on 16/10/2012.
https://github.com/tumtumtum/audjustable
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Copyright (c) 2012-2014 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
@@ -15,15 +15,15 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@@ -32,14 +32,21 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "DataSource.h"
#import "HttpDataSource.h"
#import "DataSourceWrapper.h"
#import "STKDataSource.h"
#import "STKHTTPDataSource.h"
#import "STKDataSourceWrapper.h"
@interface AutoRecoveringHttpDataSource : DataSourceWrapper
typedef struct
{
int watchdogPeriodSeconds;
int inactivePeriodBeforeReconnectSeconds;
}
STKAutoRecoveringHTTPDataSourceOptions;
-(id) initWithHttpDataSource:(HttpDataSource*)innerDataSource;
@interface STKAutoRecoveringHTTPDataSource : STKDataSourceWrapper
@property (readonly) HttpDataSource* innerDataSource;
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource;
@property (readonly) STKHTTPDataSource* innerDataSource;
@end
@@ -0,0 +1,391 @@
/**********************************************************************************
AudioPlayer.m
Created by Thong Nguyen on 16/10/2012.
https://github.com/tumtumtum/audjustable
Copyright (c) 2012-2014 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import <sys/socket.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import "mach/mach_time.h"
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import "STKAutoRecoveringHTTPDataSource.h"
#define DEFAULT_WATCHDOG_PERIOD_SECONDS (8)
#define DEFAULT_INACTIVE_PERIOD_BEFORE_RECONNECT_SECONDS (15)
static uint64_t GetTickCount(void)
{
static mach_timebase_info_data_t sTimebaseInfo;
uint64_t machTime = mach_absolute_time();
if (sTimebaseInfo.denom == 0 )
{
(void) mach_timebase_info(&sTimebaseInfo);
}
uint64_t millis = ((machTime / 1000000) * sTimebaseInfo.numer) / sTimebaseInfo.denom;
return millis;
}
@interface STKAutoRecoveringHTTPDataSource()
{
int serial;
int waitSeconds;
NSTimer* timeoutTimer;
BOOL waitingForNetwork;
uint64_t ticksWhenLastDataReceived;
SCNetworkReachabilityRef reachabilityRef;
STKAutoRecoveringHTTPDataSourceOptions options;
}
-(void) reachabilityChanged;
@end
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
@autoreleasepool
{
STKAutoRecoveringHTTPDataSource* dataSource = (__bridge STKAutoRecoveringHTTPDataSource*)info;
[dataSource reachabilityChanged];
}
}
static void PopulateOptionsWithDefault(STKAutoRecoveringHTTPDataSourceOptions* options)
{
if (options->watchdogPeriodSeconds == 0)
{
options->watchdogPeriodSeconds = DEFAULT_WATCHDOG_PERIOD_SECONDS;
}
if (options->inactivePeriodBeforeReconnectSeconds == 0)
{
options->inactivePeriodBeforeReconnectSeconds = DEFAULT_INACTIVE_PERIOD_BEFORE_RECONNECT_SECONDS;
}
}
@implementation STKAutoRecoveringHTTPDataSource
-(STKHTTPDataSource*) innerHTTPDataSource
{
return (STKHTTPDataSource*)self.innerDataSource;
}
-(id) initWithDataSource:(STKDataSource *)innerDataSource
{
return [self initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource];
}
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn
{
return [self initWithHTTPDataSource:innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions){}];
}
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions)optionsIn
{
if (self = [super initWithDataSource:innerDataSourceIn])
{
self.innerDataSource.delegate = self;
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
PopulateOptionsWithDefault(&optionsIn);
self->options = optionsIn;
reachabilityRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
}
return self;
}
-(BOOL) startNotifierOnRunLoop:(NSRunLoop*)runLoop
{
BOOL retVal = NO;
SCNetworkReachabilityContext context = { 0, (__bridge void*)self, NULL, NULL, NULL };
if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
{
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, runLoop.getCFRunLoop, kCFRunLoopDefaultMode))
{
retVal = YES;
}
}
return retVal;
}
-(BOOL) registerForEvents:(NSRunLoop*)runLoop
{
[super registerForEvents:runLoop];
[self startNotifierOnRunLoop:runLoop];
if (timeoutTimer)
{
[timeoutTimer invalidate];
timeoutTimer = nil;
}
ticksWhenLastDataReceived = GetTickCount();
[self createTimeoutTimer];
return YES;
}
-(void) unregisterForEvents
{
[super unregisterForEvents];
[self stopNotifier];
[self destroyTimeoutTimer];
}
-(void) timeoutTimerTick:(NSTimer*)timer
{
if (![self hasBytesAvailable])
{
if ([self hasGotNetworkConnection])
{
uint64_t currentTicks = GetTickCount();
if (((currentTicks - ticksWhenLastDataReceived) / 1000) >= options.inactivePeriodBeforeReconnectSeconds)
{
serial++;
NSLog(@"timeoutTimerTick %lld/%lld", self.position, self.length);
[self attemptReconnectWithSerial:@(serial)];
}
}
}
}
-(void) createTimeoutTimer
{
[self destroyTimeoutTimer];
NSRunLoop* runLoop = self.innerDataSource.eventsRunLoop;
if (runLoop == nil)
{
return;
}
timeoutTimer = [NSTimer timerWithTimeInterval:options.watchdogPeriodSeconds target:self selector:@selector(timeoutTimerTick:) userInfo:@(serial) repeats:YES];
[runLoop addTimer:timeoutTimer forMode:NSRunLoopCommonModes];
}
-(void) destroyTimeoutTimer
{
if (timeoutTimer)
{
[timeoutTimer invalidate];
timeoutTimer = nil;
}
}
-(void) stopNotifier
{
if (reachabilityRef != NULL)
{
SCNetworkReachabilitySetCallback(reachabilityRef, NULL, NULL);
SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, [self.innerDataSource.eventsRunLoop getCFRunLoop], kCFRunLoopDefaultMode);
}
}
-(BOOL) hasGotNetworkConnection
{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
return ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
}
return NO;
}
-(void) seekToOffset:(int64_t)offset
{
ticksWhenLastDataReceived = GetTickCount();
[super seekToOffset:offset];
}
-(void) close
{
[self destroyTimeoutTimer];
[super close];
}
-(void) dealloc
{
NSLog(@"STKAutoRecoveringHTTPDataSource dealloc");
self.innerDataSource.delegate = nil;
[self stopNotifier];
[self destroyTimeoutTimer];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if (reachabilityRef!= NULL)
{
CFRelease(reachabilityRef);
}
}
-(void) reachabilityChanged
{
if (waitingForNetwork)
{
waitingForNetwork = NO;
NSLog(@"reachabilityChanged %lld/%lld", self.position, self.length);
serial++;
[self attemptReconnectWithSerial:@(serial)];
}
}
-(void) dataSourceDataAvailable:(STKDataSource*)dataSource
{
if (![self.innerDataSource hasBytesAvailable])
{
return;
}
serial++;
waitSeconds = 1;
ticksWhenLastDataReceived = GetTickCount();
[super dataSourceDataAvailable:dataSource];
}
-(void) attemptReconnectWithSerial:(NSNumber*)serialIn
{
if (serialIn.intValue != self->serial)
{
return;
}
NSLog(@"attemptReconnect %lld/%lld", self.position, self.length);
if (self.innerDataSource.eventsRunLoop)
{
[self.innerDataSource reconnect];
}
}
-(void) attemptReconnectWithTimer:(NSTimer*)timer
{
[self attemptReconnectWithSerial:(NSNumber*)timer.userInfo];
}
-(void) processRetryOnError
{
if (![self hasGotNetworkConnection])
{
waitingForNetwork = YES;
return;
}
waitingForNetwork = NO;
NSRunLoop* runLoop = self.innerDataSource.eventsRunLoop;
if (runLoop == nil)
{
// DataSource no longer used
return;
}
else
{
serial++;
NSTimer* timer = [NSTimer timerWithTimeInterval:waitSeconds target:self selector:@selector(attemptReconnectWithTimer:) userInfo:@(serial) repeats:NO];
[runLoop addTimer:timer forMode:NSRunLoopCommonModes];
}
waitSeconds = MIN(waitSeconds + 1, 5);
}
-(void) dataSourceEof:(STKDataSource*)dataSource
{
NSLog(@"dataSourceEof");
if ([self position] < [self length])
{
[self processRetryOnError];
return;
}
[self.delegate dataSourceEof:self];
}
-(void) dataSourceErrorOccured:(STKDataSource*)dataSource
{
NSLog(@"dataSourceErrorOccured");
if (self.innerDataSource.httpStatusCode == 416 /* Range out of bounds */)
{
[super dataSourceEof:dataSource];
}
else
{
[self processRetryOnError];
}
}
-(NSString*) description
{
return [NSString stringWithFormat:@"HTTP data source with file length: %lld and position: %lld", self.length, self.position];
}
@end
@@ -15,15 +15,15 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@@ -32,26 +32,32 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "DataSource.h"
#import "STKDataSource.h"
@class CoreFoundationDataSource;
@class STKCoreFoundationDataSource;
@interface CoreFoundationDataSourceClientInfo : NSObject
@property (readwrite) CFReadStreamRef readStreamRef;
@property (readwrite, retain) CoreFoundationDataSource* datasource;
@property (readwrite, retain) STKCoreFoundationDataSource* datasource;
@end
@interface CoreFoundationDataSource : DataSource
@interface STKCoreFoundationDataSource : STKDataSource
{
@protected
BOOL isInErrorState;
CFReadStreamRef stream;
NSRunLoop* eventsRunLoop;
}
@property (readonly) BOOL isInErrorState;
-(BOOL) reregisterForEvents;
-(void) open;
-(void) openCompleted;
-(void) dataAvailable;
-(void) eof;
-(void) errorOccured;
-(CFStreamStatus) status;
@end
@@ -15,15 +15,15 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@@ -32,11 +32,11 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "CoreFoundationDataSource.h"
#import "STKCoreFoundationDataSource.h"
static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eventType, void* inClientInfo)
{
CoreFoundationDataSource* datasource = (__bridge CoreFoundationDataSource*)inClientInfo;
STKCoreFoundationDataSource* datasource = (__bridge STKCoreFoundationDataSource*)inClientInfo;
switch (eventType)
{
@@ -49,6 +49,9 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
case kCFStreamEventHasBytesAvailable:
[datasource dataAvailable];
break;
case kCFStreamEventOpenCompleted:
[datasource openCompleted];
break;
default:
break;
}
@@ -58,7 +61,12 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
@synthesize readStreamRef, datasource;
@end
@implementation CoreFoundationDataSource
@implementation STKCoreFoundationDataSource
-(BOOL) isInErrorState
{
return self->isInErrorState;
}
-(void) dataAvailable
{
@@ -72,6 +80,8 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
-(void) errorOccured
{
self->isInErrorState = YES;
[self.delegate dataSourceErrorOccured:self];
}
@@ -79,7 +89,10 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
{
if (stream)
{
[self unregisterForEvents];
if (eventsRunLoop)
{
[self unregisterForEvents];
}
[self close];
@@ -91,6 +104,11 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
{
if (stream)
{
if (eventsRunLoop)
{
[self unregisterForEvents];
}
CFReadStreamClose(stream);
CFRelease(stream);
@@ -98,13 +116,17 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
}
}
-(void) seekToOffset:(long long)offset
-(void) open
{
}
-(void) seekToOffset:(SInt64)offset
{
}
-(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size
{
return CFReadStreamRead(stream, buffer, size);
return (int)CFReadStreamRead(stream, buffer, size);
}
-(void) unregisterForEvents
@@ -113,6 +135,8 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
{
CFReadStreamSetClient(stream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, NULL, NULL);
CFReadStreamUnscheduleFromRunLoop(stream, [eventsRunLoop getCFRunLoop], kCFRunLoopCommonModes);
eventsRunLoop = nil;
}
}
@@ -133,19 +157,21 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
-(BOOL) registerForEvents:(NSRunLoop*)runLoop
{
eventsRunLoop = runLoop;
if (stream)
{
CFStreamClientContext context = {0, (__bridge void*)self, NULL, NULL, NULL};
CFReadStreamSetClient(stream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, ReadStreamCallbackProc, &context);
CFReadStreamScheduleWithRunLoop(stream, [eventsRunLoop getCFRunLoop], kCFRunLoopCommonModes);
if (!stream)
{
// Will register when they open or seek
return YES;
}
CFStreamClientContext context = {0, (__bridge void*)self, NULL, NULL, NULL};
return NO;
CFReadStreamSetClient(stream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, ReadStreamCallbackProc, &context);
CFReadStreamScheduleWithRunLoop(stream, [eventsRunLoop getCFRunLoop], kCFRunLoopCommonModes);
return YES;
}
-(BOOL) hasBytesAvailable
@@ -158,4 +184,18 @@ static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eve
return CFReadStreamHasBytesAvailable(stream);
}
-(CFStreamStatus) status
{
if (stream)
{
return CFReadStreamGetStatus(stream);
}
return 0;
}
-(void) openCompleted
{
}
@end
@@ -15,15 +15,15 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@@ -35,31 +35,26 @@
#import <Foundation/Foundation.h>
#include <AudioToolbox/AudioToolbox.h>
@class DataSource;
@class STKDataSource;
@protocol DataSourceDelegate<NSObject>
-(void) dataSourceDataAvailable:(DataSource*)dataSource;
-(void) dataSourceErrorOccured:(DataSource*)dataSource;
-(void) dataSourceEof:(DataSource*)dataSource;
@protocol STKDataSourceDelegate<NSObject>
-(void) dataSourceDataAvailable:(STKDataSource*)dataSource;
-(void) dataSourceErrorOccured:(STKDataSource*)dataSource;
-(void) dataSourceEof:(STKDataSource*)dataSource;
@end
@protocol AudioDataSource<NSObject>
@property (readwrite) double averageBitRate;
@property (readwrite) long long audioDataOffset;
@end
@interface STKDataSource : NSObject
@interface DataSource : NSObject
@property (readonly) long long position;
@property (readonly) long long length;
@property (readonly) SInt64 position;
@property (readonly) SInt64 length;
@property (readonly) BOOL hasBytesAvailable;
@property (readwrite, unsafe_unretained) id<DataSourceDelegate> delegate;
@property (readwrite, unsafe_unretained) id<STKDataSourceDelegate> delegate;
-(BOOL) registerForEvents:(NSRunLoop*)runLoop;
-(void) unregisterForEvents;
-(void) close;
-(void) seekToOffset:(long long)offset;
-(void) seekToOffset:(SInt64)offset;
-(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size;
-(AudioFileTypeID) audioFileTypeHint;
@@ -15,15 +15,15 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@@ -32,17 +32,17 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "DataSource.h"
#import "STKDataSource.h"
@implementation DataSource
@implementation STKDataSource
@synthesize delegate;
-(long long) length
-(SInt64) length
{
return 0;
}
-(void) seekToOffset:(long long)offset
-(void) seekToOffset:(SInt64)offset
{
}
@@ -51,7 +51,7 @@
return -1;
}
-(long long) position
-(SInt64) position
{
return 0;
}
@@ -66,7 +66,7 @@
}
-(void) close
{
{
}
-(BOOL) hasBytesAvailable
@@ -5,7 +5,7 @@
https://github.com/tumtumtum/audjustable
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
@@ -15,12 +15,12 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
@@ -32,12 +32,12 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "DataSource.h"
#import "STKDataSource.h"
@interface DataSourceWrapper : DataSource<DataSourceDelegate>
@interface STKDataSourceWrapper : STKDataSource<STKDataSourceDelegate>
-(id) initWithDataSource:(DataSource*)innerDataSource;
-(id) initWithDataSource:(STKDataSource*)innerDataSource;
@property (readonly) DataSource* innerDataSource;
@property (readonly) STKDataSource* innerDataSource;
@end
@@ -5,7 +5,7 @@
https://github.com/tumtumtum/audjustable
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
@@ -15,12 +15,12 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
@@ -32,15 +32,15 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "DataSourceWrapper.h"
#import "STKDataSourceWrapper.h"
@interface DataSourceWrapper()
@property (readwrite) DataSource* innerDataSource;
@interface STKDataSourceWrapper()
@property (readwrite) STKDataSource* innerDataSource;
@end
@implementation DataSourceWrapper
@implementation STKDataSourceWrapper
-(id) initWithDataSource:(DataSource*)innerDataSourceIn
-(id) initWithDataSource:(STKDataSource*)innerDataSourceIn
{
if (self = [super init])
{
@@ -62,12 +62,12 @@
self.innerDataSource.delegate = nil;
}
-(long long) length
-(SInt64) length
{
return self.innerDataSource.length;
}
-(void) seekToOffset:(long long)offset
-(void) seekToOffset:(SInt64)offset
{
return [self.innerDataSource seekToOffset:offset];
}
@@ -77,7 +77,7 @@
return [self.innerDataSource readIntoBuffer:buffer withSize:size];
}
-(long long) position
-(SInt64) position
{
return self.innerDataSource.position;
}
@@ -102,17 +102,17 @@
return self.innerDataSource.hasBytesAvailable;
}
-(void) dataSourceDataAvailable:(DataSource*)dataSource
-(void) dataSourceDataAvailable:(STKDataSource*)dataSource
{
[self.delegate dataSourceDataAvailable:self];
}
-(void) dataSourceErrorOccured:(DataSource*)dataSource
-(void) dataSourceErrorOccured:(STKDataSource*)dataSource
{
[self.delegate dataSourceErrorOccured:self];
}
-(void) dataSourceEof:(DataSource*)dataSource
-(void) dataSourceEof:(STKDataSource*)dataSource
{
[self.delegate dataSourceEof:self];
}
@@ -15,39 +15,42 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
**********************************************************************************/
#import "CoreFoundationDataSource.h"
#import "STKCoreFoundationDataSource.h"
@interface HttpDataSource : CoreFoundationDataSource
{
@private
int seekStart;
int relativePosition;
int fileLength;
int discontinuous;
NSDictionary* httpHeaders;
AudioFileTypeID audioFileTypeHint;
}
@class STKHTTPDataSource;
@property (readwrite, retain) NSURL* url;
typedef void(^STKURLBlock)(NSURL* url);
typedef NSURL*(^STKURLProvider)();
typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock callback);
@interface STKHTTPDataSource : STKCoreFoundationDataSource
@property (readonly, retain) NSURL* url;
@property (readonly) UInt32 httpStatusCode;
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension;
-(id) initWithURL:(NSURL*)url;
-(id) initWithURL:(NSURL *)url httpRequestHeaders:(NSDictionary *)httpRequestHeaders;
-(id) initWithURLProvider:(STKURLProvider)urlProvider;
-(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider;
-(NSRunLoop*) eventsRunLoop;
-(void) reconnect;
@end
@@ -0,0 +1,397 @@
/**********************************************************************************
AudioPlayer.m
Created by Thong Nguyen on 14/05/2012.
https://github.com/tumtumtum/audjustable
Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "STKHTTPDataSource.h"
#import "STKLocalFileDataSource.h"
@interface STKHTTPDataSource()
{
@private
UInt32 httpStatusCode;
SInt64 seekStart;
SInt64 relativePosition;
SInt64 fileLength;
int discontinuous;
int requestSerialNumber;
NSURL* currentUrl;
STKAsyncURLProvider asyncUrlProvider;
NSDictionary* httpHeaders;
AudioFileTypeID audioFileTypeHint;
NSDictionary* requestHeaders;
}
-(void) open;
@end
@implementation STKHTTPDataSource
-(id) initWithURL:(NSURL*)urlIn
{
return [self initWithURLProvider:^NSURL* { return urlIn; }];
}
-(id) initWithURL:(NSURL *)urlIn httpRequestHeaders:(NSDictionary *)httpRequestHeaders
{
self = [self initWithURLProvider:^NSURL* { return urlIn; }];
self->requestHeaders = httpRequestHeaders;
return self;
}
-(id) initWithURLProvider:(STKURLProvider)urlProviderIn
{
urlProviderIn = [urlProviderIn copy];
return [self initWithAsyncURLProvider:^(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock block)
{
block(urlProviderIn());
}];
}
-(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn
{
if (self = [super init])
{
seekStart = 0;
relativePosition = 0;
fileLength = -1;
self->asyncUrlProvider = [asyncUrlProviderIn copy];
audioFileTypeHint = [STKLocalFileDataSource audioFileTypeHintFromFileExtension:self->currentUrl.pathExtension];
}
return self;
}
-(void) dealloc
{
NSLog(@"STKHTTPDataSource dealloc");
}
-(NSURL*) url
{
return self->currentUrl;
}
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)mimeType
{
static dispatch_once_t onceToken;
static NSDictionary* fileTypesByMimeType;
dispatch_once(&onceToken, ^
{
fileTypesByMimeType =
@{
@"audio/mp3": @(kAudioFileMP3Type),
@"audio/mpg": @(kAudioFileMP3Type),
@"audio/mpeg": @(kAudioFileMP3Type),
@"audio/wav": @(kAudioFileWAVEType),
@"audio/aifc": @(kAudioFileAIFCType),
@"audio/aiff": @(kAudioFileAIFFType),
@"audio/x-m4a": @(kAudioFileM4AType),
@"audio/x-mp4": @(kAudioFileMPEG4Type),
@"audio/aacp": @(kAudioFileAAC_ADTSType),
@"audio/m4a": @(kAudioFileM4AType),
@"audio/mp4": @(kAudioFileMPEG4Type),
@"audio/caf": @(kAudioFileCAFType),
@"audio/aac": @(kAudioFileAAC_ADTSType),
@"audio/ac3": @(kAudioFileAC3Type),
@"audio/3gp": @(kAudioFile3GPType)
};
});
NSNumber* number = [fileTypesByMimeType objectForKey:mimeType];
if (!number)
{
return 0;
}
return (AudioFileTypeID)number.intValue;
}
-(AudioFileTypeID) audioFileTypeHint
{
return audioFileTypeHint;
}
-(void) dataAvailable
{
if (stream == NULL) {
return;
}
if (self.httpStatusCode == 0)
{
CFTypeRef response = CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
if (response)
{
httpHeaders = (__bridge_transfer NSDictionary*)CFHTTPMessageCopyAllHeaderFields((CFHTTPMessageRef)response);
self->httpStatusCode = (UInt32)CFHTTPMessageGetResponseStatusCode((CFHTTPMessageRef)response);
CFRelease(response);
}
if (self.httpStatusCode == 200)
{
if (seekStart == 0)
{
fileLength = (SInt64)[[httpHeaders objectForKey:@"Content-Length"] longLongValue];
}
NSString* contentType = [httpHeaders objectForKey:@"Content-Type"];
AudioFileTypeID typeIdFromMimeType = [STKHTTPDataSource audioFileTypeHintFromMimeType:contentType];
if (typeIdFromMimeType != 0)
{
audioFileTypeHint = typeIdFromMimeType;
}
}
else if (self.httpStatusCode == 206)
{
NSString* contentRange = [httpHeaders objectForKey:@"Content-Range"];
NSArray* components = [contentRange componentsSeparatedByString:@"/"];
if (components.count == 2)
{
fileLength = [[components objectAtIndex:1] integerValue];
}
}
else if (self.httpStatusCode == 416)
{
if (self.length >= 0)
{
seekStart = self.length;
}
[self eof];
return;
}
else if (self.httpStatusCode >= 300)
{
[self errorOccured];
return;
}
}
[super dataAvailable];
}
-(SInt64) position
{
return seekStart + relativePosition;
}
-(SInt64) length
{
return fileLength >= 0 ? fileLength : 0;
}
-(void) reconnect
{
NSRunLoop* savedEventsRunLoop = eventsRunLoop;
[self close];
eventsRunLoop = savedEventsRunLoop;
[self seekToOffset:self.position];
}
-(void) seekToOffset:(SInt64)offset
{
NSRunLoop* savedEventsRunLoop = eventsRunLoop;
[self close];
eventsRunLoop = savedEventsRunLoop;
NSAssert([NSRunLoop currentRunLoop] == eventsRunLoop, @"Seek called on wrong thread");
stream = 0;
relativePosition = 0;
seekStart = offset;
self->isInErrorState = NO;
[self openForSeek:YES];
}
-(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size
{
if (size == 0)
{
return 0;
}
int read = (int)CFReadStreamRead(stream, buffer, size);
if (read < 0)
{
return read;
}
relativePosition += read;
return read;
}
-(void) open
{
return [self openForSeek:NO];
}
-(void) openForSeek:(BOOL)forSeek
{
int localRequestSerialNumber;
requestSerialNumber++;
localRequestSerialNumber = requestSerialNumber;
asyncUrlProvider(self, forSeek, ^(NSURL* url)
{
if (localRequestSerialNumber != self->requestSerialNumber)
{
return;
}
self->currentUrl = url;
if (url == nil)
{
return;
}
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)self->currentUrl, kCFHTTPVersion1_1);
if (seekStart > 0)
{
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), (__bridge CFStringRef)[NSString stringWithFormat:@"bytes=%lld-", seekStart]);
discontinuous = YES;
}
for (NSString* key in self->requestHeaders)
{
NSString* value = [self->requestHeaders objectForKey:key];
CFHTTPMessageSetHeaderFieldValue(message, (__bridge CFStringRef)key, (__bridge CFStringRef)value);
}
stream = CFReadStreamCreateForHTTPRequest(NULL, message);
if (stream == nil)
{
CFRelease(message);
[self errorOccured];
return;
}
if (!CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue))
{
CFRelease(message);
[self errorOccured];
return;
}
// Proxy support
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPProxy, proxySettings);
CFRelease(proxySettings);
// SSL support
if ([self->currentUrl.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)
{
NSDictionary* sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
[NSNull null], kCFStreamSSLPeerName,
nil];
CFReadStreamSetProperty(stream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)sslSettings);
}
[self reregisterForEvents];
self->httpStatusCode = 0;
// Open
if (!CFReadStreamOpen(stream))
{
CFRelease(stream);
CFRelease(message);
stream = 0;
[self errorOccured];
return;
}
self->isInErrorState = NO;
CFRelease(message);
});
}
-(UInt32) httpStatusCode
{
return self->httpStatusCode;
}
-(NSRunLoop*) eventsRunLoop
{
return self->eventsRunLoop;
}
-(NSString*) description
{
return [NSString stringWithFormat:@"HTTP data source with file length: %lld and position: %lld", self.length, self.position];
}
@end
@@ -15,15 +15,15 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@@ -32,20 +32,12 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "CoreFoundationDataSource.h"
#import "STKCoreFoundationDataSource.h"
@interface LocalFileDataSource : CoreFoundationDataSource
{
@private
long long position;
long long length;
AudioFileTypeID audioFileTypeHint;
}
@interface STKLocalFileDataSource : STKCoreFoundationDataSource
+(AudioFileTypeID) audioFileTypeHintFromFileExtension:(NSString*)fileExtension;
@property (readonly, copy) NSString* filePath;
-(id) initWithFilePath:(NSString*)filePath;
@end
@@ -15,15 +15,15 @@
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the
This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
4. Neither the name of Thong Nguyen nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@@ -32,15 +32,19 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************************/
#import "LocalFileDataSource.h"
#import "STKLocalFileDataSource.h"
@interface LocalFileDataSource()
@interface STKLocalFileDataSource()
{
SInt64 position;
SInt64 length;
AudioFileTypeID audioFileTypeHint;
}
@property (readwrite, copy) NSString* filePath;
-(void) open;
@end
@implementation LocalFileDataSource
@implementation STKLocalFileDataSource
@synthesize filePath;
-(id) initWithFilePath:(NSString*)filePathIn
@@ -49,9 +53,7 @@
{
self.filePath = filePathIn;
[self open];
audioFileTypeHint = [LocalFileDataSource audioFileTypeHintFromFileExtension:filePathIn.pathExtension];
audioFileTypeHint = [STKLocalFileDataSource audioFileTypeHintFromFileExtension:filePathIn.pathExtension];
}
return self;
@@ -103,6 +105,8 @@
{
if (stream)
{
[self unregisterForEvents];
CFReadStreamClose(stream);
stream = 0;
@@ -111,43 +115,57 @@
-(void) open
{
NSURL* url = [[NSURL alloc] initFileURLWithPath:self.filePath];
if (stream)
{
[self unregisterForEvents];
CFReadStreamClose(stream);
CFRelease(stream);
stream = 0;
}
NSURL* url = [[NSURL alloc] initFileURLWithPath:self.filePath];
stream = CFReadStreamCreateWithFile(NULL, (__bridge CFURLRef)url);
SInt32 errorCode;
NSNumber* number = (__bridge_transfer NSNumber*)CFURLCreatePropertyFromResource(NULL, (__bridge CFURLRef)url, kCFURLFileLength, &errorCode);
NSError* fileError;
NSFileManager* manager = [[NSFileManager alloc] init];
NSDictionary* attributes = [manager attributesOfItemAtPath:filePath error:&fileError];
if (fileError)
{
CFReadStreamClose(stream);
CFRelease(stream);
stream = 0;
return;
}
NSNumber* number = [attributes objectForKey:@"NSFileSize"];
if (number)
{
length = number.longLongValue;
}
[self reregisterForEvents];
CFReadStreamOpen(stream);
}
-(long long) position
-(SInt64) position
{
return position;
}
-(long long) length
-(SInt64) length
{
return length;
}
-(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size
{
int retval = CFReadStreamRead(stream, buffer, size);
int retval = (int)CFReadStreamRead(stream, buffer, size);
if (retval > 0)
{
@@ -163,7 +181,7 @@
return retval;
}
-(void) seekToOffset:(long long)offset
-(void) seekToOffset:(SInt64)offset
{
CFStreamStatus status = kCFStreamStatusClosed;
@@ -180,7 +198,18 @@
[self close];
[self open];
[self reregisterForEvents];
}
if (stream == 0)
{
CFRunLoopPerformBlock(eventsRunLoop.getCFRunLoop, NSRunLoopCommonModes, ^
{
[self errorOccured];
});
CFRunLoopWakeUp(eventsRunLoop.getCFRunLoop);
return;
}
if (CFReadStreamSetProperty(stream, kCFStreamPropertyFileCurrentOffset, (__bridge CFTypeRef)[NSNumber numberWithLongLong:offset]) != TRUE)
+45
View File
@@ -0,0 +1,45 @@
//
// STKQueueEntry.h
// StreamingKit
//
// Created by Thong Nguyen on 30/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import "STKDataSource.h"
#import "libkern/OSAtomic.h"
#import "AudioToolbox/AudioToolbox.h"
@interface STKQueueEntry : NSObject
{
@public
OSSpinLock spinLock;
BOOL parsedHeader;
Float64 sampleRate;
double packetDuration;
UInt64 audioDataOffset;
UInt64 audioDataByteCount;
UInt32 packetBufferSize;
volatile Float64 seekTime;
volatile SInt64 framesQueued;
volatile SInt64 framesPlayed;
volatile SInt64 lastFrameQueued;
volatile int processedPacketsCount;
volatile int processedPacketsSizeTotal;
AudioStreamBasicDescription audioStreamBasicDescription;
}
@property (readonly) UInt64 audioDataLengthInBytes;
@property (readwrite, retain) NSObject* queueItemId;
@property (readwrite, retain) STKDataSource* dataSource;
-(id) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
-(void) reset;
-(double) duration;
-(Float64) progressInFrames;
-(double) calculatedBitRate;
-(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription;
@end
+121
View File
@@ -0,0 +1,121 @@
//
// STKQueueEntry.m
// StreamingKit
//
// Created by Thong Nguyen on 30/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import "STKQueueEntry.h"
#import "STKDataSource.h"
#define STK_BIT_RATE_ESTIMATION_MIN_PACKETS_MIN (2)
#define STK_BIT_RATE_ESTIMATION_MIN_PACKETS_PREFERRED (64)
@implementation STKQueueEntry
-(id) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn
{
if (self = [super init])
{
self->spinLock = OS_SPINLOCK_INIT;
self.dataSource = dataSourceIn;
self.queueItemId = queueItemIdIn;
self->lastFrameQueued = -1;
}
return self;
}
-(void) reset
{
OSSpinLockLock(&self->spinLock);
self->framesQueued = 0;
self->framesPlayed = 0;
self->lastFrameQueued = -1;
OSSpinLockUnlock(&self->spinLock);
}
-(double) calculatedBitRate
{
double retval;
if (packetDuration > 0)
{
if (processedPacketsCount > STK_BIT_RATE_ESTIMATION_MIN_PACKETS_PREFERRED || (audioStreamBasicDescription.mBytesPerFrame == 0 && processedPacketsCount > STK_BIT_RATE_ESTIMATION_MIN_PACKETS_MIN))
{
double averagePacketByteSize = processedPacketsSizeTotal / processedPacketsCount;
retval = averagePacketByteSize / packetDuration * 8;
return retval;
}
}
retval = (audioStreamBasicDescription.mBytesPerFrame * audioStreamBasicDescription.mSampleRate) * 8;
return retval;
}
-(double) duration
{
if (self->sampleRate <= 0)
{
return 0;
}
UInt64 audioDataLengthInBytes = [self audioDataLengthInBytes];
double calculatedBitRate = [self calculatedBitRate];
if (calculatedBitRate < 1.0 || self.dataSource.length == 0)
{
return 0;
}
return audioDataLengthInBytes / (calculatedBitRate / 8);
}
-(UInt64) audioDataLengthInBytes
{
if (audioDataByteCount)
{
return audioDataByteCount;
}
else
{
if (!self.dataSource.length)
{
return 0;
}
return self.dataSource.length - audioDataOffset;
}
}
-(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription
{
if (self->audioStreamBasicDescription.mSampleRate == 0)
{
return NO;
}
return (memcmp(&(self->audioStreamBasicDescription), basicDescription, sizeof(*basicDescription)) == 0);
}
-(Float64) progressInFrames
{
OSSpinLockLock(&self->spinLock);
Float64 retval = self->seekTime + self->framesPlayed;
OSSpinLockUnlock(&self->spinLock);
return retval;
}
-(NSString*) description
{
return [[self queueItemId] description];
}
@end
@@ -0,0 +1,9 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#endif
@@ -0,0 +1,9 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
@@ -0,0 +1,13 @@
//
// StreamingKitMac.h
// StreamingKitMac
//
// Created by Thong Nguyen on 02/02/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface StreamingKitMac : NSObject
@end
@@ -0,0 +1,13 @@
//
// StreamingKitMac.m
// StreamingKitMac
//
// Created by Thong Nguyen on 02/02/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import "StreamingKitMac.h"
@implementation StreamingKitMac
@end
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.abstractpath.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
@@ -0,0 +1,34 @@
//
// StreamingKitMacTests.m
// StreamingKitMacTests
//
// Created by Thong Nguyen on 02/02/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface StreamingKitMacTests : XCTestCase
@end
@implementation StreamingKitMacTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
@@ -0,0 +1,34 @@
//
// StreamingKitTests.m
// StreamingKitTests
//
// Created by Thong Nguyen on 20/01/2014.
// Copyright (c) 2014 Thong Nguyen. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface StreamingKitTests : XCTestCase
@end
@implementation StreamingKitTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */