2006-01-20 15:34:02 +00:00
|
|
|
//
|
2006-04-02 15:44:08 +00:00
|
|
|
// OutputNode.m
|
2006-01-20 15:34:02 +00:00
|
|
|
// Cog
|
|
|
|
//
|
2006-09-04 18:46:18 +00:00
|
|
|
// Created by Vincent Spader on 8/2/05.
|
|
|
|
// Copyright 2005 Vincent Spader. All rights reserved.
|
2006-01-20 15:34:02 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
#import "OutputNode.h"
|
2007-02-24 20:36:27 +00:00
|
|
|
#import "AudioPlayer.h"
|
|
|
|
#import "BufferChain.h"
|
2022-06-24 06:17:31 +00:00
|
|
|
#import "OutputAVFoundation.h"
|
2006-01-20 15:34:02 +00:00
|
|
|
|
2013-10-11 12:03:55 +00:00
|
|
|
#import "Logging.h"
|
|
|
|
|
2006-01-20 15:34:02 +00:00
|
|
|
@implementation OutputNode
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)setup {
|
2022-01-13 07:17:07 +00:00
|
|
|
amountPlayed = 0.0;
|
2022-06-19 06:00:08 +00:00
|
|
|
amountPlayedInterval = 0.0;
|
2022-02-07 05:49:27 +00:00
|
|
|
|
|
|
|
paused = YES;
|
|
|
|
started = NO;
|
2022-06-19 06:00:08 +00:00
|
|
|
intervalReported = NO;
|
2006-04-02 15:44:08 +00:00
|
|
|
|
2022-06-24 06:17:31 +00:00
|
|
|
output = [[OutputAVFoundation alloc] initWithController:self];
|
2022-02-07 05:49:27 +00:00
|
|
|
|
2006-01-20 15:34:02 +00:00
|
|
|
[output setup];
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)seek:(double)time {
|
|
|
|
// [output pause];
|
|
|
|
[self resetBuffer];
|
2007-05-26 22:13:11 +00:00
|
|
|
|
2022-01-13 07:17:07 +00:00
|
|
|
amountPlayed = time;
|
2006-04-02 20:03:12 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)process {
|
|
|
|
paused = NO;
|
|
|
|
[output start];
|
2006-01-20 15:34:02 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)pause {
|
|
|
|
paused = YES;
|
2006-01-29 14:57:48 +00:00
|
|
|
[output pause];
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)resume {
|
|
|
|
paused = NO;
|
2006-01-29 14:57:48 +00:00
|
|
|
[output resume];
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)incrementAmountPlayed:(double)seconds {
|
|
|
|
amountPlayed += seconds;
|
2022-06-19 06:00:08 +00:00
|
|
|
amountPlayedInterval += seconds;
|
|
|
|
if(!intervalReported && amountPlayedInterval >= 60.0) {
|
|
|
|
intervalReported = YES;
|
|
|
|
[controller reportPlayCount];
|
|
|
|
}
|
2022-01-15 06:46:41 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)resetAmountPlayed {
|
|
|
|
amountPlayed = 0;
|
2022-01-15 06:46:41 +00:00
|
|
|
}
|
|
|
|
|
2022-06-19 06:00:08 +00:00
|
|
|
- (void)resetAmountPlayedInterval {
|
|
|
|
amountPlayedInterval = 0;
|
|
|
|
intervalReported = NO;
|
|
|
|
}
|
|
|
|
|
2022-06-24 06:17:31 +00:00
|
|
|
- (BOOL)selectNextBuffer {
|
|
|
|
return [controller selectNextBuffer];
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)endOfInputPlayed {
|
2022-06-19 06:00:08 +00:00
|
|
|
if(!intervalReported) {
|
|
|
|
intervalReported = YES;
|
|
|
|
[controller reportPlayCount];
|
|
|
|
}
|
2022-02-07 05:49:27 +00:00
|
|
|
[controller endOfInputPlayed];
|
2022-06-19 06:00:08 +00:00
|
|
|
[self resetAmountPlayedInterval];
|
2022-01-15 06:46:41 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (BOOL)chainQueueHasTracks {
|
|
|
|
return [controller chainQueueHasTracks];
|
2022-01-15 06:46:41 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (double)secondsBuffered {
|
|
|
|
return [buffer listDuration];
|
2022-01-15 06:46:41 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (AudioChunk *)readChunk:(size_t)amount {
|
|
|
|
@autoreleasepool {
|
|
|
|
[self setPreviousNode:[[controller bufferChain] finalNode]];
|
|
|
|
|
|
|
|
AudioChunk *ret = [super readChunk:amount];
|
|
|
|
|
|
|
|
/* if (n == 0) {
|
|
|
|
DLog(@"Output Buffer dry!");
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
return ret;
|
2007-05-26 12:44:01 +00:00
|
|
|
}
|
2006-04-02 15:44:08 +00:00
|
|
|
}
|
2006-01-20 15:34:02 +00:00
|
|
|
|
2022-07-15 10:34:10 +00:00
|
|
|
- (BOOL)peekFormat:(nonnull AudioStreamBasicDescription *)format channelConfig:(nonnull uint32_t *)config {
|
|
|
|
@autoreleasepool {
|
|
|
|
[self setPreviousNode:[[controller bufferChain] finalNode]];
|
|
|
|
|
|
|
|
return [super peekFormat:format channelConfig:config];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (double)amountPlayed {
|
|
|
|
return amountPlayed;
|
2006-01-20 15:34:02 +00:00
|
|
|
}
|
|
|
|
|
2022-06-19 06:00:08 +00:00
|
|
|
- (double)amountPlayedInterval {
|
|
|
|
return amountPlayedInterval;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (AudioStreamBasicDescription)format {
|
2006-01-20 15:34:02 +00:00
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
2022-02-07 08:56:05 +00:00
|
|
|
- (uint32_t)config {
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig {
|
2006-01-20 15:34:02 +00:00
|
|
|
format = *f;
|
2022-02-07 08:56:05 +00:00
|
|
|
config = channelConfig;
|
2022-02-07 05:49:27 +00:00
|
|
|
// Calculate a ratio and add to double(seconds) instead, as format may change
|
|
|
|
// double oldSampleRatio = sampleRatio;
|
|
|
|
BufferChain *bufferChain = [controller bufferChain];
|
|
|
|
if(bufferChain) {
|
|
|
|
ConverterNode *converter = [bufferChain converter];
|
|
|
|
if(converter) {
|
|
|
|
// This clears the resampler buffer, but not the input buffer
|
|
|
|
// We also have to jump the play position ahead accounting for
|
|
|
|
// the data we are flushing
|
2022-02-08 06:02:17 +00:00
|
|
|
amountPlayed += [[converter buffer] listDuration];
|
|
|
|
|
|
|
|
AudioStreamBasicDescription inf = [bufferChain inputFormat];
|
|
|
|
uint32_t config = [bufferChain inputConfig];
|
|
|
|
|
|
|
|
format.mChannelsPerFrame = inf.mChannelsPerFrame;
|
|
|
|
format.mBytesPerFrame = ((inf.mBitsPerChannel + 7) / 8) * format.mChannelsPerFrame;
|
|
|
|
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
|
|
|
|
channelConfig = config;
|
|
|
|
|
2022-02-07 08:56:05 +00:00
|
|
|
[converter inputFormatDidChange:[bufferChain inputFormat] inputConfig:[bufferChain inputConfig]];
|
2022-02-07 05:49:27 +00:00
|
|
|
}
|
|
|
|
}
|
2006-01-20 15:34:02 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)close {
|
2006-04-02 15:44:08 +00:00
|
|
|
[output stop];
|
2022-02-07 05:49:27 +00:00
|
|
|
output = nil;
|
2006-04-02 15:44:08 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)setVolume:(double)v {
|
2006-01-20 15:34:02 +00:00
|
|
|
[output setVolume:v];
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)setShouldContinue:(BOOL)s {
|
2006-01-20 15:34:02 +00:00
|
|
|
[super setShouldContinue:s];
|
2022-02-07 05:49:27 +00:00
|
|
|
|
|
|
|
// if (s == NO)
|
|
|
|
// [output stop];
|
2006-01-20 15:34:02 +00:00
|
|
|
}
|
2013-10-21 05:04:09 +00:00
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (BOOL)isPaused {
|
|
|
|
return paused;
|
2013-10-21 05:04:09 +00:00
|
|
|
}
|
2022-01-16 15:32:47 +00:00
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)beginEqualizer:(AudioUnit)eq {
|
|
|
|
[controller beginEqualizer:eq];
|
2022-01-16 15:32:47 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)refreshEqualizer:(AudioUnit)eq {
|
|
|
|
[controller refreshEqualizer:eq];
|
2022-01-18 04:43:08 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)endEqualizer:(AudioUnit)eq {
|
|
|
|
[controller endEqualizer:eq];
|
2022-01-16 15:32:47 +00:00
|
|
|
}
|
2022-01-19 10:08:57 +00:00
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)sustainHDCD {
|
|
|
|
[output sustainHDCD];
|
2022-01-19 10:08:57 +00:00
|
|
|
}
|
2022-01-22 22:37:37 +00:00
|
|
|
|
2022-02-08 06:44:56 +00:00
|
|
|
- (void)restartPlaybackAtCurrentPosition {
|
|
|
|
[controller restartPlaybackAtCurrentPosition];
|
|
|
|
}
|
|
|
|
|
2022-06-25 13:42:56 +00:00
|
|
|
- (double)latency {
|
|
|
|
return [output latency];
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:34:02 +00:00
|
|
|
@end
|