* Copyright 2007 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Bek, host.haiku@gmx.de
*/
#include "driver.h"
status_t
null_hw_create_virtual_buffers(device_stream_t* stream, const char* name)
{
uint32 i;
int buffer_size;
int area_size;
uint8* buffer;
buffer_size = stream->num_channels
* format_to_sample_size(stream->format)
* stream->buffer_length;
buffer_size = (buffer_size + 127) & (~127);
area_size = buffer_size * stream->num_buffers;
area_size = (area_size + B_PAGE_SIZE - 1) & (~(B_PAGE_SIZE -1));
stream->buffer_area = create_area("null_audio_buffers", (void**)&buffer,
B_ANY_KERNEL_ADDRESS, area_size,
B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
if (stream->buffer_area < B_OK)
return stream->buffer_area;
for (i = 0; i < stream->num_buffers; i++)
stream->buffers[i] = buffer + (i * buffer_size);
stream->buffer_ready_sem = create_sem(0, name);
return B_OK;
}
static int32
null_fake_interrupt(void* cookie)
{
bigtime_t sleepTime;
device_t* device = (device_t*) cookie;
int sampleRate;
switch (device->playback_stream.rate) {
case B_SR_48000:
sampleRate = 48000;
break;
case B_SR_44100:
default:
sampleRate = 44100;
break;
}
sleepTime = (device->playback_stream.buffer_length * 1000000LL) / sampleRate;
while (device->running) {
cpu_status status;
status = disable_interrupts();
acquire_spinlock(&device->playback_stream.lock);
device->playback_stream.real_time = system_time();
device->playback_stream.frames_count += device->playback_stream.buffer_length;
device->playback_stream.buffer_cycle = (device->playback_stream.buffer_cycle +1) % device->playback_stream.num_buffers;
release_spinlock(&device->playback_stream.lock);
acquire_spinlock(&device->record_stream.lock);
device->record_stream.real_time = device->playback_stream.real_time;
device->record_stream.frames_count += device->record_stream.buffer_length;
device->record_stream.buffer_cycle = (device->record_stream.buffer_cycle +1) % device->record_stream.num_buffers;
release_spinlock(&device->record_stream.lock);
restore_interrupts(status);
release_sem_etc(device->playback_stream.buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
release_sem_etc(device->record_stream.buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
snooze(sleepTime);
}
return B_OK;
}
status_t
null_start_hardware(device_t* device)
{
dprintf("null_audio: %s spawning fake interrupter\n", __func__);
device->running = true;
device->interrupt_thread = spawn_kernel_thread(null_fake_interrupt, "null_audio interrupter",
B_REAL_TIME_PRIORITY, (void*)device);
return resume_thread(device->interrupt_thread);
}
void
null_stop_hardware(device_t* device)
{
device->running = false;
}