/boot/home/config/add-ons/media/legacy.media_addon
Adding the legacy (BeOS R3) sound driver interface BMediaAddOn. Written by Jens Winkler, snapshot from 2002-06-02. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@71 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,430 @@
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <media/Buffer.h>
|
||||
#include <media/BufferGroup.h>
|
||||
#include <media/ParameterWeb.h>
|
||||
#include <media/TimeSource.h>
|
||||
|
||||
#include <support/Autolock.h>
|
||||
#include <support/Debug.h>
|
||||
|
||||
#include "driver/audio.h"
|
||||
#include "driver/sound.h"
|
||||
|
||||
#include "LegacyAudioConsumer.h"
|
||||
|
||||
#include "driver_io.h"
|
||||
|
||||
|
||||
LegacyAudioConsumer::LegacyAudioConsumer( BMediaAddOn *addon, const char *name, int32 internal_id )
|
||||
: BMediaNode( name ), BBufferConsumer( B_MEDIA_RAW_AUDIO )
|
||||
{
|
||||
mInitStatus = B_NO_INIT;
|
||||
|
||||
mAddOn = addon;
|
||||
|
||||
mId = internal_id;
|
||||
|
||||
mBuffers = NULL;
|
||||
|
||||
mThread = -1;
|
||||
|
||||
mProcessingLatency = 0LL;
|
||||
|
||||
mRunning = false;
|
||||
mConnected = false;
|
||||
|
||||
io_buf1 = NULL;
|
||||
|
||||
AddNodeKind( B_PHYSICAL_OUTPUT );
|
||||
|
||||
sprintf( device_name, "/dev/audio/old/%s", name );
|
||||
|
||||
//open the device driver for output
|
||||
fd = open( device_name, O_WRONLY );
|
||||
|
||||
if ( fd == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
DRIVER_GET_PLAYBACK_PREFERRED_BUF_SIZE( &mBuffer_size, 0 );
|
||||
|
||||
io_buf1 = malloc( 2 * ( sizeof( audio_buffer_header ) + mBuffer_size ) );
|
||||
|
||||
if ( io_buf1 == NULL ) {
|
||||
close( fd );
|
||||
return;
|
||||
}
|
||||
|
||||
io_buf2 = static_cast<char *>( io_buf1 ) + sizeof( audio_buffer_header ) + mBuffer_size;
|
||||
|
||||
static_cast<audio_buffer_header *>( io_buf1 )->reserved_1 = sizeof( audio_buffer_header ) + mBuffer_size;
|
||||
static_cast<audio_buffer_header *>( io_buf2 )->reserved_1 = sizeof( audio_buffer_header ) + mBuffer_size;
|
||||
|
||||
mInitStatus = B_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
LegacyAudioConsumer::~LegacyAudioConsumer()
|
||||
{
|
||||
if ( mInitStatus != B_OK ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
if ( mConnected ) {
|
||||
Disconnected( mInput.source, mInput.destination );
|
||||
}
|
||||
|
||||
if ( mRunning ) {
|
||||
HandleStop();
|
||||
}
|
||||
|
||||
if ( io_buf1 != NULL ) {
|
||||
free( static_cast<void *>( io_buf1 ) );
|
||||
}
|
||||
|
||||
if ( fd != 0 ) {
|
||||
close( fd );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* BMediaNode */
|
||||
|
||||
BMediaAddOn *
|
||||
LegacyAudioConsumer::AddOn( int32 *internal_id ) const
|
||||
{
|
||||
if ( internal_id ) {
|
||||
*internal_id = mId;
|
||||
}
|
||||
|
||||
return mAddOn;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::NodeRegistered()
|
||||
{
|
||||
mInput.destination.port = ControlPort();
|
||||
mInput.destination.id = 0;
|
||||
|
||||
mInput.source = media_source::null;
|
||||
|
||||
mInput.format.type = B_MEDIA_RAW_AUDIO;
|
||||
mInput.format.u.raw_audio.frame_rate = 44100.0;
|
||||
mInput.format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
mInput.format.u.raw_audio.channel_count = 2;
|
||||
mInput.format.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
mInput.format.u.raw_audio.buffer_size = mBuffer_size;
|
||||
|
||||
Run();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LegacyAudioConsumer::HandleMessage( int32 message, const void *data, size_t size )
|
||||
{
|
||||
status_t err = B_OK;
|
||||
|
||||
if ( BBufferConsumer::HandleMessage( message, data, size ) != B_OK ) {
|
||||
if ( ( err = BMediaNode::HandleMessage( message, data, size ) ) != B_OK ) {
|
||||
BMediaNode::HandleBadMessage( message, data, size );
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* BBufferConsumer */
|
||||
|
||||
status_t
|
||||
LegacyAudioConsumer::AcceptFormat( const media_destination &dest, media_format *format )
|
||||
{
|
||||
if ( format->type != B_MEDIA_RAW_AUDIO ) {
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
}
|
||||
|
||||
format->u.raw_audio.frame_rate = 44100.0;
|
||||
format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
format->u.raw_audio.channel_count = 2;
|
||||
format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
format->u.raw_audio.buffer_size = mBuffer_size;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LegacyAudioConsumer::GetNextInput( int32 *cookie, media_input *out_input )
|
||||
{
|
||||
if ( *cookie == 0 ) {
|
||||
memcpy( out_input, &mInput , sizeof( media_input ) );
|
||||
}
|
||||
|
||||
return B_BAD_INDEX;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::BufferReceived( BBuffer *buffer )
|
||||
{
|
||||
if ( ! mRunning ) {
|
||||
|
||||
buffer->Recycle();
|
||||
|
||||
} else {
|
||||
|
||||
media_timed_event event( buffer->Header()->start_time,
|
||||
BTimedEventQueue::B_HANDLE_BUFFER,
|
||||
buffer,
|
||||
BTimedEventQueue::B_RECYCLE_BUFFER );
|
||||
|
||||
EventQueue()->AddEvent( event );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::ProducerDataStatus( const media_destination &for_whom, int32 status,
|
||||
bigtime_t at_media_time )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LegacyAudioConsumer::GetLatencyFor( const media_destination &for_whom, bigtime_t *out_latency,
|
||||
media_node_id *out_timesource )
|
||||
{
|
||||
*out_latency = mBuffer_size * 10000 / 4 / 441;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LegacyAudioConsumer::Connected( const media_source &producer, const media_destination &where,
|
||||
const media_format &with_format, media_input *out_input )
|
||||
{
|
||||
mInput.source = producer;
|
||||
//mInput.format = with_format;
|
||||
mInput.node = Node();
|
||||
strcpy( mInput.name, "Legacy Audio Consumer" );
|
||||
|
||||
mBuffers = new BBufferGroup;
|
||||
|
||||
uint32 dummy_data = 0;
|
||||
int32 change_tag = 1;
|
||||
|
||||
BBufferConsumer::SetOutputBuffersFor( producer, mDest, mBuffers, static_cast<void *>( &dummy_data ),
|
||||
&change_tag, true );
|
||||
|
||||
mConnected = true;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::Disconnected( const media_source &producer, const media_destination &where )
|
||||
{
|
||||
if ( mConnected ) {
|
||||
delete mBuffers;
|
||||
mInput.source = media_source::null;
|
||||
mConnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
status_t
|
||||
LegacyAudioConsumer::FormatChanged( const media_source &producer, const media_destination &consumer,
|
||||
int32 change_tag, const media_format &format )
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* BMediaEventLooper */
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::HandleEvent( const media_timed_event *event, bigtime_t lateness, bool realTimeEvent )
|
||||
{
|
||||
switch(event->type) {
|
||||
case BTimedEventQueue::B_START:
|
||||
HandleStart( event->event_time );
|
||||
break;
|
||||
|
||||
case BTimedEventQueue::B_STOP:
|
||||
HandleStop();
|
||||
break;
|
||||
|
||||
case BTimedEventQueue::B_WARP:
|
||||
HandleTimeWarp( event->bigdata );
|
||||
break;
|
||||
|
||||
case BTimedEventQueue::B_SEEK:
|
||||
HandleSeek( event->bigdata );
|
||||
break;
|
||||
|
||||
case BTimedEventQueue::B_HANDLE_BUFFER:
|
||||
HandleBuffer( static_cast<BBuffer *>( event->pointer ) );
|
||||
break;
|
||||
|
||||
case BTimedEventQueue::B_DATA_STATUS:
|
||||
case BTimedEventQueue::B_PARAMETER:
|
||||
default:
|
||||
break; //HandleEvent: Unhandled event
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* LegacyAudioConsumer */
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::HandleStart( bigtime_t performance_time )
|
||||
{
|
||||
if ( mRunning ) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPerformanceTimeBase = performance_time;
|
||||
|
||||
//allocate buffer available semaphore
|
||||
mBuffer_avail = create_sem( 0, "legacy audio out buffer avail" );
|
||||
|
||||
if ( mBuffer_avail < B_OK ) {
|
||||
goto init_err1;
|
||||
}
|
||||
|
||||
//allocate buffer free semaphore
|
||||
mBuffer_free = create_sem( 1, "legacy audio out buffer free" );
|
||||
|
||||
if ( mBuffer_free < B_OK ) {
|
||||
goto init_err2;
|
||||
}
|
||||
|
||||
//allocate output completion semaphore
|
||||
mBuffer_waitIO = create_sem( 1, "legacy audio out waitIO" );
|
||||
|
||||
if ( mBuffer_waitIO < B_OK ) {
|
||||
goto init_err3;
|
||||
}
|
||||
|
||||
//tell the driver about the playback completion semaphore
|
||||
DRIVER_SET_PLAYBACK_COMPLETION_SEM( &mBuffer_waitIO, 0 );
|
||||
|
||||
mThread = spawn_thread( _run_thread_, "legacy audio output", B_REAL_TIME_PRIORITY, this );
|
||||
|
||||
if ( mThread < B_OK ) {
|
||||
goto init_err4;
|
||||
}
|
||||
|
||||
io_buf = io_buf1;
|
||||
|
||||
resume_thread( mThread );
|
||||
|
||||
mRunning = true;
|
||||
return;
|
||||
|
||||
init_err4:
|
||||
delete_sem( mBuffer_waitIO );
|
||||
|
||||
init_err3:
|
||||
delete_sem( mBuffer_free );
|
||||
|
||||
init_err2:
|
||||
delete_sem( mBuffer_avail );
|
||||
|
||||
init_err1:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::HandleStop()
|
||||
{
|
||||
if ( ! mRunning ) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete_sem( mBuffer_avail );
|
||||
delete_sem( mBuffer_free );
|
||||
delete_sem( mBuffer_waitIO );
|
||||
wait_for_thread( mThread, &mThread );
|
||||
|
||||
mRunning = false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::HandleTimeWarp( bigtime_t performance_time )
|
||||
{
|
||||
mPerformanceTimeBase = performance_time;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::HandleSeek( bigtime_t performance_time )
|
||||
{
|
||||
mPerformanceTimeBase = performance_time;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyAudioConsumer::HandleBuffer( BBuffer *buffer )
|
||||
{
|
||||
void *buf;
|
||||
|
||||
//wait for free buffer
|
||||
acquire_sem( mBuffer_free );
|
||||
|
||||
//avoid buffer currently in use
|
||||
buf = static_cast<void *>( ( io_buf == io_buf2 ) ? io_buf1 : io_buf2 );
|
||||
|
||||
//prepare buffer
|
||||
memcpy( static_cast<char *>( buf ) + sizeof( audio_buffer_header ), buffer->Data(), buffer->SizeUsed() );
|
||||
|
||||
//tell the io thread a new buffer is ready
|
||||
release_sem( mBuffer_avail );
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
LegacyAudioConsumer::_run_thread_( void *data )
|
||||
{
|
||||
return static_cast<LegacyAudioConsumer *>( data )->RunThread();
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
LegacyAudioConsumer::RunThread()
|
||||
{
|
||||
while ( 1 ) {
|
||||
|
||||
//wait for next buffer
|
||||
if ( acquire_sem( mBuffer_avail ) == B_BAD_SEM_ID ) {
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//send buffer
|
||||
DRIVER_UNSAFE_WRITE( io_buf, 0 );
|
||||
|
||||
//wait for IO
|
||||
if ( acquire_sem( mBuffer_waitIO ) == B_BAD_SEM_ID ) {
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
io_buf = ( io_buf == io_buf2 ) ? io_buf1 : io_buf2;
|
||||
|
||||
//mark buffer free
|
||||
release_sem( mBuffer_free );
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
#ifndef _LEGACY_AUDIO_CONSUMER_H
|
||||
#define _LEGACY_AUDIO_CONSUMER_H
|
||||
|
||||
#include <kernel/OS.h>
|
||||
#include <media/BufferConsumer.h>
|
||||
#include <media/Controllable.h>
|
||||
#include <media/MediaEventLooper.h>
|
||||
#include <media/MediaDefs.h>
|
||||
#include <media/MediaAddOn.h>
|
||||
#include <media/MediaNode.h>
|
||||
#include <support/Locker.h>
|
||||
|
||||
class LegacyAudioConsumer :
|
||||
public virtual BMediaEventLooper,
|
||||
public virtual BBufferConsumer
|
||||
{
|
||||
public:
|
||||
LegacyAudioConsumer( BMediaAddOn *addon, const char *name, int32 internal_id );
|
||||
~LegacyAudioConsumer();
|
||||
|
||||
virtual status_t InitCheck() const
|
||||
{ return mInitStatus; }
|
||||
|
||||
/* BMediaNode */
|
||||
public:
|
||||
virtual BMediaAddOn *AddOn( int32 *internal_id ) const;
|
||||
|
||||
protected:
|
||||
virtual void NodeRegistered();
|
||||
virtual status_t HandleMessage( int32 message,
|
||||
const void *data,
|
||||
size_t size );
|
||||
|
||||
/* BMediaEventLooper */
|
||||
protected:
|
||||
virtual void HandleEvent( const media_timed_event *event,
|
||||
bigtime_t lateness,
|
||||
bool realTimeEvent = false );
|
||||
|
||||
|
||||
/* BBufferConsumer */
|
||||
public:
|
||||
virtual status_t AcceptFormat( const media_destination &dest,
|
||||
media_format *format );
|
||||
|
||||
virtual status_t GetNextInput( int32 *cookie,
|
||||
media_input *out_input );
|
||||
|
||||
virtual void DisposeInputCookie( int32 cookie ) {}
|
||||
|
||||
protected:
|
||||
virtual void BufferReceived( BBuffer *buffer );
|
||||
|
||||
private:
|
||||
virtual void ProducerDataStatus( const media_destination &for_whom,
|
||||
int32 status,
|
||||
bigtime_t at_performance_time );
|
||||
|
||||
virtual status_t GetLatencyFor( const media_destination &for_whom,
|
||||
bigtime_t *out_latency,
|
||||
media_node_id *out_timesource );
|
||||
|
||||
virtual status_t Connected( const media_source &producer,
|
||||
const media_destination &where,
|
||||
const media_format &with_format,
|
||||
media_input *out_input );
|
||||
|
||||
virtual void Disconnected( const media_source &producer,
|
||||
const media_destination &where );
|
||||
|
||||
virtual status_t FormatChanged( const media_source &producer,
|
||||
const media_destination &consumer,
|
||||
int32 change_tag,
|
||||
const media_format &format );
|
||||
|
||||
/* state */
|
||||
private:
|
||||
void HandleStart( bigtime_t performance_time );
|
||||
void HandleStop();
|
||||
void HandleTimeWarp( bigtime_t performance_time );
|
||||
void HandleSeek( bigtime_t performance_time );
|
||||
void HandleBuffer( BBuffer *buffer );
|
||||
|
||||
static int32 _run_thread_( void *data );
|
||||
int32 RunThread();
|
||||
|
||||
status_t mInitStatus;
|
||||
|
||||
BMediaAddOn *mAddOn;
|
||||
int32 mId;
|
||||
|
||||
char device_name[32];
|
||||
|
||||
BBufferGroup *mBuffers;
|
||||
thread_id mThread;
|
||||
|
||||
/* state variables */
|
||||
volatile bool mRunning;
|
||||
volatile bool mConnected;
|
||||
|
||||
volatile bigtime_t mPerformanceTimeBase;
|
||||
volatile bigtime_t mProcessingLatency;
|
||||
|
||||
media_input mInput;
|
||||
media_destination mDest;
|
||||
|
||||
size_t mBuffer_size;
|
||||
|
||||
volatile void *io_buf1;
|
||||
volatile void *io_buf2;
|
||||
volatile void *io_buf;
|
||||
|
||||
int fd; //file descriptor for hw driver
|
||||
|
||||
sem_id mBuffer_avail;
|
||||
sem_id mBuffer_free;
|
||||
|
||||
sem_id mBuffer_waitIO; //IO completion semaphore
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,209 @@
|
||||
#include <media/MediaDefs.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "driver/sound.h"
|
||||
|
||||
#include "LegacyAudioDevice.h"
|
||||
|
||||
|
||||
LegacyAudioDevice::LegacyAudioDevice( const char *name, int32 id )
|
||||
{
|
||||
size_t buffer_size;
|
||||
|
||||
fInitOK = false;
|
||||
|
||||
//open the device driver
|
||||
fd = open( name, O_RDWR );
|
||||
|
||||
if ( fd == 0 ) {
|
||||
goto init_err1;
|
||||
}
|
||||
|
||||
input_flavor.name = const_cast<char *>( name );
|
||||
input_flavor.info = "legacy audio input";
|
||||
input_flavor.kinds = B_BUFFER_PRODUCER|B_CONTROLLABLE|B_PHYSICAL_INPUT;
|
||||
input_flavor.flavor_flags = B_FLAVOR_IS_GLOBAL;
|
||||
input_flavor.internal_id = 2 * id;
|
||||
input_flavor.possible_count = 1;
|
||||
input_flavor.in_format_count = 0;
|
||||
input_flavor.in_format_flags = 0;
|
||||
input_flavor.in_formats = NULL;
|
||||
input_flavor.out_format_count = 1;
|
||||
input_flavor.out_format_flags = 0;
|
||||
input_flavor.out_formats = &input_format;
|
||||
|
||||
//get driver capture buffer size
|
||||
ioctl( fd, SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE, &buffer_size, 0 );
|
||||
ioctl( fd, SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE, buffer_size, 0 );
|
||||
|
||||
input_format.type = B_MEDIA_RAW_AUDIO;
|
||||
input_format.u.raw_audio.frame_rate = 44100.0;
|
||||
input_format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
input_format.u.raw_audio.channel_count = 2;
|
||||
input_format.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
input_format.u.raw_audio.buffer_size = buffer_size;
|
||||
|
||||
//allocate input completion semaphore
|
||||
in_sem = create_sem( 0, "legacy audio input completion" );
|
||||
|
||||
if ( in_sem < B_OK ) {
|
||||
goto init_err2;
|
||||
}
|
||||
|
||||
//tell the driver about the capture completion semaphore
|
||||
ioctl( fd, SOUND_SET_CAPTURE_COMPLETION_SEM, &in_sem, 0 );
|
||||
|
||||
output_flavor.name = const_cast<char *>( name );
|
||||
output_flavor.info = "legacy audio output";
|
||||
output_flavor.kinds = B_BUFFER_CONSUMER|B_TIME_SOURCE|B_CONTROLLABLE|B_PHYSICAL_OUTPUT;
|
||||
output_flavor.flavor_flags = B_FLAVOR_IS_GLOBAL;
|
||||
output_flavor.internal_id = 2 * id + 1;
|
||||
output_flavor.possible_count = 1;
|
||||
output_flavor.in_format_count = 1;
|
||||
output_flavor.in_format_flags = 0;
|
||||
output_flavor.in_formats = &output_format;
|
||||
output_flavor.out_format_count = 0;
|
||||
output_flavor.out_format_flags = 0;
|
||||
output_flavor.out_formats = NULL;
|
||||
|
||||
//get driver playback buffer size
|
||||
ioctl( fd, SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE, &buffer_size, 0 );
|
||||
ioctl( fd, SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE, buffer_size, 0 );
|
||||
|
||||
output_format.type = B_MEDIA_RAW_AUDIO;
|
||||
output_format.u.raw_audio.frame_rate = 44100.0;
|
||||
output_format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
output_format.u.raw_audio.channel_count = 2;
|
||||
output_format.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
output_format.u.raw_audio.buffer_size = buffer_size;
|
||||
|
||||
//allocate output completion semaphore
|
||||
out_sem = create_sem( 0, "legacy audio output completion" );
|
||||
|
||||
if ( out_sem < B_OK ) {
|
||||
goto init_err3;
|
||||
}
|
||||
|
||||
//tell the driver about the playback completion semaphore
|
||||
ioctl( fd, SOUND_SET_PLAYBACK_COMPLETION_SEM, &out_sem, 0 );
|
||||
|
||||
fInitOK = true;
|
||||
return;
|
||||
|
||||
init_err3:
|
||||
delete_sem( in_sem );
|
||||
|
||||
init_err2:
|
||||
close( fd );
|
||||
|
||||
init_err1:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
LegacyAudioDevice::~LegacyAudioDevice()
|
||||
{
|
||||
if ( fInitOK == false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//cleaning up...
|
||||
|
||||
if ( out_sem > B_OK ) {
|
||||
delete_sem( out_sem );
|
||||
}
|
||||
|
||||
if ( in_sem > B_OK ) {
|
||||
delete_sem( in_sem );
|
||||
}
|
||||
|
||||
if ( fd != 0 ) {
|
||||
close( fd );
|
||||
}
|
||||
|
||||
//...done
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
LegacyAudioDevice::Input_Thread()
|
||||
{
|
||||
while ( 1 ) {
|
||||
/* send IO request */
|
||||
ioctl( fd, SOUND_UNSAFE_READ, buffer, sizeof( buffer ) );
|
||||
|
||||
/* Wait for IO completion:
|
||||
The only acceptable response is B_OK. Everything else means
|
||||
the thread should quit. */
|
||||
_ if ( acquire_sem( in_sem ) != B_OK ) {
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Send buffers only if the node is running and the output has been
|
||||
* enabled */
|
||||
if ( !fRunning || !fEnabled ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BAutolock _(fLock);
|
||||
|
||||
/* Fetch a buffer from the buffer group */
|
||||
BBuffer *buffer = fBufferGroup->RequestBuffer(
|
||||
4 * fConnectedFormat.display.line_width *
|
||||
fConnectedFormat.display.line_count, 0LL);
|
||||
if (!buffer)
|
||||
continue;
|
||||
|
||||
/* Fill out the details about this buffer. */
|
||||
media_header *h = buffer->Header();
|
||||
h->type = B_MEDIA_RAW_VIDEO;
|
||||
h->time_source = TimeSource()->ID();
|
||||
h->size_used = 4 * fConnectedFormat.display.line_width *
|
||||
fConnectedFormat.display.line_count;
|
||||
/* For a buffer originating from a device, you might want to calculate
|
||||
* this based on the PerformanceTimeFor the time your buffer arrived at
|
||||
* the hardware (plus any applicable adjustments). */
|
||||
h->start_time = fPerformanceTimeBase +
|
||||
(bigtime_t)
|
||||
((fFrame - fFrameBase) *
|
||||
(1000000 / fConnectedFormat.field_rate));
|
||||
h->file_pos = 0;
|
||||
h->orig_size = 0;
|
||||
h->data_offset = 0;
|
||||
h->u.raw_video.field_gamma = 1.0;
|
||||
h->u.raw_video.field_sequence = fFrame;
|
||||
h->u.raw_video.field_number = 0;
|
||||
h->u.raw_video.pulldown_number = 0;
|
||||
h->u.raw_video.first_active_line = 1;
|
||||
h->u.raw_video.line_count = fConnectedFormat.display.line_count;
|
||||
|
||||
/* Fill in a pattern */
|
||||
uint32 *p = (uint32 *)buffer->Data();
|
||||
for (int y=0;y<fConnectedFormat.display.line_count;y++)
|
||||
for (int x=0;x<fConnectedFormat.display.line_width;x++)
|
||||
*(p++) = ((((x+y)^0^x)+fFrame) & 0xff) * (0x01010101 & fColor);
|
||||
|
||||
/* Send the buffer on down to the consumer */
|
||||
if (SendBuffer(buffer, fOutput.destination) < B_OK) {
|
||||
PRINTF(-1, ("FrameGenerator: Error sending buffer\n"));
|
||||
/* If there is a problem sending the buffer, return it to its
|
||||
* buffer group. */
|
||||
buffer->Recycle();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
LegacyAudioDevice::Output_Thread()
|
||||
{
|
||||
while (1) {
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*****************************************************************************/
|
||||
// LegacyAudioDevice class
|
||||
//
|
||||
// [Class Description]
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2002 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _LEGACY_AUDIO_DEVICE_H
|
||||
#define _LEGACY_AUDIO_DEVICE_H
|
||||
|
||||
#include <media/MediaAddOn.h>
|
||||
#include <media/MediaFormats.h>
|
||||
|
||||
class LegacyAudioDevice
|
||||
{
|
||||
public:
|
||||
LegacyAudioDevice( const char *name, int32 id );
|
||||
~LegacyAudioDevice();
|
||||
|
||||
bool CheckInit()
|
||||
{ return fInitOK; }
|
||||
|
||||
flavor_info *GetInputFlavor()
|
||||
{ return &input_flavor; }
|
||||
|
||||
flavor_info *GetOutputFlavor()
|
||||
{ return &output_flavor; }
|
||||
|
||||
media_format *GetInputFormat()
|
||||
{ return &input_format; }
|
||||
|
||||
media_format *GetOutputFormat()
|
||||
{ return &output_format; }
|
||||
|
||||
|
||||
protected:
|
||||
int32 Input_Thread();
|
||||
int32 Output_Thread();
|
||||
|
||||
private:
|
||||
bool fInitOK;
|
||||
|
||||
int fd; //file-descriptor of hw device
|
||||
|
||||
flavor_info input_flavor;
|
||||
media_format input_format;
|
||||
sem_id in_sem; //input completion semaphore
|
||||
thread_id input_thread; //input thread
|
||||
|
||||
flavor_info output_flavor;
|
||||
media_format output_format;
|
||||
sem_id out_sem; //output completion semaphore
|
||||
thread_id output_thread; //output thread
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <media/Buffer.h>
|
||||
#include <media/BufferGroup.h>
|
||||
#include <media/ParameterWeb.h>
|
||||
#include <media/TimeSource.h>
|
||||
|
||||
#include <support/Autolock.h>
|
||||
#include <support/Debug.h>
|
||||
|
||||
#include "driver/sound.h"
|
||||
|
||||
//#include "LegacyAudioProducer.h"
|
||||
|
||||
#if 0
|
||||
LegacyAudioProducer::LegacyAudioProducer( BMediaAddOn *addon, const char *name, int32 internal_id )
|
||||
: BMediaNode( name ), BMediaEventLooper(), BBufferProducer( B_MEDIA_RAW_AUDIO ), BControllable()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
#ifndef _LEGACY_AUDIO_PRODUCER_H
|
||||
#define _LEGACY_AUDIO_PRODUCER_H
|
||||
|
||||
#include <kernel/OS.h>
|
||||
#include <media/BufferProducer.h>
|
||||
#include <media/Controllable.h>
|
||||
#include <media/MediaAddOn.h>
|
||||
#include <media/MediaDefs.h>
|
||||
#include <media/MediaEventLooper.h>
|
||||
#include <media/MediaNode.h>
|
||||
#include <support/Locker.h>
|
||||
|
||||
class LegacyAudioProducer : public virtual BMediaEventLooper,
|
||||
public virtual BBufferProducer,
|
||||
public virtual BControllable
|
||||
{
|
||||
public:
|
||||
LegacyAudioProducer( BMediaAddOn *addon, const char *name, int32 internal_id );
|
||||
virtual ~LegacyAudioProducer();
|
||||
virtual status_t InitCheck() const { return fInitStatus; }
|
||||
|
||||
/* BMediaNode */
|
||||
public:
|
||||
virtual port_id ControlPort() const;
|
||||
virtual BMediaAddOn *AddOn( int32 *internal_id ) const;
|
||||
virtual status_t HandleMessage( int32 message, const void *data, size_t size );
|
||||
|
||||
protected:
|
||||
virtual void Preroll() {}
|
||||
virtual void SetTimeSource( BTimeSource *time_source );
|
||||
virtual status_t RequestCompleted( const media_request_info &info );
|
||||
|
||||
/* BMediaEventLooper */
|
||||
protected:
|
||||
virtual void NodeRegistered();
|
||||
virtual void Start( bigtime_t performance_time );
|
||||
virtual void Stop( bigtime_t performance_time, bool immediate );
|
||||
virtual void Seek( bigtime_t media_time, bigtime_t performance_time );
|
||||
virtual void TimeWarp( bigtime_t at_real_time, bigtime_t to_performance_time );
|
||||
virtual status_t AddTimer( bigtime_t at_performance_time, int32 cookie );
|
||||
virtual void SetRunMode( run_mode mode );
|
||||
virtual void HandleEvent( const media_timed_event *event, bigtime_t lateness, bool realTimeEvent = false );
|
||||
virtual void CleanUpEvent( const media_timed_event *event );
|
||||
virtual bigtime_t OfflineTime();
|
||||
virtual void ControlLoop();
|
||||
virtual status_t DeleteHook( BMediaNode *node );
|
||||
|
||||
/* BBufferProducer */
|
||||
protected:
|
||||
virtual status_t FormatSuggestionRequested( media_type type, int32 quality, media_format *format );
|
||||
virtual status_t FormatProposal( const media_source &output, media_format *format );
|
||||
virtual status_t FormatChangeRequested( const media_source &source, const media_destination &destination,
|
||||
media_format *io_format, int32 *_deprecated_ );
|
||||
virtual status_t GetNextOutput( int32 *cookie, media_output *out_output );
|
||||
virtual status_t DisposeOutputCookie( int32 cookie );
|
||||
virtual status_t SetBufferGroup( const media_source &for_source, BBufferGroup *group );
|
||||
virtual status_t VideoClippingChanged( const media_source &for_source, int16 num_shorts, int16 *clip_data,
|
||||
const media_video_display_info &display, int32 *_deprecated_ )
|
||||
{ return B_ERROR; }
|
||||
virtual status_t GetLatency( bigtime_t *out_latency );
|
||||
virtual status_t PrepareToConnect( const media_source &what, const media_destination &where, media_format *format,
|
||||
media_source *out_source, char *out_name);
|
||||
virtual void Connect( status_t error, const media_source &source, const media_destination &destination,
|
||||
const media_format &format, char *io_name );
|
||||
virtual void Disconnect( const media_source &what, const media_destination &where );
|
||||
virtual void LateNoticeReceived( const media_source &what, bigtime_t how_much, bigtime_t performance_time );
|
||||
virtual void EnableOutput( const media_source &what, bool enabled, int32 *_deprecated_ );
|
||||
virtual status_t SetPlayRate( int32 numer,int32 denom );
|
||||
virtual void AdditionalBufferRequested( const media_source & source, media_buffer_id prev_buffer,
|
||||
bigtime_t prev_time, const media_seek_tag *prev_tag );
|
||||
virtual void LatencyChanged( const media_source &source, const media_destination &destination,
|
||||
bigtime_t new_latency, uint32 flags );
|
||||
|
||||
/* BControllable */
|
||||
protected:
|
||||
virtual status_t GetParameterValue( int32 id, bigtime_t *last_change, void *value, size_t *size );
|
||||
virtual void SetParameterValue( int32 id, bigtime_t when, const void *value, size_t size );
|
||||
virtual status_t StartControlPanel( BMessenger *out_messenger )
|
||||
{ return B_ERROR; }
|
||||
|
||||
/* state */
|
||||
private:
|
||||
void HandleStart( bigtime_t performance_time );
|
||||
void HandleStop();
|
||||
void HandleTimeWarp( bigtime_t performance_time );
|
||||
void HandleSeek( bigtime_t performance_time );
|
||||
|
||||
status_t fInitStatus;
|
||||
|
||||
int32 fInternalID;
|
||||
BMediaAddOn *fAddOn;
|
||||
|
||||
BLocker fLock;
|
||||
BBufferGroup *fBufferGroup;
|
||||
|
||||
thread_id fThread;
|
||||
sem_id fFrameSync;
|
||||
|
||||
static int32 _run_thread_( void *data );
|
||||
int32 RunThread();
|
||||
|
||||
#if 0
|
||||
/* The remaining variables should be declared volatile, but they
|
||||
* are not here to improve the legibility of the sample code. */
|
||||
uint32 fFrame;
|
||||
uint32 fFrameBase;
|
||||
bigtime_t fPerformanceTimeBase;
|
||||
bigtime_t fProcessingLatency;
|
||||
media_output fOutput;
|
||||
media_raw_video_format fConnectedFormat;
|
||||
bool fRunning;
|
||||
bool fConnected;
|
||||
bool fEnabled;
|
||||
|
||||
enum { P_COLOR };
|
||||
uint32 fColor;
|
||||
bigtime_t fLastColorChange;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
#include <support/Autolock.h>
|
||||
#include <media/MediaDefs.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <media/MediaAddOn.h>
|
||||
|
||||
#include "LegacyMediaAddOn.h"
|
||||
|
||||
#include "LegacyAudioConsumer.h"
|
||||
#include "LegacyAudioProducer.h"
|
||||
|
||||
|
||||
LegacyMediaAddOn::LegacyMediaAddOn( image_id imid )
|
||||
: BMediaAddOn( imid )
|
||||
{
|
||||
fInitStatus = B_NO_INIT;
|
||||
|
||||
consumer = new LegacyAudioConsumer( this, "ymf744/1", 0 );
|
||||
//producer = new LegacyAudioProducer( "maestro2/1" );
|
||||
|
||||
fInitStatus = B_OK;
|
||||
}
|
||||
|
||||
|
||||
LegacyMediaAddOn::~LegacyMediaAddOn()
|
||||
{
|
||||
delete consumer;
|
||||
//delete producer;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LegacyMediaAddOn::InitCheck( const char **out_failure_text )
|
||||
{
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
LegacyMediaAddOn::CountFlavors()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LegacyMediaAddOn::GetFlavorAt( int32 n, const flavor_info **out_info )
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
BMediaNode *
|
||||
LegacyMediaAddOn::InstantiateNodeFor( const flavor_info *info, BMessage *config, status_t *out_error )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
BMediaAddOn *
|
||||
make_media_addon( image_id imid )
|
||||
{
|
||||
return new LegacyMediaAddOn( imid );
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef _LEGACY_MEDIA_ADDON_H
|
||||
#define _LEGACY_MEDIA_ADDON_H
|
||||
|
||||
#include <media/MediaAddOn.h>
|
||||
|
||||
#include "LegacyAudioConsumer.h"
|
||||
//#include "LegacyAudioProducer.h"
|
||||
|
||||
|
||||
class LegacyMediaAddOn : public BMediaAddOn
|
||||
{
|
||||
public:
|
||||
LegacyMediaAddOn( image_id imid );
|
||||
virtual ~LegacyMediaAddOn();
|
||||
|
||||
virtual status_t InitCheck( const char **out_failure_text );
|
||||
|
||||
virtual int32 CountFlavors();
|
||||
virtual status_t GetFlavorAt( int32 n, const flavor_info **out_info );
|
||||
virtual BMediaNode *InstantiateNodeFor( const flavor_info *info, BMessage *config, status_t *out_error );
|
||||
|
||||
virtual status_t GetConfigurationFor( BMediaNode *node, BMessage *message )
|
||||
{ return B_ERROR; }
|
||||
virtual status_t SaveConfigInfo( BMediaNode *node, BMessage *message )
|
||||
{ return B_OK; }
|
||||
|
||||
virtual bool WantsAutoStart()
|
||||
{ return false; }
|
||||
virtual status_t AutoStart( int in_count, BMediaNode **out_node, int32 *out_internal_id, bool *out_has_more )
|
||||
{ return B_ERROR; }
|
||||
|
||||
private:
|
||||
status_t fInitStatus;
|
||||
|
||||
flavor_info fFlavorInfo;
|
||||
media_format fMediaFormat;
|
||||
|
||||
//BList *consumers;
|
||||
//BList *producers;
|
||||
|
||||
LegacyAudioConsumer *consumer;
|
||||
};
|
||||
|
||||
|
||||
extern "C" _EXPORT BMediaAddOn *make_media_addon( image_id you );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _DRIVER_IO_H
|
||||
#define _DRIVER_IO_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "driver/sound.h"
|
||||
|
||||
#define DRIVER_GET_PARAMS(x...) ioctl( fd, SOUND_GET_PARAMS, x )
|
||||
#define DRIVER_SET_PARAMS(x...) ioctl( fd, SOUND_SET_PARAMS, x )
|
||||
#define DRIVER_SET_PLAYBACK_COMPLETION_SEM(x...) ioctl( fd, SOUND_SET_PLAYBACK_COMPLETION_SEM, x )
|
||||
#define DRIVER_SET_CAPTURE_COMPLETION_SEM(x...) ioctl( fd, SOUND_SET_CAPTURE_COMPLETION_SEM, x )
|
||||
#define DRIVER_UNSAFE_WRITE(x...) ioctl( fd, SOUND_UNSAFE_WRITE, x )
|
||||
#define DRIVER_UNSAFE_READ(x...) ioctl( fd, SOUND_UNSAFE_READ, x )
|
||||
#define DRIVER_LOCK_FOR_DMA(x...) ioctl( fd, SOUND_LOCK_FOR_DMA, x )
|
||||
#define DRIVER_SET_CAPTURE_PREFERRED_BUF_SIZE(x...) ioctl( fd, SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE, x )
|
||||
#define DRIVER_SET_PLAYBACK_PREFERRED_BUF_SIZE(x...) ioctl( fd, SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE, x )
|
||||
#define DRIVER_GET_CAPTURE_PREFERRED_BUF_SIZE(x...) ioctl( fd, SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE, x )
|
||||
#define DRIVER_GET_PLAYBACK_PREFERRED_BUF_SIZE(x...) ioctl( fd, SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE, x )
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user