Added new files

CQTexperiment
vspader 2005-09-07 22:33:16 +00:00
parent 91957a3d72
commit bb9f463b52
20 changed files with 530 additions and 9 deletions

View File

@ -11,6 +11,7 @@ The playlist index now starts at 1.
Seekbar now updates the time field as you drag it, Simon Savary <savary (at) oricom.ca>
French translation courtesy of Simon Savary <savary (at) oricom.ca>
Window is now brought to the front when opening a playlist.
Should work with 3rd party audio devices.
0.04
----

View File

@ -197,6 +197,8 @@
8E267D0C0837F7A6004ACBC5 /* UpdateController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = UpdateController.m; sourceTree = "<group>"; };
8E2871080836934A0013CE39 /* VirtualRingBuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = VirtualRingBuffer.h; sourceTree = "<group>"; };
8E2871090836934A0013CE39 /* VirtualRingBuffer.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = VirtualRingBuffer.m; sourceTree = "<group>"; };
8E2C5C2D08A67867008DA854 /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
8E2C5C2E08A67867008DA854 /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
8E45227A0832898A00F8BA7C /* Sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sound.h; sourceTree = "<group>"; };
8E45227B0832898A00F8BA7C /* Sound.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = Sound.m; sourceTree = "<group>"; };
8E47218508318D7A001F89FA /* DNDArrayController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DNDArrayController.h; path = Playlist/DNDArrayController.h; sourceTree = "<group>"; };
@ -215,6 +217,16 @@
8E546D6908843E8500E356EE /* French */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = French; path = French.lproj/Localizable.strings; sourceTree = "<group>"; };
8E5A90B0084CBC2F00AE6D62 /* Changelog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Changelog; sourceTree = "<group>"; };
8E6F2A1808480D010011F126 /* wheel.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = wheel.icns; path = Icons/wheel.icns; sourceTree = "<group>"; };
8E7D4F0B08A0709C00EBB15A /* OutputCoreAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OutputCoreAudio.h; sourceTree = "<group>"; };
8E7D4F0C08A0709C00EBB15A /* OutputCoreAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OutputCoreAudio.m; sourceTree = "<group>"; };
8E7D4F0F08A070AC00EBB15A /* OutputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OutputController.h; sourceTree = "<group>"; };
8E7D4F1008A070AC00EBB15A /* OutputController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OutputController.m; sourceTree = "<group>"; };
8E7D4F1308A070BB00EBB15A /* InputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputController.h; sourceTree = "<group>"; };
8E7D4F1408A070BB00EBB15A /* InputController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InputController.m; sourceTree = "<group>"; };
8E7D4F1808A070D600EBB15A /* Converter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Converter.h; sourceTree = "<group>"; };
8E7D4F1908A070D600EBB15A /* Converter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Converter.m; sourceTree = "<group>"; };
8E7D4F5A08A0734300EBB15A /* Semaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Semaphore.h; sourceTree = "<group>"; };
8E7D4F5B08A0734300EBB15A /* Semaphore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Semaphore.m; sourceTree = "<group>"; };
8E7FA05508731B49005E8B5F /* TODO */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TODO; sourceTree = "<group>"; };
8E7FA05908731B6F005E8B5F /* COMPILE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COMPILE; sourceTree = "<group>"; };
8E81BC31083673ED0025A375 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; };
@ -313,6 +325,7 @@
080E96DDFE201D6D7F000001 /* Classes */ = {
isa = PBXGroup;
children = (
8E7D4F0A08A0708600EBB15A /* New */,
8E267D030837F7A6004ACBC5 /* Feedback */,
8E267D080837F7A6004ACBC5 /* Updates */,
8E47215C08318D12001F89FA /* Playlist */,
@ -472,6 +485,25 @@
name = Custom;
sourceTree = "<group>";
};
8E7D4F0A08A0708600EBB15A /* New */ = {
isa = PBXGroup;
children = (
8E7D4F1808A070D600EBB15A /* Converter.h */,
8E7D4F1908A070D600EBB15A /* Converter.m */,
8E7D4F0B08A0709C00EBB15A /* OutputCoreAudio.h */,
8E7D4F0C08A0709C00EBB15A /* OutputCoreAudio.m */,
8E7D4F0F08A070AC00EBB15A /* OutputController.h */,
8E7D4F1008A070AC00EBB15A /* OutputController.m */,
8E7D4F1308A070BB00EBB15A /* InputController.h */,
8E7D4F1408A070BB00EBB15A /* InputController.m */,
8E7D4F5A08A0734300EBB15A /* Semaphore.h */,
8E7D4F5B08A0734300EBB15A /* Semaphore.m */,
8E2C5C2D08A67867008DA854 /* Controller.h */,
8E2C5C2E08A67867008DA854 /* Controller.m */,
);
name = New;
sourceTree = "<group>";
};
8EAFD26D08465E4500107BA5 /* Icons */ = {
isa = PBXGroup;
children = (

30
Controller.h Normal file
View File

@ -0,0 +1,30 @@
//
// Controller.h
// Cog
//
// Created by Zaphod Beeblebrox on 8/7/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface SoundController : NSObject {
InputController *input;
OutputController *output;
Converter *converter;
NSLock *outputLock;
NSLock *inputLock;
Semaphore *conversionSemaphore;
Semaphore *ioSemaphore;
NSMutableArray *amountConverted;
unsigned int amountPlayed; //when amountPlayed > amountConverted[0], amountPlayed -= amountConverted[0], pop(amountConverted[0])
}
- (void)convertedAmount:(int)amount; //called by converter...same thread?
- (void)playedAmount:(int)amount; //called by outputcontroller...different thread
@end

14
Controller.m Normal file
View File

@ -0,0 +1,14 @@
//
// Controller.m
// Cog
//
// Created by Zaphod Beeblebrox on 8/7/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import "Controller.h"
@implementation SoundController
@end

22
Converter.h Normal file
View File

@ -0,0 +1,22 @@
//
// Converter.h
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface Converter : NSObject {
SoundController *soundController;
}
- (void)setup;
- (void)cleanUp;
- (void)process;
- (int)convert:(void *)dest amount:(int)amount;
@end

111
Converter.m Normal file
View File

@ -0,0 +1,111 @@
//
// Converter.m
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import "Converter.h"
@implementation Converter
//called from the complexfill when the audio is converted...good clean fun
static OSStatus ACInputProc(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData)
{
SoundController *soundController = (SoundController *)inUserData;
OSStatus err = noErr;
int amountToWrite;
int amountWritten;
amountToWrite = (*ioNumberDataPackets)*[[soundController input] format].mBytesPerPacket;
availInput = [[[soundController input] buffer] amountAvailableToReadReturningBuffer:&readPtr];
while (availInput == 0)
{
[conversionSemaphore wait];
availInput = [[[soundController input] buffer] amountAvailableToReadReturningBuffer:&readPtr];
}
if (availInput > amountToWrite)
availInput = amountToWrite;
*ioNumberDataPackets = availInput/format->mBytesPerPacket;
ioData->mBuffers[0].mData = readPtr;
ioData->mBuffers[0].mDataByteSize = availInput;
ioData->mBuffers[0].mNumberChannels = [[soundController input] format].mChannelsPerFrame;
ioData->mNumberBuffers = 1;
return err;
}
-(void)process
{
void *writePtr;
int availOutput;
int amountConverted;
while ([soundController shouldContinue] == YES)
{
[[soundController outputLock] lock];
availOutput = [[[soundController output] buffer] amountAvailableToWriteReturningBuffer:&writePtr];
while (availOutput == 0)
{
[[soundController outputLock] unlock];
[conversionSemaphore wait];
[[soundController outputLock] lock];
availOutput = [[[soundController output] buffer] amountAvailableToWriteReturningBuffer:&writePtr];
}
amountConverted = [self convert:writePtr amount:availOutput];
[[[soundController output] buffer] didWriteAmount:amountConverted];
[[soundController outputLock] unlock];
}
}
- (int)convert:(void *)dest amount:(int)amount
{
AudioBufferList ioData;
UInt32 ioNumberFrames;
OSStatus err;
ioNumberFrames = amount/[[soundController output] format].mBytesPerFrame;
ioData.mBuffers[0].mData = dest;
ioData.mBuffers[0].mDataByteSize = amount;
ioData.mBuffers[0].mNumberChannels = [[soundController output] format].mChannelsPerFrame;
ioData.mNumberBuffers = 1;
err = AudioConverterFillComplexBuffer(converter, ACInputProc, &[[soundController input] format], &ioNumberFrames, &ioData, NULL);
if (err != noErr)
DBLog(@"Converter error: %i", err);
[[soundController inputBuffer] didReadLength:(ioNumberFrames * [[[soundController input] format].mBytesPerFrame]);
[[soundController ioSemaphore] signal];
return ioData.mBuffers[0].mDataByteSize;
}
- (void)setup
{
//Make the converter
OSStatus stat = noErr;
stat = AudioConverterNew ( &sourceStreamFormat, &deviceFormat, &converter);
// DBLog(@"Created converter");
if (stat != noErr)
{
DBLog(@"Error creating converter %i", stat);
}
}
- (void)cleanUp
{
AudioConverterDispose(converter);
}
@end

View File

@ -9,7 +9,7 @@
<key>29</key>
<string>243 676 346 44 0 0 1024 746 </string>
<key>463</key>
<string>354 382 352 268 0 0 1024 746 </string>
<string>336 385 352 268 0 0 1024 746 </string>
<key>513</key>
<string>475 157 109 106 0 0 1024 746 </string>
</dict>
@ -28,8 +28,8 @@
<integer>3</integer>
<key>IBOpenObjects</key>
<array>
<integer>21</integer>
<integer>463</integer>
<integer>21</integer>
</array>
<key>IBSystem Version</key>
<string>8C46</string>

Binary file not shown.

17
InputController.h Normal file
View File

@ -0,0 +1,17 @@
//
// InputController.h
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface InputController : NSObject {
VirtualRingBuffer *buffer;
AudioStreamBasicDescription format;
}
@end

19
InputController.m Normal file
View File

@ -0,0 +1,19 @@
//
// InputController.m
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import "InputController.h"
@implementation InputController
- (void)play
{
[SoundFile open:filename];
}
@end

17
OutputController.h Normal file
View File

@ -0,0 +1,17 @@
//
// OutputController.h
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface OutputController : NSObject {
VirtualRingBuffer *buffer;
AudioStreamBasicDescription format;
}
@end

14
OutputController.m Normal file
View File

@ -0,0 +1,14 @@
//
// OutputController.m
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import "OutputController.h"
@implementation OutputController
@end

20
OutputCoreAudio.h Normal file
View File

@ -0,0 +1,20 @@
//
// OutputCoreAudio.h
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface OutputCoreAudio : NSObject {
}
- (void)setup;
- (void)start;
- (void)stop;
@end

158
OutputCoreAudio.m Normal file
View File

@ -0,0 +1,158 @@
//
// OutputCoreAudio.m
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import "OutputCoreAudio.h"
@implementation OutputCoreAudio
static OSStatus Sound_Renderer(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
{
Sound *sound = (Sound *)inRefCon;
OSStatus err = noErr;
int amountAvailable;
int amountToRead;
void *readPointer;
[sound->readLock lock];
amountAvailable = [sound->readRingBuffer lengthAvailableToReadReturningPointer:&readPointer];
if (sound->playbackStatus == kCogStatusEndOfFile && amountAvailable == 0)
{
DBLog(@"FILE CHANGED!!!!!");
[sound sendPortMessage:kCogFileChangedMessage];
sound->readRingBuffer = [sound oppositeBuffer:sound->readRingBuffer];
[sound setPlaybackStatus:kCogStatusPlaying];
sound->currentPosition = 0;
double time = [sound calculateTime:sound->totalLength];
int bitrate = [sound->soundFile bitRate];
[sound sendPortMessage:kCogLengthUpdateMessage withData:&time ofSize:(sizeof(double))];
[sound sendPortMessage:kCogBitrateUpdateMessage withData:&bitrate ofSize:(sizeof(int))];
}
if (sound->playbackStatus == kCogStatusEndOfPlaylist && amountAvailable == 0)
{
//Stop playback
[sound setPlaybackStatus:kCogStatusStopped];
// return err;
}
if (amountAvailable < ([sound->readRingBuffer bufferLength] - BUFFER_WRITE_CHUNK))
{
// DBLog(@"AVAILABLE: %i", amountAvailable);
[sound fireFillTimer];
}
if (amountAvailable > inNumberFrames*sound->deviceFormat.mBytesPerPacket)
amountToRead = inNumberFrames*sound->deviceFormat.mBytesPerPacket;
else
amountToRead = amountAvailable;
memcpy(ioData->mBuffers[0].mData, readPointer, amountToRead);
ioData->mBuffers[0].mDataByteSize = amountToRead;
[sound->readRingBuffer didReadLength:amountToRead];
sound->currentPosition += amountToRead;
[sound->readLock unlock];
return err;
}
- (void)setup
{
ComponentDescription desc;
OSStatus err;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
Component comp = FindNextComponent(NULL, &desc); //Finds an component that meets the desc spec's
if (comp == NULL)
return NO;
err = OpenAComponent(comp, &outputUnit); //gains access to the services provided by the component
if (err)
return NO;
// Initialize AudioUnit
err = AudioUnitInitialize(outputUnit);
if (err != noErr)
return NO;
UInt32 size = sizeof (AudioStreamBasicDescription);
Boolean outWritable;
//Gets the size of the Stream Format Property and if it is writable
AudioUnitGetPropertyInfo(outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
0,
&size,
&outWritable);
//Get the current stream format of the output
err = AudioUnitGetProperty (outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
0,
&deviceFormat,
&size);
if (err != noErr)
return NO;
// change output format...
///Seems some 3rd party devices return incorrect stuff...or I just don't like noninterleaved data.
deviceFormat.mFormatFlags &= ~kLinearPCMFormatFlagIsNonInterleaved;
deviceFormat.mBytesPerFrame = deviceFormat.mChannelsPerFrame*(deviceFormat.mBitsPerChannel/8);
deviceFormat.mBytesPerPacket = deviceFormat.mBytesPerFrame * deviceFormat.mFramesPerPacket;
// DBLog(@"stuff: %i %i %i %i", deviceFormat.mBitsPerChannel, deviceFormat.mBytesPerFrame, deviceFormat.mBytesPerPacket, deviceFormat.mFramesPerPacket);
err = AudioUnitSetProperty (outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
0,
&deviceFormat,
size);
//Set the stream format of the output to match the input
err = AudioUnitSetProperty (outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&deviceFormat,
size);
//setup render callbacks
renderCallback.inputProc = Sound_Renderer;
renderCallback.inputProcRefCon = self;
AudioUnitSetProperty(outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(AURenderCallbackStruct));
// DBLog(@"Audio output successfully initialized");
return (err == noErr);
}
- (void)start
{
AudioOutputUnitStart(outputUnit);
}
- (void)stop
{
if (outputUnit)
AudioOutputUnitStop(outputUnit);
}
@end

View File

@ -219,10 +219,12 @@
-(void)readTags
{
TagLib_File *tagFile = taglib_file_new((const char *)[filename UTF8String]);
NSLog(@"Does it have a file? %i %s", tagFile, (const char *)[filename UTF8String]);
if (tagFile)
{
TagLib_Tag *tag = taglib_file_tag(tagFile);
NSLog(@"Does it have a tag? %i", tag);
if (tag)
{
char *pArtist, *pTitle, *pAlbum, *pGenre, *pComment;

2
README
View File

@ -19,7 +19,7 @@ licenses.
It is rated M for mature by the ESRB, the MPAA, and whatever else deems it
unsuitable for virgin ears.
All Cog code is copywrited by me, and is licensed under the GPL.
All Cog code is copyrighted by me, and is licensed under the GPL.
If you would like the photoshop sources for the various icons and
graphics, please send me an email, and I will be happy to get them to you.

21
Semaphore.h Normal file
View File

@ -0,0 +1,21 @@
//
// Semaphore.h
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <mach/mach.h>
@interface Semaphore : NSObject {
semaphore_t semaphore;
}
-(id)init;
-(void)signal;
-(void)timedWait:(int)seconds;
-(void)wait;
@end

42
Semaphore.m Normal file
View File

@ -0,0 +1,42 @@
//
// Semaphore.m
// Cog
//
// Created by Zaphod Beeblebrox on 8/2/05.
// Copyright 2005 __MyCompanyName__. All rights reserved.
//
#import "Semaphore.h"
@implementation Semaphore
-(id)init
{
self = [super init];
if (self)
{
semaphore_create(mach_task_self(), &semaphore, SYNC_POLICY_FIFO, 0);
}
return self;
}
-(void)signal
{
semaphore_signal(semaphore);
}
-(void)timedWait:(int)seconds
{
mach_timespec_t timeout = {seconds, 0};
semaphore_timedwait(semaphore, timeout);
}
-(void)wait
{
semaphore_wait(semaphore);
}
@end

View File

@ -102,7 +102,7 @@ enum
- (void)resetBuffer;
- (VirtualRingBuffer *)oppositeBuffer:(VirtualRingBuffer *)buf;
//private methodss
//private methods
- (BOOL)setupAudioOutput;
- (BOOL)startAudioOutput;
- (void)stopAudioOutput;

View File

@ -137,6 +137,9 @@ static OSStatus Sound_Renderer(void *inRefCon, AudioUnitRenderActionFlags *ioAc
sound->currentPosition += amountToRead;
if (sound->currentPosition > 1764000)
[sound stop];
[sound->readLock unlock];
return err;
@ -689,8 +692,6 @@ static OSStatus Sound_Renderer(void *inRefCon, AudioUnitRenderActionFlags *ioAc
return;
}
DBLog(@"DONT LIKE THIS, HUH?");
[readLock lock];
unsigned long length = totalLength;
int bitrate = [soundFile bitRate];
@ -718,7 +719,7 @@ static OSStatus Sound_Renderer(void *inRefCon, AudioUnitRenderActionFlags *ioAc
- (void)resetBuffer
{
[writeLock lock];
[readLock lock];
// [readLock lock];
[ringBuffer empty];
[auxRingBuffer empty];
@ -728,7 +729,7 @@ static OSStatus Sound_Renderer(void *inRefCon, AudioUnitRenderActionFlags *ioAc
currentPosition = 0;
[readLock unlock];
// [readLock unlock];
[writeLock unlock];
}