mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 02:04:20 +00:00
Added OSS sound sink. Not connected to the build.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@28520 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
151a751f23
commit
3fb844f810
2 changed files with 253 additions and 0 deletions
|
@ -1,3 +1,7 @@
|
|||
2009-08-23 17:16-BST David Chisnall <theraven@sucs.org>
|
||||
|
||||
* Tools/sound/GSOSSSoundSink.m: Added OSS sound back end
|
||||
|
||||
2009-08-23 11:50-EDT Gregory John Casamento <greg.casamento@gmail.com>
|
||||
|
||||
* Tools/sound/GNUmakefile: Fix circular dependency issue.
|
||||
|
|
249
Tools/sound/GSOSSSoundSink.m
Normal file
249
Tools/sound/GSOSSSoundSink.m
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
AudioOutputSink.m
|
||||
|
||||
Sink audio data to the Open Sound System
|
||||
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
Written by: David Chisnall <theraven@sucs.org>
|
||||
Date: Jun 2009
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <GNUstepGUI/GSSoundSource.h>
|
||||
#import <GNUstepGUI/GSSoundSink.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/soundcard.h>
|
||||
|
||||
|
||||
#if SOUND_VERSION >= 0x040000
|
||||
#define OSS_V4
|
||||
#endif
|
||||
|
||||
|
||||
@interface AudioOutputSink : NSObject <GSSoundSink>
|
||||
{
|
||||
NSString *devicePath;
|
||||
int dev;
|
||||
int channels;
|
||||
int format;
|
||||
int rate;
|
||||
}
|
||||
@end
|
||||
|
||||
const static NSString *DefaultDevice = @"/dev/dsp";
|
||||
|
||||
@implementation AudioOutputSink
|
||||
+ (BOOL)canInitWithPlaybackDevice: (NSString *)playbackDevice
|
||||
{
|
||||
if (NULL == playbackDevice)
|
||||
{
|
||||
playbackDevice = DefaultDevice;
|
||||
}
|
||||
const char *device = [playbackDevice UTF8String];
|
||||
BOOL success = NO;
|
||||
int d = open(device, O_WRONLY, 0);
|
||||
if (-1 != d)
|
||||
{
|
||||
int ver;
|
||||
/* Check that this is an OSS device by trying an OSS ioctl on it */
|
||||
success = (-1 != ioctl(d, OSS_GETVERSION, &ver));
|
||||
close(d);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
- (BOOL)configureDevice
|
||||
{
|
||||
/* Close the device if it's open already. */
|
||||
[self close];
|
||||
|
||||
/* Open the device */
|
||||
if (-1 == (dev = open([devicePath UTF8String], O_WRONLY, 0)))
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* Set the number of channels */
|
||||
if (-1 == ioctl(dev, SNDCTL_DSP_CHANNELS, &channels))
|
||||
{
|
||||
[self close];
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* Set the sample format. */
|
||||
if (-1 == ioctl(dev, SNDCTL_DSP_SETFMT, &format))
|
||||
{
|
||||
[self close];
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (-1 == ioctl(dev, SNDCTL_DSP_SPEED, &rate))
|
||||
{
|
||||
[self close];
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithEncoding: (int)encoding
|
||||
channels: (NSUInteger)channelCount
|
||||
sampleRate: (NSUInteger)sampleRate
|
||||
byteOrder: (NSByteOrder)byteOrder
|
||||
{
|
||||
if (nil == (self = [super init])) { return nil; }
|
||||
|
||||
channels = channelCount;
|
||||
rate = sampleRate;
|
||||
|
||||
switch (encoding)
|
||||
{
|
||||
case GSSoundFormatPCMS8:
|
||||
format = AFMT_S8;
|
||||
break;
|
||||
|
||||
case GSSoundFormatPCM16:
|
||||
switch (byteOrder)
|
||||
{
|
||||
case NS_LittleEndian:
|
||||
format = AFMT_S16_LE;
|
||||
break;
|
||||
case NS_BigEndian:
|
||||
format = AFMT_S16_BE;
|
||||
break;
|
||||
default:
|
||||
format = AFMT_S16_NE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GSSoundFormatPCM24:
|
||||
switch (byteOrder)
|
||||
{
|
||||
case NS_LittleEndian:
|
||||
format = AFMT_S24_LE;
|
||||
break;
|
||||
case NS_BigEndian:
|
||||
format = AFMT_S24_BE;
|
||||
break;
|
||||
default:
|
||||
format = AFMT_S24_NE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GSSoundFormatPCM32:
|
||||
switch (byteOrder)
|
||||
{
|
||||
case NS_LittleEndian:
|
||||
format = AFMT_S32_LE;
|
||||
break;
|
||||
case NS_BigEndian:
|
||||
format = AFMT_S32_BE;
|
||||
break;
|
||||
default:
|
||||
format = AFMT_S32_NE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GSSoundFormatFloat32:
|
||||
/* Some OSS implementations (e.g. FreeBSD) don't support AFMT_FLOAT)
|
||||
* Fall through to unsupported formats if this is one of them.
|
||||
*/
|
||||
#ifdef AFMT_FLOAT
|
||||
format = AFMT_FLOAT;
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* Does this even exist? */
|
||||
case GSSoundFormatFloat64:
|
||||
default:
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Try to initialise this device */
|
||||
if (![self configureDevice])
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)open
|
||||
{
|
||||
return [self configureDevice];
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
if (-1 != dev)
|
||||
{
|
||||
close(dev);
|
||||
dev = -1;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)playBytes: (void*)bytes length: (NSUInteger)length
|
||||
{
|
||||
do
|
||||
{
|
||||
int written = write(dev, bytes, (size_t)length);
|
||||
if (-1 == written)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
length -= written;
|
||||
bytes += written;
|
||||
} while (length > 0);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)setVolume: (float)volume
|
||||
{
|
||||
#ifdef OSS_V4
|
||||
char channelVolue = volume * 255;
|
||||
/* OSS uses one byte for left and one byte for right volume */
|
||||
int vol = (channelVolue << 8) + channelVolue;
|
||||
ioctl(dev, SNDCTL_DSP_SETPLAYVOL, &vol);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (float)volume
|
||||
{
|
||||
#ifdef OSS_V4
|
||||
int vol;
|
||||
if (-1 == ioctl(dev, SNDCTL_DSP_SETPLAYVOL, &vol))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* Mask off the low 8 bits and scale back */
|
||||
return ((float)(vol & 255) ) / 255;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setPlaybackDeviceIdentifier: (NSString*)playbackDeviceIdentifier
|
||||
{
|
||||
ASSIGN(devicePath, playbackDeviceIdentifier);
|
||||
[self configureDevice];
|
||||
}
|
||||
|
||||
- (NSString*)playbackDeviceIdentifier
|
||||
{
|
||||
return devicePath;
|
||||
}
|
||||
/* Not implemented */
|
||||
- (void)setChannelMapping: (NSArray*)channelMapping { return; }
|
||||
- (NSArray*)channelMapping { return nil; }
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in a new issue