AudioPlayer.m 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279
  1. /**********************************************************************************
  2. AudioPlayer.m
  3. Created by Thong Nguyen on 14/05/2012.
  4. https://github.com/tumtumtum/audjustable
  5. Inspired by Matt Gallagher's AudioStreamer:
  6. https://github.com/mattgallagher/AudioStreamer
  7. Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
  8. Redistribution and use in source and binary forms, with or without
  9. modification, are permitted provided that the following conditions are met:
  10. 1. Redistributions of source code must retain the above copyright
  11. notice, this list of conditions and the following disclaimer.
  12. 2. Redistributions in binary form must reproduce the above copyright
  13. notice, this list of conditions and the following disclaimer in the
  14. documentation and/or other materials provided with the distribution.
  15. 3. All advertising materials mentioning features or use of this software
  16. must display the following acknowledgement:
  17. This product includes software developed by Thong Nguyen (tumtumtum@gmail.com)
  18. 4. Neither the name of Thong Nguyen nor the
  19. names of its contributors may be used to endorse or promote products
  20. derived from this software without specific prior written permission.
  21. THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY
  22. EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  23. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  24. DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  25. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  26. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  27. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  28. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. **********************************************************************************/
  32. #import "AudioPlayer.h"
  33. #import "AudioToolbox/AudioToolbox.h"
  34. #import "HttpDataSource.h"
  35. #import "LocalFileDataSource.h"
  36. #import "libkern/OSAtomic.h"
  37. #define BitRateEstimationMinPackets (64)
  38. #define AudioPlayerBuffersNeededToStart (16)
  39. #define AudioPlayerDefaultReadBufferSize (16 * 1024)
  40. #define AudioPlayerDefaultPacketBufferSize (2048)
  41. #define OSSTATUS_PARAM_ERROR (-50)
  42. @interface NSMutableArray(AudioPlayerExtensions)
  43. -(void) enqueue:(id)obj;
  44. -(id) dequeue;
  45. -(id) peek;
  46. @end
  47. @implementation NSMutableArray(AudioPlayerExtensions)
  48. -(void) enqueue:(id)obj
  49. {
  50. [self insertObject:obj atIndex:0];
  51. }
  52. -(void) skipQueue:(id)obj
  53. {
  54. [self addObject:obj];
  55. }
  56. -(id) dequeue
  57. {
  58. if ([self count] == 0)
  59. {
  60. return nil;
  61. }
  62. id retval = [self lastObject];
  63. [self removeLastObject];
  64. return retval;
  65. }
  66. -(id) peek
  67. {
  68. return [self lastObject];
  69. }
  70. -(id) peekRecent
  71. {
  72. if (self.count == 0)
  73. {
  74. return nil;
  75. }
  76. return [self objectAtIndex:0];
  77. }
  78. @end
  79. @interface QueueEntry : NSObject
  80. {
  81. @public
  82. BOOL parsedHeader;
  83. double sampleRate;
  84. double lastProgress;
  85. double packetDuration;
  86. UInt64 audioDataOffset;
  87. UInt64 audioDataByteCount;
  88. UInt32 packetBufferSize;
  89. volatile double seekTime;
  90. volatile int bytesPlayed;
  91. volatile int processedPacketsCount;
  92. volatile int processedPacketsSizeTotal;
  93. AudioStreamBasicDescription audioStreamBasicDescription;
  94. }
  95. @property (readwrite, retain) NSObject* queueItemId;
  96. @property (readwrite, retain) DataSource* dataSource;
  97. @property (readwrite) int bufferIndex;
  98. @property (readonly) UInt64 audioDataLengthInBytes;
  99. -(double) duration;
  100. -(double) calculatedBitRate;
  101. -(double) progress;
  102. -(id) initWithDataSource:(DataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
  103. -(id) initWithDataSource:(DataSource*)dataSource andQueueItemId:(NSObject*)queueItemId andBufferIndex:(int)bufferIndex;
  104. @end
  105. @implementation QueueEntry
  106. @synthesize dataSource, queueItemId, bufferIndex;
  107. -(id) initWithDataSource:(DataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn
  108. {
  109. return [self initWithDataSource:dataSourceIn andQueueItemId:queueItemIdIn andBufferIndex:-1];
  110. }
  111. -(id) initWithDataSource:(DataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn andBufferIndex:(int)bufferIndexIn
  112. {
  113. if (self = [super init])
  114. {
  115. self.dataSource = dataSourceIn;
  116. self.queueItemId = queueItemIdIn;
  117. self.bufferIndex = bufferIndexIn;
  118. }
  119. return self;
  120. }
  121. -(double) calculatedBitRate
  122. {
  123. double retval;
  124. if (packetDuration && processedPacketsCount > BitRateEstimationMinPackets)
  125. {
  126. double averagePacketByteSize = processedPacketsSizeTotal / processedPacketsCount;
  127. retval = averagePacketByteSize / packetDuration * 8;
  128. return retval;
  129. }
  130. retval = (audioStreamBasicDescription.mBytesPerFrame * audioStreamBasicDescription.mSampleRate) * 8;
  131. return retval;
  132. }
  133. -(void) updateAudioDataSource
  134. {
  135. if ([self->dataSource conformsToProtocol:@protocol(AudioDataSource)])
  136. {
  137. double calculatedBitrate = [self calculatedBitRate];
  138. id<AudioDataSource> audioDataSource = (id<AudioDataSource>)self->dataSource;
  139. audioDataSource.averageBitRate = calculatedBitrate;
  140. audioDataSource.audioDataOffset = audioDataOffset;
  141. }
  142. }
  143. -(double) progress
  144. {
  145. double retval = lastProgress;
  146. double duration = [self duration];
  147. if (self->sampleRate > 0)
  148. {
  149. double calculatedBitrate = [self calculatedBitRate];
  150. retval = self->bytesPlayed / calculatedBitrate * 8;
  151. retval = seekTime + retval;
  152. [self updateAudioDataSource];
  153. }
  154. if (retval > duration)
  155. {
  156. retval = duration;
  157. }
  158. return retval;
  159. }
  160. -(double) duration
  161. {
  162. if (self->sampleRate <= 0)
  163. {
  164. return 0;
  165. }
  166. UInt64 audioDataLengthInBytes = [self audioDataLengthInBytes];
  167. double calculatedBitRate = [self calculatedBitRate];
  168. if (calculatedBitRate == 0 || dataSource.length == 0)
  169. {
  170. return 0;
  171. }
  172. return audioDataLengthInBytes / (calculatedBitRate / 8);
  173. }
  174. -(UInt64) audioDataLengthInBytes
  175. {
  176. if (audioDataByteCount)
  177. {
  178. return audioDataByteCount;
  179. }
  180. else
  181. {
  182. if (!dataSource.length)
  183. {
  184. return 0;
  185. }
  186. return dataSource.length - audioDataOffset;
  187. }
  188. }
  189. -(NSString*) description
  190. {
  191. return [[self queueItemId] description];
  192. }
  193. @end
  194. @interface AudioPlayer()
  195. @property (readwrite) AudioPlayerInternalState internalState;
  196. -(void) logInfo:(NSString*)line;
  197. -(void) processQueue:(BOOL)skipCurrent;
  198. -(void) createAudioQueue;
  199. -(void) enqueueBuffer;
  200. -(void) resetAudioQueueWithReason:(NSString*)reason;
  201. -(BOOL) startAudioQueue;
  202. -(void) stopAudioQueueWithReason:(NSString*)reason;
  203. -(BOOL) processRunloop;
  204. -(void) wakeupPlaybackThread;
  205. -(void) audioQueueFinishedPlaying:(QueueEntry*)entry;
  206. -(void) processSeekToTime;
  207. -(void) didEncounterError:(AudioPlayerErrorCode)errorCode;
  208. -(void) setInternalState:(AudioPlayerInternalState)value;
  209. -(void) processDidFinishPlaying:(QueueEntry*)entry withNext:(QueueEntry*)next;
  210. -(void) handlePropertyChangeForFileStream:(AudioFileStreamID)audioFileStreamIn fileStreamPropertyID:(AudioFileStreamPropertyID)propertyID ioFlags:(UInt32*)ioFlags;
  211. -(void) handleAudioPackets:(const void*)inputData numberBytes:(UInt32)numberBytes numberPackets:(UInt32)numberPackets packetDescriptions:(AudioStreamPacketDescription*)packetDescriptions;
  212. -(void) handleAudioQueueOutput:(AudioQueueRef)audioQueue buffer:(AudioQueueBufferRef)buffer;
  213. -(void) handlePropertyChangeForQueue:(AudioQueueRef)audioQueue propertyID:(AudioQueuePropertyID)propertyID;
  214. @end
  215. static void AudioFileStreamPropertyListenerProc(void* clientData, AudioFileStreamID audioFileStream, AudioFileStreamPropertyID propertyId, UInt32* flags)
  216. {
  217. AudioPlayer* player = (__bridge AudioPlayer*)clientData;
  218. [player handlePropertyChangeForFileStream:audioFileStream fileStreamPropertyID:propertyId ioFlags:flags];
  219. }
  220. static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UInt32 numberPackets, const void* inputData, AudioStreamPacketDescription* packetDescriptions)
  221. {
  222. AudioPlayer* player = (__bridge AudioPlayer*)clientData;
  223. [player handleAudioPackets:inputData numberBytes:numberBytes numberPackets:numberPackets packetDescriptions:packetDescriptions];
  224. }
  225. static void AudioQueueOutputCallbackProc(void* clientData, AudioQueueRef audioQueue, AudioQueueBufferRef buffer)
  226. {
  227. AudioPlayer* player = (__bridge AudioPlayer*)clientData;
  228. [player handleAudioQueueOutput:audioQueue buffer:buffer];
  229. }
  230. static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQueue, AudioQueuePropertyID propertyId)
  231. {
  232. AudioPlayer* player = (__bridge AudioPlayer*)userData;
  233. [player handlePropertyChangeForQueue:audioQueue propertyID:propertyId];
  234. }
  235. @implementation AudioPlayer
  236. @synthesize delegate, internalState, state;
  237. -(AudioPlayerInternalState) internalState
  238. {
  239. return internalState;
  240. }
  241. -(void) setInternalState:(AudioPlayerInternalState)value
  242. {
  243. if (value == internalState)
  244. {
  245. return;
  246. }
  247. internalState = value;
  248. if ([self.delegate respondsToSelector:@selector(audioPlayer:internalStateChanged:)])
  249. {
  250. dispatch_async(dispatch_get_main_queue(), ^
  251. {
  252. [self.delegate audioPlayer:self internalStateChanged:internalState];
  253. });
  254. }
  255. AudioPlayerState newState;
  256. switch (internalState)
  257. {
  258. case AudioPlayerInternalStateInitialised:
  259. newState = AudioPlayerStateReady;
  260. break;
  261. case AudioPlayerInternalStateRunning:
  262. case AudioPlayerInternalStateStartingThread:
  263. case AudioPlayerInternalStateWaitingForData:
  264. case AudioPlayerInternalStateWaitingForQueueToStart:
  265. case AudioPlayerInternalStatePlaying:
  266. case AudioPlayerInternalStateRebuffering:
  267. newState = AudioPlayerStatePlaying;
  268. break;
  269. case AudioPlayerInternalStateStopping:
  270. case AudioPlayerInternalStateStopped:
  271. newState = AudioPlayerStateStopped;
  272. break;
  273. case AudioPlayerInternalStatePaused:
  274. newState = AudioPlayerStatePaused;
  275. break;
  276. case AudioPlayerInternalStateDisposed:
  277. newState = AudioPlayerStateDisposed;
  278. break;
  279. case AudioPlayerInternalStateError:
  280. newState = AudioPlayerStateError;
  281. break;
  282. }
  283. if (newState != self.state)
  284. {
  285. self.state = newState;
  286. dispatch_async(dispatch_get_main_queue(), ^
  287. {
  288. [self.delegate audioPlayer:self stateChanged:self.state];
  289. });
  290. }
  291. }
  292. -(AudioPlayerStopReason) stopReason
  293. {
  294. return stopReason;
  295. }
  296. -(BOOL) audioQueueIsRunning
  297. {
  298. UInt32 isRunning;
  299. UInt32 isRunningSize = sizeof(isRunning);
  300. AudioQueueGetProperty(audioQueue, kAudioQueueProperty_IsRunning, &isRunning, &isRunningSize);
  301. return isRunning ? YES : NO;
  302. }
  303. -(void) logInfo:(NSString*)line
  304. {
  305. if ([self->delegate respondsToSelector:@selector(audioPlayer:logInfo:)])
  306. {
  307. [self->delegate audioPlayer:self logInfo:line];
  308. }
  309. }
  310. -(id) init
  311. {
  312. return [self initWithNumberOfAudioQueueBuffers:AudioPlayerDefaultNumberOfAudioQueueBuffers andReadBufferSize:AudioPlayerDefaultReadBufferSize];
  313. }
  314. -(id) initWithNumberOfAudioQueueBuffers:(int)numberOfAudioQueueBuffers andReadBufferSize:(int)readBufferSizeIn
  315. {
  316. if (self = [super init])
  317. {
  318. fastApiQueue = [[NSOperationQueue alloc] init];
  319. [fastApiQueue setMaxConcurrentOperationCount:1];
  320. readBufferSize = readBufferSizeIn;
  321. readBuffer = calloc(sizeof(UInt8), readBufferSize);
  322. audioQueueBufferCount = numberOfAudioQueueBuffers;
  323. audioQueueBuffer = calloc(sizeof(AudioQueueBufferRef), audioQueueBufferCount);
  324. audioQueueBufferRefLookupCount = audioQueueBufferCount * 2;
  325. audioQueueBufferLookup = calloc(sizeof(AudioQueueBufferRefLookupEntry), audioQueueBufferRefLookupCount);
  326. packetDescs = calloc(sizeof(AudioStreamPacketDescription), audioQueueBufferCount);
  327. bufferUsed = calloc(sizeof(bool), audioQueueBufferCount);
  328. pthread_mutexattr_t attr;
  329. pthread_mutexattr_init(&attr);
  330. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  331. pthread_mutex_init(&playerMutex, &attr);
  332. pthread_mutex_init(&queueBuffersMutex, NULL);
  333. pthread_cond_init(&queueBufferReadyCondition, NULL);
  334. threadFinishedCondLock = [[NSConditionLock alloc] initWithCondition:0];
  335. self.internalState = AudioPlayerInternalStateInitialised;
  336. upcomingQueue = [[NSMutableArray alloc] init];
  337. bufferingQueue = [[NSMutableArray alloc] init];
  338. }
  339. return self;
  340. }
  341. -(void) dealloc
  342. {
  343. if (currentlyReadingEntry)
  344. {
  345. currentlyReadingEntry.dataSource.delegate = nil;
  346. }
  347. if (currentlyPlayingEntry)
  348. {
  349. currentlyPlayingEntry.dataSource.delegate = nil;
  350. }
  351. pthread_mutex_destroy(&playerMutex);
  352. pthread_mutex_destroy(&queueBuffersMutex);
  353. pthread_cond_destroy(&queueBufferReadyCondition);
  354. if (audioFileStream)
  355. {
  356. AudioFileStreamClose(audioFileStream);
  357. }
  358. if (audioQueue)
  359. {
  360. AudioQueueDispose(audioQueue, true);
  361. }
  362. free(bufferUsed);
  363. free(readBuffer);
  364. free(packetDescs);
  365. free(audioQueueBuffer);
  366. free(audioQueueBufferLookup);
  367. free(levelMeterState);
  368. }
  369. -(void) startSystemBackgroundTask
  370. {
  371. pthread_mutex_lock(&playerMutex);
  372. {
  373. if (backgroundTaskId != UIBackgroundTaskInvalid)
  374. {
  375. pthread_mutex_unlock(&playerMutex);
  376. return;
  377. }
  378. backgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
  379. {
  380. [self stopSystemBackgroundTask];
  381. }];
  382. }
  383. pthread_mutex_unlock(&playerMutex);
  384. }
  385. -(void) stopSystemBackgroundTask
  386. {
  387. pthread_mutex_lock(&playerMutex);
  388. {
  389. if (backgroundTaskId != UIBackgroundTaskInvalid)
  390. {
  391. [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskId];
  392. backgroundTaskId = UIBackgroundTaskInvalid;
  393. }
  394. }
  395. pthread_mutex_unlock(&playerMutex);
  396. }
  397. -(DataSource*) dataSourceFromURL:(NSURL*)url
  398. {
  399. DataSource* retval;
  400. if ([url.scheme isEqualToString:@"file"])
  401. {
  402. retval = [[LocalFileDataSource alloc] initWithFilePath:url.path];
  403. }
  404. else
  405. {
  406. retval = [[HttpDataSource alloc] initWithURL:url];
  407. }
  408. return retval;
  409. }
  410. -(void) clearQueue
  411. {
  412. pthread_mutex_lock(&playerMutex);
  413. {
  414. NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:bufferingQueue.count + upcomingQueue.count];
  415. QueueEntry* entry = [bufferingQueue dequeue];
  416. if (entry && entry != currentlyPlayingEntry)
  417. {
  418. [array addObject:[entry queueItemId]];
  419. }
  420. while (bufferingQueue.count > 0)
  421. {
  422. [array addObject:[[bufferingQueue dequeue] queueItemId]];
  423. }
  424. for (QueueEntry* entry in upcomingQueue)
  425. {
  426. [array addObject:entry.queueItemId];
  427. }
  428. [upcomingQueue removeAllObjects];
  429. dispatch_async(dispatch_get_main_queue(), ^
  430. {
  431. if ([self.delegate respondsToSelector:@selector(audioPlayer:didCancelQueuedItems:)])
  432. {
  433. [self.delegate audioPlayer:self didCancelQueuedItems:array];
  434. }
  435. });
  436. }
  437. pthread_mutex_unlock(&playerMutex);
  438. }
  439. -(void) play:(NSURL*)url
  440. {
  441. [self setDataSource:[self dataSourceFromURL:url] withQueueItemId:url];
  442. }
  443. -(void) setDataSource:(DataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId
  444. {
  445. [fastApiQueue cancelAllOperations];
  446. [fastApiQueue addOperationWithBlock:^
  447. {
  448. pthread_mutex_lock(&playerMutex);
  449. {
  450. [self startSystemBackgroundTask];
  451. [self clearQueue];
  452. [upcomingQueue enqueue:[[QueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
  453. self.internalState = AudioPlayerInternalStateRunning;
  454. [self processQueue:YES];
  455. }
  456. pthread_mutex_unlock(&playerMutex);
  457. }];
  458. }
  459. -(void) queueDataSource:(DataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId
  460. {
  461. [fastApiQueue addOperationWithBlock:^
  462. {
  463. pthread_mutex_lock(&playerMutex);
  464. {
  465. [upcomingQueue enqueue:[[QueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]];
  466. [self processQueue:NO];
  467. }
  468. pthread_mutex_unlock(&playerMutex);
  469. }];
  470. }
  471. -(void) handlePropertyChangeForFileStream:(AudioFileStreamID)inAudioFileStream fileStreamPropertyID:(AudioFileStreamPropertyID)inPropertyID ioFlags:(UInt32*)ioFlags
  472. {
  473. OSStatus error;
  474. switch (inPropertyID)
  475. {
  476. case kAudioFileStreamProperty_DataOffset:
  477. {
  478. SInt64 offset;
  479. UInt32 offsetSize = sizeof(offset);
  480. AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_DataOffset, &offsetSize, &offset);
  481. currentlyReadingEntry->parsedHeader = YES;
  482. currentlyReadingEntry->audioDataOffset = offset;
  483. [currentlyReadingEntry updateAudioDataSource];
  484. }
  485. break;
  486. case kAudioFileStreamProperty_DataFormat:
  487. {
  488. if (currentlyReadingEntry->audioStreamBasicDescription.mSampleRate == 0) {
  489. AudioStreamBasicDescription newBasicDescription;
  490. UInt32 size = sizeof(newBasicDescription);
  491. AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &size, &newBasicDescription);
  492. currentlyReadingEntry->audioStreamBasicDescription = newBasicDescription;
  493. }
  494. currentlyReadingEntry->sampleRate = currentlyReadingEntry->audioStreamBasicDescription.mSampleRate;
  495. currentlyReadingEntry->packetDuration = currentlyReadingEntry->audioStreamBasicDescription.mFramesPerPacket / currentlyReadingEntry->sampleRate;
  496. UInt32 packetBufferSize = 0;
  497. UInt32 sizeOfPacketBufferSize = sizeof(packetBufferSize);
  498. error = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfPacketBufferSize, &packetBufferSize);
  499. if (error || packetBufferSize == 0)
  500. {
  501. error = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfPacketBufferSize, &packetBufferSize);
  502. if (error || packetBufferSize == 0)
  503. {
  504. currentlyReadingEntry->packetBufferSize = AudioPlayerDefaultPacketBufferSize;
  505. }
  506. }
  507. [currentlyReadingEntry updateAudioDataSource];
  508. AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1);
  509. }
  510. break;
  511. case kAudioFileStreamProperty_AudioDataByteCount:
  512. {
  513. UInt64 audioDataByteCount;
  514. UInt32 byteCountSize = sizeof(audioDataByteCount);
  515. AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &audioDataByteCount);
  516. currentlyReadingEntry->audioDataByteCount = audioDataByteCount;
  517. [currentlyReadingEntry updateAudioDataSource];
  518. }
  519. break;
  520. case kAudioFileStreamProperty_ReadyToProducePackets:
  521. {
  522. discontinuous = YES;
  523. }
  524. break;
  525. case kAudioFileStreamProperty_FormatList:
  526. {
  527. Boolean outWriteable;
  528. UInt32 formatListSize;
  529. OSStatus err = AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, &outWriteable);
  530. if (err)
  531. {
  532. break;
  533. }
  534. AudioFormatListItem *formatList = malloc(formatListSize);
  535. err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, formatList);
  536. if (err)
  537. {
  538. free(formatList);
  539. break;
  540. }
  541. for (int i = 0; i * sizeof(AudioFormatListItem) < formatListSize; i += sizeof(AudioFormatListItem))
  542. {
  543. AudioStreamBasicDescription pasbd = formatList[i].mASBD;
  544. if (pasbd.mFormatID == kAudioFormatMPEG4AAC_HE ||
  545. pasbd.mFormatID == kAudioFormatMPEG4AAC_HE_V2)
  546. {
  547. //
  548. // We've found HE-AAC, remember this to tell the audio queue
  549. // when we construct it.
  550. //
  551. #if !TARGET_IPHONE_SIMULATOR
  552. currentlyReadingEntry->audioStreamBasicDescription = pasbd;
  553. #endif
  554. break;
  555. }
  556. }
  557. free(formatList);
  558. }
  559. break;
  560. }
  561. }
  562. -(void) handleAudioPackets:(const void*)inputData numberBytes:(UInt32)numberBytes numberPackets:(UInt32)numberPackets packetDescriptions:(AudioStreamPacketDescription*)packetDescriptionsIn
  563. {
  564. if (currentlyReadingEntry == nil)
  565. {
  566. return;
  567. }
  568. if (seekToTimeWasRequested)
  569. {
  570. return;
  571. }
  572. if (audioQueue == nil)
  573. {
  574. [self createAudioQueue];
  575. }
  576. else if (memcmp(&currentAudioStreamBasicDescription, &currentlyReadingEntry->audioStreamBasicDescription, sizeof(currentAudioStreamBasicDescription)) != 0)
  577. {
  578. if (currentlyReadingEntry == currentlyPlayingEntry)
  579. {
  580. [self createAudioQueue];
  581. }
  582. else
  583. {
  584. return;
  585. }
  586. }
  587. if (discontinuous)
  588. {
  589. discontinuous = NO;
  590. }
  591. if (packetDescriptionsIn)
  592. {
  593. // VBR
  594. for (int i = 0; i < numberPackets; i++)
  595. {
  596. SInt64 packetOffset = packetDescriptionsIn[i].mStartOffset;
  597. SInt64 packetSize = packetDescriptionsIn[i].mDataByteSize;
  598. int bufSpaceRemaining;
  599. if (currentlyReadingEntry->processedPacketsSizeTotal < 0xfffff)
  600. {
  601. OSAtomicAdd32((int32_t)packetSize, &currentlyReadingEntry->processedPacketsSizeTotal);
  602. OSAtomicIncrement32(&currentlyReadingEntry->processedPacketsCount);
  603. }
  604. if (packetSize > currentlyReadingEntry->packetBufferSize)
  605. {
  606. return;
  607. }
  608. bufSpaceRemaining = currentlyReadingEntry->packetBufferSize - bytesFilled;
  609. if (bufSpaceRemaining < packetSize)
  610. {
  611. [self enqueueBuffer];
  612. if (seekToTimeWasRequested || self.internalState == AudioPlayerInternalStateStopped || self.internalState == AudioPlayerInternalStateStopping || self.internalState == AudioPlayerInternalStateDisposed)
  613. {
  614. return;
  615. }
  616. }
  617. if (bytesFilled + packetSize > currentlyReadingEntry->packetBufferSize)
  618. {
  619. return;
  620. }
  621. AudioQueueBufferRef bufferToFill = audioQueueBuffer[fillBufferIndex];
  622. memcpy((char*)bufferToFill->mAudioData + bytesFilled, (const char*)inputData + packetOffset, packetSize);
  623. packetDescs[packetsFilled] = packetDescriptionsIn[i];
  624. packetDescs[packetsFilled].mStartOffset = bytesFilled;
  625. bytesFilled += packetSize;
  626. packetsFilled++;
  627. int packetsDescRemaining = audioQueueBufferCount - packetsFilled;
  628. if (packetsDescRemaining <= 0)
  629. {
  630. [self enqueueBuffer];
  631. if (seekToTimeWasRequested || self.internalState == AudioPlayerInternalStateStopped || self.internalState == AudioPlayerInternalStateStopping || self.internalState == AudioPlayerInternalStateDisposed)
  632. {
  633. return;
  634. }
  635. }
  636. }
  637. }
  638. else
  639. {
  640. // CBR
  641. int offset = 0;
  642. while (numberBytes)
  643. {
  644. int bytesLeft = AudioPlayerDefaultPacketBufferSize - bytesFilled;
  645. if (bytesLeft < numberBytes)
  646. {
  647. [self enqueueBuffer];
  648. if (seekToTimeWasRequested || self.internalState == AudioPlayerInternalStateStopped || self.internalState == AudioPlayerInternalStateStopping || self.internalState == AudioPlayerInternalStateDisposed)
  649. {
  650. return;
  651. }
  652. }
  653. pthread_mutex_lock(&playerMutex);
  654. {
  655. int copySize;
  656. bytesLeft = AudioPlayerDefaultPacketBufferSize - bytesFilled;
  657. if (bytesLeft < numberBytes)
  658. {
  659. copySize = bytesLeft;
  660. }
  661. else
  662. {
  663. copySize = numberBytes;
  664. }
  665. if (bytesFilled > currentlyPlayingEntry->packetBufferSize)
  666. {
  667. pthread_mutex_unlock(&playerMutex);
  668. return;
  669. }
  670. AudioQueueBufferRef fillBuf = audioQueueBuffer[fillBufferIndex];
  671. memcpy((char*)fillBuf->mAudioData + bytesFilled, (const char*)(inputData + offset), copySize);
  672. bytesFilled += copySize;
  673. packetsFilled = 0;
  674. numberBytes -= copySize;
  675. offset += copySize;
  676. }
  677. pthread_mutex_unlock(&playerMutex);
  678. }
  679. }
  680. }
  681. -(void) handleAudioQueueOutput:(AudioQueueRef)audioQueueIn buffer:(AudioQueueBufferRef)bufferIn
  682. {
  683. int bufferIndex = -1;
  684. if (audioQueueIn != audioQueue)
  685. {
  686. return;
  687. }
  688. QueueEntry* entry = nil;
  689. if (currentlyPlayingEntry)
  690. {
  691. OSSpinLockLock(&currentlyPlayingLock);
  692. {
  693. if (currentlyPlayingEntry)
  694. {
  695. entry = currentlyPlayingEntry;
  696. if (!audioQueueFlushing)
  697. {
  698. currentlyPlayingEntry->bytesPlayed += bufferIn->mAudioDataByteSize;
  699. }
  700. }
  701. }
  702. OSSpinLockUnlock(&currentlyPlayingLock);
  703. }
  704. int index = (int)bufferIn % audioQueueBufferRefLookupCount;
  705. for (int i = 0; i < audioQueueBufferCount; i++)
  706. {
  707. if (audioQueueBufferLookup[index].ref == bufferIn)
  708. {
  709. bufferIndex = audioQueueBufferLookup[index].bufferIndex;
  710. break;
  711. }
  712. index = (index + 1) % audioQueueBufferRefLookupCount;
  713. }
  714. audioPacketsPlayedCount++;
  715. if (bufferIndex == -1)
  716. {
  717. [self didEncounterError:AudioPlayerErrorUnknownBuffer];
  718. pthread_mutex_lock(&queueBuffersMutex);
  719. pthread_cond_signal(&queueBufferReadyCondition);
  720. pthread_mutex_unlock(&queueBuffersMutex);
  721. return;
  722. }
  723. pthread_mutex_lock(&queueBuffersMutex);
  724. BOOL signal = NO;
  725. if (bufferUsed[bufferIndex])
  726. {
  727. bufferUsed[bufferIndex] = false;
  728. numberOfBuffersUsed--;
  729. }
  730. else
  731. {
  732. // This should never happen
  733. signal = YES;
  734. }
  735. if (!audioQueueFlushing && [self progress] > 4.0 && numberOfBuffersUsed == 0 ) {
  736. self.internalState = AudioPlayerInternalStateRebuffering;
  737. }
  738. if (!audioQueueFlushing)
  739. {
  740. if (entry != nil)
  741. {
  742. if (entry.bufferIndex == audioPacketsPlayedCount && entry.bufferIndex != -1)
  743. {
  744. entry.bufferIndex = -1;
  745. if (playbackThread)
  746. {
  747. CFRunLoopPerformBlock([playbackThreadRunLoop getCFRunLoop], NSDefaultRunLoopMode, ^
  748. {
  749. [self audioQueueFinishedPlaying:entry];
  750. });
  751. CFRunLoopWakeUp([playbackThreadRunLoop getCFRunLoop]);
  752. signal = YES;
  753. }
  754. }
  755. }
  756. }
  757. if (self.internalState == AudioPlayerInternalStateStopped
  758. || self.internalState == AudioPlayerInternalStateStopping
  759. || self.internalState == AudioPlayerInternalStateDisposed
  760. || self.internalState == AudioPlayerInternalStateError
  761. || self.internalState == AudioPlayerInternalStateWaitingForQueueToStart)
  762. {
  763. signal = waiting || numberOfBuffersUsed < 8;
  764. }
  765. else if (audioQueueFlushing)
  766. {
  767. signal = signal || (audioQueueFlushing && numberOfBuffersUsed < 8);
  768. }
  769. else
  770. {
  771. if (seekToTimeWasRequested)
  772. {
  773. signal = YES;
  774. }
  775. else
  776. {
  777. if ((waiting && numberOfBuffersUsed < audioQueueBufferCount / 2) || (numberOfBuffersUsed < 8))
  778. {
  779. signal = YES;
  780. }
  781. }
  782. }
  783. if (signal)
  784. {
  785. pthread_cond_signal(&queueBufferReadyCondition);
  786. }
  787. pthread_mutex_unlock(&queueBuffersMutex);
  788. }
  789. -(void) handlePropertyChangeForQueue:(AudioQueueRef)audioQueueIn propertyID:(AudioQueuePropertyID)propertyId
  790. {
  791. if (audioQueueIn != audioQueue)
  792. {
  793. return;
  794. }
  795. if (propertyId == kAudioQueueProperty_IsRunning)
  796. {
  797. if (![self audioQueueIsRunning] && self.internalState == AudioPlayerInternalStateStopping)
  798. {
  799. self.internalState = AudioPlayerInternalStateStopped;
  800. }
  801. else if (self.internalState == AudioPlayerInternalStateWaitingForQueueToStart)
  802. {
  803. [NSRunLoop currentRunLoop];
  804. self.internalState = AudioPlayerInternalStatePlaying;
  805. }
  806. }
  807. }
  808. -(void) enqueueBuffer
  809. {
  810. pthread_mutex_lock(&playerMutex);
  811. {
  812. OSStatus error;
  813. if (audioFileStream == 0)
  814. {
  815. pthread_mutex_unlock(&playerMutex);
  816. return;
  817. }
  818. if (self.internalState == AudioPlayerInternalStateStopped)
  819. {
  820. pthread_mutex_unlock(&playerMutex);
  821. return;
  822. }
  823. if (audioQueueFlushing || newFileToPlay)
  824. {
  825. pthread_mutex_unlock(&playerMutex);
  826. return;
  827. }
  828. pthread_mutex_lock(&queueBuffersMutex);
  829. bufferUsed[fillBufferIndex] = true;
  830. numberOfBuffersUsed++;
  831. pthread_mutex_unlock(&queueBuffersMutex);
  832. AudioQueueBufferRef buffer = audioQueueBuffer[fillBufferIndex];
  833. buffer->mAudioDataByteSize = bytesFilled;
  834. if (packetsFilled)
  835. {
  836. error = AudioQueueEnqueueBuffer(audioQueue, buffer, packetsFilled, packetDescs);
  837. }
  838. else
  839. {
  840. error = AudioQueueEnqueueBuffer(audioQueue, buffer, 0, NULL);
  841. }
  842. audioPacketsReadCount++;
  843. if (error)
  844. {
  845. pthread_mutex_unlock(&playerMutex);
  846. return;
  847. }
  848. if (self.internalState == AudioPlayerInternalStateWaitingForData && numberOfBuffersUsed >= AudioPlayerBuffersNeededToStart)
  849. {
  850. if (![self startAudioQueue])
  851. {
  852. pthread_mutex_unlock(&playerMutex);
  853. return;
  854. }
  855. }
  856. if (self.internalState == AudioPlayerInternalStateRebuffering && numberOfBuffersUsed >= AudioPlayerBuffersNeededToStart)
  857. {
  858. self.internalState = AudioPlayerInternalStatePlaying;
  859. }
  860. if (++fillBufferIndex >= audioQueueBufferCount)
  861. {
  862. fillBufferIndex = 0;
  863. }
  864. bytesFilled = 0;
  865. packetsFilled = 0;
  866. }
  867. pthread_mutex_unlock(&playerMutex);
  868. pthread_mutex_lock(&queueBuffersMutex);
  869. waiting = YES;
  870. while (bufferUsed[fillBufferIndex] && !(seekToTimeWasRequested || self.internalState == AudioPlayerInternalStateStopped || self.internalState == AudioPlayerInternalStateStopping || self.internalState == AudioPlayerInternalStateDisposed))
  871. {
  872. if (numberOfBuffersUsed == 0)
  873. {
  874. memset(&bufferUsed[0], 0, sizeof(bool) * audioQueueBufferCount);
  875. break;
  876. }
  877. pthread_cond_wait(&queueBufferReadyCondition, &queueBuffersMutex);
  878. }
  879. waiting = NO;
  880. pthread_mutex_unlock(&queueBuffersMutex);
  881. }
  882. -(void) didEncounterError:(AudioPlayerErrorCode)errorCodeIn
  883. {
  884. errorCode = errorCodeIn;
  885. self.internalState = AudioPlayerInternalStateError;
  886. dispatch_async(dispatch_get_main_queue(), ^
  887. {
  888. [self.delegate audioPlayer:self didEncounterError:errorCode];
  889. });
  890. }
  891. -(void) createAudioQueue
  892. {
  893. OSStatus error;
  894. [self startSystemBackgroundTask];
  895. if (audioQueue)
  896. {
  897. AudioQueueStop(audioQueue, YES);
  898. AudioQueueDispose(audioQueue, YES);
  899. audioQueue = nil;
  900. }
  901. OSSpinLockLock(&currentlyPlayingLock);
  902. currentAudioStreamBasicDescription = currentlyPlayingEntry->audioStreamBasicDescription;
  903. OSSpinLockUnlock(&currentlyPlayingLock);
  904. error = AudioQueueNewOutput(&currentlyPlayingEntry->audioStreamBasicDescription, AudioQueueOutputCallbackProc, (__bridge void*)self, NULL, NULL, 0, &audioQueue);
  905. if (error)
  906. {
  907. return;
  908. }
  909. error = AudioQueueAddPropertyListener(audioQueue, kAudioQueueProperty_IsRunning, AudioQueueIsRunningCallbackProc, (__bridge void*)self);
  910. if (error)
  911. {
  912. return;
  913. }
  914. #if TARGET_OS_IPHONE
  915. UInt32 val = kAudioQueueHardwareCodecPolicy_PreferHardware;
  916. AudioQueueSetProperty(audioQueue, kAudioQueueProperty_HardwareCodecPolicy, &val, sizeof(UInt32));
  917. AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1);
  918. #endif
  919. memset(audioQueueBufferLookup, 0, sizeof(AudioQueueBufferRefLookupEntry) * audioQueueBufferRefLookupCount);
  920. // Allocate AudioQueue buffers
  921. for (int i = 0; i < audioQueueBufferCount; i++)
  922. {
  923. error = AudioQueueAllocateBuffer(audioQueue, currentlyPlayingEntry->packetBufferSize, &audioQueueBuffer[i]);
  924. unsigned int hash = (unsigned int)audioQueueBuffer[i] % audioQueueBufferRefLookupCount;
  925. while (true)
  926. {
  927. if (audioQueueBufferLookup[hash].ref == 0)
  928. {
  929. audioQueueBufferLookup[hash].ref = audioQueueBuffer[i];
  930. audioQueueBufferLookup[hash].bufferIndex = i;
  931. break;
  932. }
  933. else
  934. {
  935. hash++;
  936. hash %= audioQueueBufferRefLookupCount;
  937. }
  938. }
  939. bufferUsed[i] = false;
  940. if (error)
  941. {
  942. return;
  943. }
  944. }
  945. audioPacketsReadCount = 0;
  946. audioPacketsPlayedCount = 0;
  947. // Get file cookie/magic bytes information
  948. UInt32 cookieSize;
  949. Boolean writable;
  950. error = AudioFileStreamGetPropertyInfo(audioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable);
  951. if (error)
  952. {
  953. return;
  954. }
  955. void* cookieData = calloc(1, cookieSize);
  956. error = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData);
  957. if (error)
  958. {
  959. free(cookieData);
  960. return;
  961. }
  962. error = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_MagicCookie, cookieData, cookieSize);
  963. if (error)
  964. {
  965. free(cookieData);
  966. return;
  967. }
  968. AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1);
  969. // Reset metering enabled in case the user set it before the queue was created
  970. [self setMeteringEnabled:meteringEnabled];
  971. free(cookieData);
  972. }
  973. -(double) duration
  974. {
  975. if (newFileToPlay)
  976. {
  977. return 0;
  978. }
  979. OSSpinLockLock(&currentlyPlayingLock);
  980. QueueEntry* entry = currentlyPlayingEntry;
  981. if (entry == nil)
  982. {
  983. OSSpinLockUnlock(&currentlyPlayingLock);
  984. return 0;
  985. }
  986. double retval = [entry duration];
  987. OSSpinLockUnlock(&currentlyPlayingLock);
  988. return retval;
  989. }
  990. -(double) progress
  991. {
  992. if (seekToTimeWasRequested)
  993. {
  994. return requestedSeekTime;
  995. }
  996. if (newFileToPlay)
  997. {
  998. return 0;
  999. }
  1000. OSSpinLockLock(&currentlyPlayingLock);
  1001. QueueEntry* entry = currentlyPlayingEntry;
  1002. if (entry == nil)
  1003. {
  1004. OSSpinLockUnlock(&currentlyPlayingLock);
  1005. return 0;
  1006. }
  1007. double retval = [entry progress];
  1008. OSSpinLockUnlock(&currentlyPlayingLock);
  1009. return retval;
  1010. }
  1011. -(void) wakeupPlaybackThread
  1012. {
  1013. NSRunLoop* runLoop = playbackThreadRunLoop;
  1014. if (runLoop)
  1015. {
  1016. CFRunLoopPerformBlock([runLoop getCFRunLoop], NSDefaultRunLoopMode, ^
  1017. {
  1018. [self processRunloop];
  1019. });
  1020. CFRunLoopWakeUp([runLoop getCFRunLoop]);
  1021. }
  1022. pthread_mutex_lock(&queueBuffersMutex);
  1023. if (waiting)
  1024. {
  1025. pthread_cond_signal(&queueBufferReadyCondition);
  1026. }
  1027. pthread_mutex_unlock(&queueBuffersMutex);
  1028. }
  1029. -(void) seekToTime:(double)value
  1030. {
  1031. pthread_mutex_lock(&playerMutex);
  1032. {
  1033. BOOL seekAlreadyRequested = seekToTimeWasRequested;
  1034. seekToTimeWasRequested = YES;
  1035. requestedSeekTime = value;
  1036. if (!seekAlreadyRequested)
  1037. {
  1038. [self wakeupPlaybackThread];
  1039. }
  1040. }
  1041. pthread_mutex_unlock(&playerMutex);
  1042. }
  1043. -(void) processQueue:(BOOL)skipCurrent
  1044. {
  1045. if (playbackThread == nil)
  1046. {
  1047. newFileToPlay = YES;
  1048. playbackThread = [[NSThread alloc] initWithTarget:self selector:@selector(startInternal) object:nil];
  1049. [playbackThread start];
  1050. [self wakeupPlaybackThread];
  1051. }
  1052. else
  1053. {
  1054. if (skipCurrent)
  1055. {
  1056. newFileToPlay = YES;
  1057. [self resetAudioQueueWithReason:@"from skipCurrent"];
  1058. }
  1059. [self wakeupPlaybackThread];
  1060. }
  1061. }
  1062. -(void) setCurrentlyReadingEntry:(QueueEntry*)entry andStartPlaying:(BOOL)startPlaying
  1063. {
  1064. pthread_mutex_lock(&queueBuffersMutex);
  1065. if (startPlaying)
  1066. {
  1067. if (audioQueue)
  1068. {
  1069. pthread_mutex_unlock(&queueBuffersMutex);
  1070. [self resetAudioQueueWithReason:@"from setCurrentlyReadingEntry"];
  1071. pthread_mutex_lock(&queueBuffersMutex);
  1072. }
  1073. }
  1074. if (audioFileStream)
  1075. {
  1076. AudioFileStreamClose(audioFileStream);
  1077. audioFileStream = 0;
  1078. }
  1079. if (currentlyReadingEntry)
  1080. {
  1081. currentlyReadingEntry.dataSource.delegate = nil;
  1082. [currentlyReadingEntry.dataSource unregisterForEvents];
  1083. [currentlyReadingEntry.dataSource close];
  1084. }
  1085. currentlyReadingEntry = entry;
  1086. currentlyReadingEntry.dataSource.delegate = self;
  1087. if (currentlyReadingEntry.dataSource.position != 0)
  1088. {
  1089. [currentlyReadingEntry.dataSource seekToOffset:0];
  1090. }
  1091. [currentlyReadingEntry.dataSource registerForEvents:[NSRunLoop currentRunLoop]];
  1092. if (startPlaying)
  1093. {
  1094. [bufferingQueue removeAllObjects];
  1095. [self processDidFinishPlaying:currentlyPlayingEntry withNext:entry];
  1096. }
  1097. else
  1098. {
  1099. [bufferingQueue enqueue:entry];
  1100. }
  1101. pthread_mutex_unlock(&queueBuffersMutex);
  1102. }
  1103. -(void) audioQueueFinishedPlaying:(QueueEntry*)entry
  1104. {
  1105. pthread_mutex_lock(&playerMutex);
  1106. {
  1107. pthread_mutex_lock(&queueBuffersMutex);
  1108. {
  1109. QueueEntry* next = [bufferingQueue dequeue];
  1110. [self processDidFinishPlaying:entry withNext:next];
  1111. }
  1112. pthread_mutex_unlock(&queueBuffersMutex);
  1113. }
  1114. pthread_mutex_unlock(&playerMutex);
  1115. }
  1116. -(void) processDidFinishPlaying:(QueueEntry*)entry withNext:(QueueEntry*)next
  1117. {
  1118. if (entry != currentlyPlayingEntry)
  1119. {
  1120. return;
  1121. }
  1122. NSObject* queueItemId = entry.queueItemId;
  1123. double progress = [entry progress];
  1124. double duration = [entry duration];
  1125. BOOL nextIsDifferent = currentlyPlayingEntry != next;
  1126. if (next)
  1127. {
  1128. if (nextIsDifferent)
  1129. {
  1130. next->seekTime = 0;
  1131. seekToTimeWasRequested = NO;
  1132. }
  1133. OSSpinLockLock(&currentlyPlayingLock);
  1134. currentlyPlayingEntry = next;
  1135. currentlyPlayingEntry->bytesPlayed = 0;
  1136. NSObject* playingQueueItemId = playingQueueItemId = currentlyPlayingEntry.queueItemId;
  1137. OSSpinLockUnlock(&currentlyPlayingLock);
  1138. if (nextIsDifferent && entry)
  1139. {
  1140. dispatch_async(dispatch_get_main_queue(), ^
  1141. {
  1142. [self.delegate audioPlayer:self didFinishPlayingQueueItemId:queueItemId withReason:stopReason andProgress:progress andDuration:duration];
  1143. });
  1144. }
  1145. if (nextIsDifferent)
  1146. {
  1147. dispatch_async(dispatch_get_main_queue(), ^
  1148. {
  1149. [self.delegate audioPlayer:self didStartPlayingQueueItemId:playingQueueItemId];
  1150. });
  1151. }
  1152. }
  1153. else
  1154. {
  1155. OSSpinLockLock(&currentlyPlayingLock);
  1156. currentlyPlayingEntry = nil;
  1157. OSSpinLockUnlock(&currentlyPlayingLock);
  1158. if (currentlyReadingEntry == nil)
  1159. {
  1160. if (upcomingQueue.count == 0)
  1161. {
  1162. stopReason = AudioPlayerStopReasonNoStop;
  1163. self.internalState = AudioPlayerInternalStateStopping;
  1164. }
  1165. }
  1166. if (nextIsDifferent && entry)
  1167. {
  1168. dispatch_async(dispatch_get_main_queue(), ^
  1169. {
  1170. [self.delegate audioPlayer:self didFinishPlayingQueueItemId:queueItemId withReason:stopReason andProgress:progress andDuration:duration];
  1171. });
  1172. }
  1173. }
  1174. }
  1175. -(BOOL) processRunloop
  1176. {
  1177. pthread_mutex_lock(&playerMutex);
  1178. {
  1179. if (self.internalState == AudioPlayerInternalStatePaused)
  1180. {
  1181. pthread_mutex_unlock(&playerMutex);
  1182. return YES;
  1183. }
  1184. else if (newFileToPlay)
  1185. {
  1186. QueueEntry* entry = [upcomingQueue dequeue];
  1187. self.internalState = AudioPlayerInternalStateWaitingForData;
  1188. [self setCurrentlyReadingEntry:entry andStartPlaying:YES];
  1189. newFileToPlay = NO;
  1190. }
  1191. else if (seekToTimeWasRequested && currentlyPlayingEntry && currentlyPlayingEntry != currentlyReadingEntry)
  1192. {
  1193. currentlyPlayingEntry.bufferIndex = -1;
  1194. [self setCurrentlyReadingEntry:currentlyPlayingEntry andStartPlaying:YES];
  1195. currentlyReadingEntry->parsedHeader = NO;
  1196. [currentlyReadingEntry.dataSource seekToOffset:0];
  1197. }
  1198. else if (self.internalState == AudioPlayerInternalStateStopped && stopReason == AudioPlayerStopReasonUserAction)
  1199. {
  1200. [self stopAudioQueueWithReason:@"from processRunLoop/1"];
  1201. currentlyReadingEntry.dataSource.delegate = nil;
  1202. [currentlyReadingEntry.dataSource unregisterForEvents];
  1203. [currentlyReadingEntry.dataSource close];
  1204. if (currentlyPlayingEntry)
  1205. {
  1206. [self processDidFinishPlaying:currentlyPlayingEntry withNext:nil];
  1207. }
  1208. pthread_mutex_lock(&queueBuffersMutex);
  1209. if ([bufferingQueue peek] == currentlyPlayingEntry)
  1210. {
  1211. [bufferingQueue dequeue];
  1212. }
  1213. OSSpinLockLock(&currentlyPlayingLock);
  1214. currentlyPlayingEntry = nil;
  1215. OSSpinLockUnlock(&currentlyPlayingLock);
  1216. currentlyReadingEntry = nil;
  1217. seekToTimeWasRequested = NO;
  1218. pthread_mutex_unlock(&queueBuffersMutex);
  1219. }
  1220. else if (self.internalState == AudioPlayerInternalStateStopped && stopReason == AudioPlayerStopReasonUserActionFlushStop)
  1221. {
  1222. currentlyReadingEntry.dataSource.delegate = nil;
  1223. [currentlyReadingEntry.dataSource unregisterForEvents];
  1224. [currentlyReadingEntry.dataSource close];
  1225. if (currentlyPlayingEntry)
  1226. {
  1227. [self processDidFinishPlaying:currentlyPlayingEntry withNext:nil];
  1228. }
  1229. pthread_mutex_lock(&queueBuffersMutex);
  1230. if ([bufferingQueue peek] == currentlyPlayingEntry)
  1231. {
  1232. [bufferingQueue dequeue];
  1233. }
  1234. OSSpinLockLock(&currentlyPlayingLock);
  1235. currentlyPlayingEntry = nil;
  1236. OSSpinLockUnlock(&currentlyPlayingLock);
  1237. currentlyReadingEntry = nil;
  1238. pthread_mutex_unlock(&queueBuffersMutex);
  1239. [self resetAudioQueueWithReason:@"from processRunLoop"];
  1240. }
  1241. else if (currentlyReadingEntry == nil)
  1242. {
  1243. BOOL nextIsIncompatible = NO;
  1244. QueueEntry* next = [bufferingQueue peek];
  1245. if (next == nil)
  1246. {
  1247. next = [upcomingQueue peek];
  1248. if (next)
  1249. {
  1250. if (next->audioStreamBasicDescription.mSampleRate != 0)
  1251. {
  1252. if (memcmp(&next->audioStreamBasicDescription, &currentAudioStreamBasicDescription, sizeof(currentAudioStreamBasicDescription)) != 0)
  1253. {
  1254. nextIsIncompatible = YES;
  1255. }
  1256. }
  1257. }
  1258. }
  1259. if (nextIsIncompatible && currentlyPlayingEntry != nil)
  1260. {
  1261. // Holding off cause next is incompatible
  1262. }
  1263. else
  1264. {
  1265. if (upcomingQueue.count > 0)
  1266. {
  1267. QueueEntry* entry = [upcomingQueue dequeue];
  1268. BOOL startPlaying = currentlyPlayingEntry == nil;
  1269. BOOL wasCurrentlyPlayingNothing = currentlyPlayingEntry == nil;
  1270. [self setCurrentlyReadingEntry:entry andStartPlaying:startPlaying];
  1271. if (wasCurrentlyPlayingNothing)
  1272. {
  1273. [self setInternalState:AudioPlayerInternalStateWaitingForData];
  1274. }
  1275. }
  1276. else if (currentlyPlayingEntry == nil)
  1277. {
  1278. if (self.internalState != AudioPlayerInternalStateStopped)
  1279. {
  1280. [self stopAudioQueueWithReason:@"from processRunLoop/2"];
  1281. stopReason = AudioPlayerStopReasonEof;
  1282. }
  1283. }
  1284. }
  1285. }
  1286. if (disposeWasRequested)
  1287. {
  1288. pthread_mutex_unlock(&playerMutex);
  1289. return NO;
  1290. }
  1291. }
  1292. pthread_mutex_unlock(&playerMutex);
  1293. if (currentlyReadingEntry && currentlyReadingEntry->parsedHeader && currentlyReadingEntry != currentlyPlayingEntry)
  1294. {
  1295. if (currentAudioStreamBasicDescription.mSampleRate != 0)
  1296. {
  1297. if (memcmp(&currentAudioStreamBasicDescription, &currentlyReadingEntry->audioStreamBasicDescription, sizeof(currentAudioStreamBasicDescription)) != 0)
  1298. {
  1299. [currentlyReadingEntry.dataSource unregisterForEvents];
  1300. if ([bufferingQueue peek] == currentlyReadingEntry)
  1301. {
  1302. [bufferingQueue dequeue];
  1303. }
  1304. QueueEntry* newEntry = [[QueueEntry alloc] initWithDataSource:currentlyReadingEntry.dataSource andQueueItemId:currentlyReadingEntry.queueItemId];
  1305. newEntry->audioStreamBasicDescription = currentlyReadingEntry->audioStreamBasicDescription;
  1306. [upcomingQueue skipQueue:newEntry];
  1307. OSSpinLockLock(&currentlyPlayingLock);
  1308. currentlyReadingEntry = nil;
  1309. OSSpinLockUnlock(&currentlyPlayingLock);
  1310. }
  1311. }
  1312. }
  1313. if (currentlyPlayingEntry && currentlyPlayingEntry->parsedHeader)
  1314. {
  1315. if (seekToTimeWasRequested && currentlyReadingEntry == currentlyPlayingEntry)
  1316. {
  1317. [self processSeekToTime];
  1318. seekToTimeWasRequested = NO;
  1319. }
  1320. }
  1321. return YES;
  1322. }
  1323. -(void) startInternal
  1324. {
  1325. @autoreleasepool
  1326. {
  1327. playbackThreadRunLoop = [NSRunLoop currentRunLoop];
  1328. NSThread.currentThread.threadPriority = 1;
  1329. bytesFilled = 0;
  1330. packetsFilled = 0;
  1331. [playbackThreadRunLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
  1332. while (true)
  1333. {
  1334. if (![self processRunloop])
  1335. {
  1336. break;
  1337. }
  1338. NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:10];
  1339. [playbackThreadRunLoop runMode:NSDefaultRunLoopMode beforeDate:date];
  1340. }
  1341. disposeWasRequested = NO;
  1342. seekToTimeWasRequested = NO;
  1343. currentlyReadingEntry.dataSource.delegate = nil;
  1344. currentlyPlayingEntry.dataSource.delegate = nil;
  1345. currentlyReadingEntry = nil;
  1346. pthread_mutex_lock(&playerMutex);
  1347. OSSpinLockLock(&currentlyPlayingLock);
  1348. currentlyPlayingEntry = nil;
  1349. OSSpinLockUnlock(&currentlyPlayingLock);
  1350. pthread_mutex_unlock(&playerMutex);
  1351. self.internalState = AudioPlayerInternalStateDisposed;
  1352. [threadFinishedCondLock lock];
  1353. [threadFinishedCondLock unlockWithCondition:1];
  1354. }
  1355. }
  1356. -(void) processSeekToTime
  1357. {
  1358. OSStatus error;
  1359. OSSpinLockLock(&currentlyPlayingLock);
  1360. QueueEntry* currentEntry = currentlyReadingEntry;
  1361. OSSpinLockUnlock(&currentlyPlayingLock);
  1362. NSAssert(currentEntry == currentlyPlayingEntry, @"playing and reading must be the same");
  1363. if (!currentEntry || ([currentEntry calculatedBitRate] == 0.0 || currentlyPlayingEntry.dataSource.length <= 0))
  1364. {
  1365. return;
  1366. }
  1367. long long seekByteOffset = currentEntry->audioDataOffset + (requestedSeekTime / self.duration) * (currentlyReadingEntry.audioDataLengthInBytes);
  1368. if (seekByteOffset > currentEntry.dataSource.length - (2 * currentEntry->packetBufferSize))
  1369. {
  1370. seekByteOffset = currentEntry.dataSource.length - 2 * currentEntry->packetBufferSize;
  1371. }
  1372. currentEntry->seekTime = requestedSeekTime;
  1373. currentEntry->lastProgress = requestedSeekTime;
  1374. double calculatedBitRate = [currentEntry calculatedBitRate];
  1375. if (currentEntry->packetDuration > 0 && calculatedBitRate > 0)
  1376. {
  1377. UInt32 ioFlags = 0;
  1378. SInt64 packetAlignedByteOffset;
  1379. SInt64 seekPacket = floor(requestedSeekTime / currentEntry->packetDuration);
  1380. error = AudioFileStreamSeek(audioFileStream, seekPacket, &packetAlignedByteOffset, &ioFlags);
  1381. if (!error && !(ioFlags & kAudioFileStreamSeekFlag_OffsetIsEstimated))
  1382. {
  1383. double delta = ((seekByteOffset - (SInt64)currentEntry->audioDataOffset) - packetAlignedByteOffset) / calculatedBitRate * 8;
  1384. currentEntry->seekTime -= delta;
  1385. seekByteOffset = packetAlignedByteOffset + currentEntry->audioDataOffset;
  1386. }
  1387. }
  1388. [currentEntry updateAudioDataSource];
  1389. [currentEntry.dataSource seekToOffset:seekByteOffset];
  1390. if (seekByteOffset > 0)
  1391. {
  1392. discontinuous = YES;
  1393. }
  1394. if (audioQueue)
  1395. {
  1396. [self resetAudioQueueWithReason:@"from seekToTime"];
  1397. }
  1398. if (currentEntry)
  1399. {
  1400. currentEntry->bytesPlayed = 0;
  1401. }
  1402. }
  1403. -(BOOL) startAudioQueue
  1404. {
  1405. OSStatus error;
  1406. self.internalState = AudioPlayerInternalStateWaitingForQueueToStart;
  1407. AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1);
  1408. error = AudioQueueStart(audioQueue, NULL);
  1409. if (error)
  1410. {
  1411. if (backgroundTaskId == UIBackgroundTaskInvalid)
  1412. {
  1413. [self startSystemBackgroundTask];
  1414. }
  1415. [self stopAudioQueueWithReason:@"from startAudioQueue"];
  1416. [self createAudioQueue];
  1417. self.internalState = AudioPlayerInternalStateWaitingForQueueToStart;
  1418. AudioQueueStart(audioQueue, NULL);
  1419. }
  1420. [self stopSystemBackgroundTask];
  1421. return YES;
  1422. }
  1423. -(void) stopAudioQueueWithReason:(NSString*)reason
  1424. {
  1425. OSStatus error;
  1426. if (!audioQueue)
  1427. {
  1428. [self logInfo:[@"stopAudioQueue/1 " stringByAppendingString:reason]];
  1429. self.internalState = AudioPlayerInternalStateStopped;
  1430. return;
  1431. }
  1432. else
  1433. {
  1434. [self logInfo:[@"stopAudioQueue/2 " stringByAppendingString:reason]];
  1435. audioQueueFlushing = YES;
  1436. error = AudioQueueStop(audioQueue, true);
  1437. error = error | AudioQueueDispose(audioQueue, true);
  1438. audioQueue = nil;
  1439. }
  1440. if (error)
  1441. {
  1442. [self didEncounterError:AudioPlayerErrorQueueStopFailed];
  1443. }
  1444. pthread_mutex_lock(&queueBuffersMutex);
  1445. if (numberOfBuffersUsed != 0)
  1446. {
  1447. numberOfBuffersUsed = 0;
  1448. memset(&bufferUsed[0], 0, sizeof(bool) * audioQueueBufferCount);
  1449. }
  1450. pthread_cond_signal(&queueBufferReadyCondition);
  1451. pthread_mutex_unlock(&queueBuffersMutex);
  1452. bytesFilled = 0;
  1453. fillBufferIndex = 0;
  1454. packetsFilled = 0;
  1455. audioPacketsReadCount = 0;
  1456. audioPacketsPlayedCount = 0;
  1457. audioQueueFlushing = NO;
  1458. self.internalState = AudioPlayerInternalStateStopped;
  1459. }
  1460. -(void) resetAudioQueueWithReason:(NSString*)reason
  1461. {
  1462. OSStatus error;
  1463. [self logInfo:[@"resetAudioQueue/1 " stringByAppendingString:reason]];
  1464. pthread_mutex_lock(&playerMutex);
  1465. {
  1466. audioQueueFlushing = YES;
  1467. if (audioQueue)
  1468. {
  1469. error = AudioQueueReset(audioQueue);
  1470. if (error)
  1471. {
  1472. dispatch_async(dispatch_get_main_queue(), ^
  1473. {
  1474. [self didEncounterError:AudioPlayerErrorQueueStopFailed];;
  1475. });
  1476. }
  1477. }
  1478. }
  1479. pthread_mutex_unlock(&playerMutex);
  1480. pthread_mutex_lock(&queueBuffersMutex);
  1481. if (numberOfBuffersUsed != 0)
  1482. {
  1483. numberOfBuffersUsed = 0;
  1484. memset(&bufferUsed[0], 0, sizeof(bool) * audioQueueBufferCount);
  1485. }
  1486. pthread_cond_signal(&queueBufferReadyCondition);
  1487. bytesFilled = 0;
  1488. fillBufferIndex = 0;
  1489. packetsFilled = 0;
  1490. if (currentlyPlayingEntry)
  1491. {
  1492. currentlyPlayingEntry->lastProgress = 0;
  1493. }
  1494. audioPacketsReadCount = 0;
  1495. audioPacketsPlayedCount = 0;
  1496. audioQueueFlushing = NO;
  1497. pthread_mutex_unlock(&queueBuffersMutex);
  1498. }
  1499. -(void) dataSourceDataAvailable:(DataSource*)dataSourceIn
  1500. {
  1501. OSStatus error;
  1502. if (currentlyReadingEntry.dataSource != dataSourceIn)
  1503. {
  1504. return;
  1505. }
  1506. if (!currentlyReadingEntry.dataSource.hasBytesAvailable)
  1507. {
  1508. return;
  1509. }
  1510. int read = [currentlyReadingEntry.dataSource readIntoBuffer:readBuffer withSize:readBufferSize];
  1511. if (read == 0)
  1512. {
  1513. return;
  1514. }
  1515. if (audioFileStream == 0)
  1516. {
  1517. error = AudioFileStreamOpen((__bridge void*)self, AudioFileStreamPropertyListenerProc, AudioFileStreamPacketsProc, dataSourceIn.audioFileTypeHint, &audioFileStream);
  1518. if (error)
  1519. {
  1520. return;
  1521. }
  1522. }
  1523. if (read < 0)
  1524. {
  1525. // iOS will shutdown network connections if the app is backgrounded (i.e. device is locked when player is paused)
  1526. // We try to reopen -- should probably add a back-off protocol in the future
  1527. long long position = currentlyReadingEntry.dataSource.position;
  1528. [currentlyReadingEntry.dataSource seekToOffset:position];
  1529. return;
  1530. }
  1531. int flags = 0;
  1532. if (discontinuous)
  1533. {
  1534. flags = kAudioFileStreamParseFlag_Discontinuity;
  1535. }
  1536. error = AudioFileStreamParseBytes(audioFileStream, read, readBuffer, flags);
  1537. if (error)
  1538. {
  1539. if (dataSourceIn == currentlyPlayingEntry.dataSource)
  1540. {
  1541. [self didEncounterError:AudioPlayerErrorStreamParseBytesFailed];
  1542. }
  1543. return;
  1544. }
  1545. }
  1546. -(void) dataSourceErrorOccured:(DataSource*)dataSourceIn
  1547. {
  1548. if (currentlyReadingEntry.dataSource != dataSourceIn)
  1549. {
  1550. return;
  1551. }
  1552. [self didEncounterError:AudioPlayerErrorDataNotFound];
  1553. }
  1554. -(void) dataSourceEof:(DataSource*)dataSourceIn
  1555. {
  1556. if (currentlyReadingEntry.dataSource != dataSourceIn)
  1557. {
  1558. return;
  1559. }
  1560. if (bytesFilled)
  1561. {
  1562. [self enqueueBuffer];
  1563. }
  1564. [self logInfo:[NSString stringWithFormat:@"dataSourceEof for dataSource: %@", dataSourceIn]];
  1565. NSObject* queueItemId = currentlyReadingEntry.queueItemId;
  1566. dispatch_async(dispatch_get_main_queue(), ^
  1567. {
  1568. [self.delegate audioPlayer:self didFinishBufferingSourceWithQueueItemId:queueItemId];
  1569. });
  1570. pthread_mutex_lock(&playerMutex);
  1571. {
  1572. if (audioQueue)
  1573. {
  1574. currentlyReadingEntry.bufferIndex = audioPacketsReadCount;
  1575. currentlyReadingEntry = nil;
  1576. if (self.internalState == AudioPlayerInternalStatePlaying)
  1577. {
  1578. if (audioQueue)
  1579. {
  1580. if (![self audioQueueIsRunning])
  1581. {
  1582. [self logInfo:@"startAudioQueue from dataSourceEof"];
  1583. [self startAudioQueue];
  1584. }
  1585. }
  1586. }
  1587. }
  1588. else
  1589. {
  1590. stopReason = AudioPlayerStopReasonEof;
  1591. self.internalState = AudioPlayerInternalStateStopped;
  1592. }
  1593. }
  1594. pthread_mutex_unlock(&playerMutex);
  1595. }
  1596. -(void) pause
  1597. {
  1598. pthread_mutex_lock(&playerMutex);
  1599. {
  1600. OSStatus error;
  1601. if (self.internalState != AudioPlayerInternalStatePaused)
  1602. {
  1603. self.internalState = AudioPlayerInternalStatePaused;
  1604. if (audioQueue)
  1605. {
  1606. error = AudioQueuePause(audioQueue);
  1607. if (error)
  1608. {
  1609. [self didEncounterError:AudioPlayerErrorQueuePauseFailed];
  1610. pthread_mutex_unlock(&playerMutex);
  1611. return;
  1612. }
  1613. }
  1614. [self wakeupPlaybackThread];
  1615. }
  1616. }
  1617. pthread_mutex_unlock(&playerMutex);
  1618. }
  1619. -(void) resume
  1620. {
  1621. pthread_mutex_lock(&playerMutex);
  1622. {
  1623. OSStatus error;
  1624. if (self.internalState == AudioPlayerInternalStatePaused)
  1625. {
  1626. self.internalState = AudioPlayerInternalStatePlaying;
  1627. if (seekToTimeWasRequested)
  1628. {
  1629. [self resetAudioQueueWithReason:@"from resume"];
  1630. }
  1631. error = AudioQueueStart(audioQueue, 0);
  1632. if (error)
  1633. {
  1634. [self didEncounterError:AudioPlayerErrorQueueStartFailed];
  1635. pthread_mutex_unlock(&playerMutex);
  1636. return;
  1637. }
  1638. [self wakeupPlaybackThread];
  1639. }
  1640. }
  1641. pthread_mutex_unlock(&playerMutex);
  1642. }
  1643. -(void) stop
  1644. {
  1645. pthread_mutex_lock(&playerMutex);
  1646. {
  1647. if (self.internalState == AudioPlayerInternalStateStopped)
  1648. {
  1649. pthread_mutex_unlock(&playerMutex);
  1650. return;
  1651. }
  1652. stopReason = AudioPlayerStopReasonUserAction;
  1653. self.internalState = AudioPlayerInternalStateStopped;
  1654. [self wakeupPlaybackThread];
  1655. }
  1656. pthread_mutex_unlock(&playerMutex);
  1657. }
  1658. -(void) flushStop
  1659. {
  1660. pthread_mutex_lock(&playerMutex);
  1661. {
  1662. if (self.internalState == AudioPlayerInternalStateStopped)
  1663. {
  1664. pthread_mutex_unlock(&playerMutex);
  1665. return;
  1666. }
  1667. stopReason = AudioPlayerStopReasonUserActionFlushStop;
  1668. self.internalState = AudioPlayerInternalStateStopped;
  1669. [self wakeupPlaybackThread];
  1670. }
  1671. pthread_mutex_unlock(&playerMutex);
  1672. }
  1673. -(void) stopThread
  1674. {
  1675. BOOL wait = NO;
  1676. pthread_mutex_lock(&playerMutex);
  1677. {
  1678. disposeWasRequested = YES;
  1679. if (playbackThread && playbackThreadRunLoop)
  1680. {
  1681. wait = YES;
  1682. CFRunLoopStop([playbackThreadRunLoop getCFRunLoop]);
  1683. }
  1684. }
  1685. pthread_mutex_unlock(&playerMutex);
  1686. if (wait)
  1687. {
  1688. [threadFinishedCondLock lockWhenCondition:1];
  1689. [threadFinishedCondLock unlockWithCondition:0];
  1690. }
  1691. }
  1692. -(void) mute
  1693. {
  1694. AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 0);
  1695. }
  1696. -(void) unmute
  1697. {
  1698. AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1);
  1699. }
  1700. -(void) dispose
  1701. {
  1702. [self stop];
  1703. [self stopThread];
  1704. }
  1705. -(NSObject*) currentlyPlayingQueueItemId
  1706. {
  1707. OSSpinLockLock(&currentlyPlayingLock);
  1708. QueueEntry* entry = currentlyPlayingEntry;
  1709. if (entry == nil)
  1710. {
  1711. OSSpinLockUnlock(&currentlyPlayingLock);
  1712. return nil;
  1713. }
  1714. NSObject* retval = entry.queueItemId;
  1715. OSSpinLockUnlock(&currentlyPlayingLock);
  1716. return retval;
  1717. }
  1718. #pragma mark Metering
  1719. -(void) setMeteringEnabled:(BOOL)value
  1720. {
  1721. if (!audioQueue)
  1722. {
  1723. meteringEnabled = value;
  1724. return;
  1725. }
  1726. UInt32 on = value ? 1 : 0;
  1727. OSStatus error = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_EnableLevelMetering, &on, sizeof(on));
  1728. if (error)
  1729. {
  1730. meteringEnabled = NO;
  1731. }
  1732. else
  1733. {
  1734. meteringEnabled = YES;
  1735. }
  1736. }
  1737. -(BOOL) meteringEnabled
  1738. {
  1739. return meteringEnabled;
  1740. }
  1741. -(void) updateMeters
  1742. {
  1743. if (!meteringEnabled)
  1744. {
  1745. NSAssert(NO, @"Metering is not enabled. Make sure to set meteringEnabled = YES.");
  1746. }
  1747. NSInteger channels = currentAudioStreamBasicDescription.mChannelsPerFrame;
  1748. if (numberOfChannels != channels)
  1749. {
  1750. numberOfChannels = channels;
  1751. if (levelMeterState) free(levelMeterState);
  1752. {
  1753. levelMeterState = malloc(sizeof(AudioQueueLevelMeterState) * numberOfChannels);
  1754. }
  1755. }
  1756. UInt32 sizeofMeters = sizeof(AudioQueueLevelMeterState) * numberOfChannels;
  1757. AudioQueueGetProperty(audioQueue, kAudioQueueProperty_CurrentLevelMeterDB, levelMeterState, &sizeofMeters);
  1758. }
  1759. -(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber
  1760. {
  1761. if (!meteringEnabled || !levelMeterState || (channelNumber > numberOfChannels))
  1762. {
  1763. return 0;
  1764. }
  1765. return levelMeterState[channelNumber].mPeakPower;
  1766. }
  1767. -(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber
  1768. {
  1769. if (!meteringEnabled || !levelMeterState || (channelNumber > numberOfChannels))
  1770. {
  1771. return 0;
  1772. }
  1773. return levelMeterState[channelNumber].mAveragePower;
  1774. }
  1775. @end