Add play count data collection, including first seen times for every file first added to the playlist. Data is indexed by album, artist, and title, or by filename, whichever matches first. Add interfaces to AppleScript automation definition as well. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
187 lines
3.6 KiB
Objective-C
187 lines
3.6 KiB
Objective-C
//
|
|
// OutputNode.m
|
|
// Cog
|
|
//
|
|
// Created by Vincent Spader on 8/2/05.
|
|
// Copyright 2005 Vincent Spader. All rights reserved.
|
|
//
|
|
|
|
#import "OutputNode.h"
|
|
#import "AudioPlayer.h"
|
|
#import "BufferChain.h"
|
|
#import "OutputCoreAudio.h"
|
|
|
|
#import "Logging.h"
|
|
|
|
@implementation OutputNode
|
|
|
|
- (void)setup {
|
|
amountPlayed = 0.0;
|
|
amountPlayedInterval = 0.0;
|
|
|
|
paused = YES;
|
|
started = NO;
|
|
intervalReported = NO;
|
|
|
|
output = [[OutputCoreAudio alloc] initWithController:self];
|
|
|
|
[output setup];
|
|
}
|
|
|
|
- (void)seek:(double)time {
|
|
// [output pause];
|
|
[self resetBuffer];
|
|
|
|
amountPlayed = time;
|
|
}
|
|
|
|
- (void)process {
|
|
paused = NO;
|
|
[output start];
|
|
}
|
|
|
|
- (void)pause {
|
|
paused = YES;
|
|
[output pause];
|
|
}
|
|
|
|
- (void)resume {
|
|
paused = NO;
|
|
[output resume];
|
|
}
|
|
|
|
- (void)incrementAmountPlayed:(double)seconds {
|
|
amountPlayed += seconds;
|
|
amountPlayedInterval += seconds;
|
|
if(!intervalReported && amountPlayedInterval >= 60.0) {
|
|
intervalReported = YES;
|
|
[controller reportPlayCount];
|
|
}
|
|
}
|
|
|
|
- (void)resetAmountPlayed {
|
|
amountPlayed = 0;
|
|
}
|
|
|
|
- (void)resetAmountPlayedInterval {
|
|
amountPlayedInterval = 0;
|
|
intervalReported = NO;
|
|
}
|
|
|
|
- (void)endOfInputPlayed {
|
|
if(!intervalReported) {
|
|
intervalReported = YES;
|
|
[controller reportPlayCount];
|
|
}
|
|
[controller endOfInputPlayed];
|
|
[self resetAmountPlayedInterval];
|
|
}
|
|
|
|
- (BOOL)chainQueueHasTracks {
|
|
return [controller chainQueueHasTracks];
|
|
}
|
|
|
|
- (double)secondsBuffered {
|
|
return [buffer listDuration];
|
|
}
|
|
|
|
- (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;
|
|
}
|
|
}
|
|
|
|
- (double)amountPlayed {
|
|
return amountPlayed;
|
|
}
|
|
|
|
- (double)amountPlayedInterval {
|
|
return amountPlayedInterval;
|
|
}
|
|
|
|
- (AudioStreamBasicDescription)format {
|
|
return format;
|
|
}
|
|
|
|
- (uint32_t)config {
|
|
return config;
|
|
}
|
|
|
|
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig {
|
|
format = *f;
|
|
config = channelConfig;
|
|
// 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
|
|
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;
|
|
|
|
[converter setOutputFormat:format
|
|
outputConfig:channelConfig];
|
|
[converter inputFormatDidChange:[bufferChain inputFormat] inputConfig:[bufferChain inputConfig]];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)close {
|
|
[output stop];
|
|
output = nil;
|
|
}
|
|
|
|
- (void)setVolume:(double)v {
|
|
[output setVolume:v];
|
|
}
|
|
|
|
- (void)setShouldContinue:(BOOL)s {
|
|
[super setShouldContinue:s];
|
|
|
|
// if (s == NO)
|
|
// [output stop];
|
|
}
|
|
|
|
- (BOOL)isPaused {
|
|
return paused;
|
|
}
|
|
|
|
- (void)beginEqualizer:(AudioUnit)eq {
|
|
[controller beginEqualizer:eq];
|
|
}
|
|
|
|
- (void)refreshEqualizer:(AudioUnit)eq {
|
|
[controller refreshEqualizer:eq];
|
|
}
|
|
|
|
- (void)endEqualizer:(AudioUnit)eq {
|
|
[controller endEqualizer:eq];
|
|
}
|
|
|
|
- (void)sustainHDCD {
|
|
[output sustainHDCD];
|
|
}
|
|
|
|
- (void)restartPlaybackAtCurrentPosition {
|
|
[controller restartPlaybackAtCurrentPosition];
|
|
}
|
|
|
|
@end
|