RString RageSoundDriver_OSS::Init()
{
	fd = open("/dev/dsp", O_WRONLY|O_NONBLOCK);
	if( fd == -1 )
		return ssprintf( "RageSoundDriver_OSS: Couldn't open /dev/dsp: %s", strerror(errno) );

	RString sError = CheckOSSVersion( fd );
	if( sError != "" )
		return sError;

	int i = AFMT_S16_LE;
	if(ioctl(fd, SNDCTL_DSP_SETFMT, &i) == -1)
		return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SETFMT, %i): %s", i, strerror(errno) );
	if(i != AFMT_S16_LE)
		return ssprintf( "RageSoundDriver_OSS: Wanted format %i, got %i instead", AFMT_S16_LE, i );

	i = channels;
	if(ioctl(fd, SNDCTL_DSP_CHANNELS, &i) == -1)
		return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_CHANNELS, %i): %s", i, strerror(errno) );
	if(i != channels)
		return ssprintf( "RageSoundDriver_OSS: Wanted %i channels, got %i instead", channels, i );
		
	i = 44100;
	if(ioctl(fd, SNDCTL_DSP_SPEED, &i) == -1 )
		return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SPEED, %i): %s", i, strerror(errno) );
	samplerate = i;
	LOG->Trace("RageSoundDriver_OSS: sample rate %i", samplerate);
	i = (num_chunks << 16) + chunk_order;
	if(ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1)
		return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SETFRAGMENT, %i): %s", i, strerror(errno) );
	StartDecodeThread();
	
	MixingThread.SetName( "RageSoundDriver_OSS" );
	MixingThread.Create( MixerThread_start, this );

	return "";
}
RageSound_OSS::RageSound_OSS()
{
	fd = open("/dev/dsp", O_WRONLY|O_NONBLOCK);
	if(fd == -1)
		RageException::ThrowNonfatal("RageSound_OSS: Couldn't open /dev/dsp: %s", strerror(errno));

	CheckOSSVersion( fd );

	shutdown = false;
	last_cursor_pos = 0;

	int i = AFMT_S16_LE;
	if(ioctl(fd, SNDCTL_DSP_SETFMT, &i) == -1)
		RageException::ThrowNonfatal("RageSound_OSS: ioctl(SNDCTL_DSP_SETFMT, %i): %s", i, strerror(errno));
	if(i != AFMT_S16_LE)
		RageException::ThrowNonfatal("RageSound_OSS: Wanted format %i, got %i instead", AFMT_S16_LE, i);

	i = channels;
	if(ioctl(fd, SNDCTL_DSP_CHANNELS, &i) == -1)
		RageException::ThrowNonfatal("RageSound_OSS: ioctl(SNDCTL_DSP_CHANNELS, %i): %s", i, strerror(errno));
	if(i != channels)
		RageException::ThrowNonfatal("RageSound_OSS: Wanted %i channels, got %i instead", channels, i);
		
	i = 44100;
	if(ioctl(fd, SOUND_PCM_WRITE_RATE, &i) == -1 )
		RageException::ThrowNonfatal("RageSound_OSS: ioctl(SOUND_PCM_WRITE_RATE, %i): %s", i, strerror(errno));
	samplerate = i;
	LOG->Trace("RageSound_OSS: sample rate %i", samplerate);
	i = (num_chunks << 16) + chunk_order;
	if(ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1)
		RageException::ThrowNonfatal("RageSound_OSS: ioctl(SNDCTL_DSP_SETFRAGMENT, %i): %s", i, strerror(errno));

	StartDecodeThread();
	
	MixingThread.SetName( "RageSound_OSS" );
	MixingThread.Create( MixerThread_start, this );
}