* More WIP cleanup and simplifications
* Fixed another memory leak in NodeRegistered() git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25938 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -29,7 +29,7 @@ const int gSupportedFormats[] = {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *gSupportedFormatsNames[] = {
|
const char* gSupportedFormatsNames[] = {
|
||||||
"raw", //AFMT_SUPPORTED_PCM,
|
"raw", //AFMT_SUPPORTED_PCM,
|
||||||
"µ-law", //AFMT_MU_LAW,
|
"µ-law", //AFMT_MU_LAW,
|
||||||
"a-law", //AFMT_A_LAW,
|
"a-law", //AFMT_A_LAW,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <MediaRoster.h>
|
#include <MediaRoster.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -29,24 +30,30 @@
|
|||||||
#include "OpenSoundDeviceEngine.h"
|
#include "OpenSoundDeviceEngine.h"
|
||||||
#include "OpenSoundDeviceMixer.h"
|
#include "OpenSoundDeviceMixer.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
|
||||||
class OpenSoundNode::NodeInput {
|
class OpenSoundNode::NodeInput {
|
||||||
public:
|
public:
|
||||||
NodeInput(const media_input& input, const media_format& format)
|
NodeInput(const media_input& input, int engineIndex, int ossFormatFlags,
|
||||||
: fNode(NULL),
|
OpenSoundNode* node)
|
||||||
fEngineIndex(-1),
|
: fNode(node),
|
||||||
|
fEngineIndex(engineIndex),
|
||||||
fRealEngine(NULL),
|
fRealEngine(NULL),
|
||||||
fOSSFormatFlags(0),
|
fOSSFormatFlags(ossFormatFlags),
|
||||||
|
|
||||||
fInput(input),
|
fInput(input),
|
||||||
fPreferredFormat(format),
|
fPreferredFormat(input.format),
|
||||||
|
// Keep a version of the original preferred format,
|
||||||
|
// in case we are re-connected and need to start "clean"
|
||||||
|
|
||||||
fThread(-1),
|
fThread(-1),
|
||||||
fBufferCycle(1),
|
|
||||||
|
|
||||||
fBuffers(4)
|
fBuffers(4)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
|
fInput.format.u.raw_audio.format
|
||||||
|
= media_raw_audio_format::wildcard.format;
|
||||||
}
|
}
|
||||||
|
|
||||||
~NodeInput()
|
~NodeInput()
|
||||||
@@ -102,7 +109,6 @@ public:
|
|||||||
media_format fPreferredFormat;
|
media_format fPreferredFormat;
|
||||||
|
|
||||||
thread_id fThread;
|
thread_id fThread;
|
||||||
uint32 fBufferCycle;
|
|
||||||
BList fBuffers;
|
BList fBuffers;
|
||||||
// contains BBuffer* pointers that have not yet played
|
// contains BBuffer* pointers that have not yet played
|
||||||
};
|
};
|
||||||
@@ -123,8 +129,7 @@ public:
|
|||||||
fBufferGroup(NULL),
|
fBufferGroup(NULL),
|
||||||
fOutputEnabled(true),
|
fOutputEnabled(true),
|
||||||
|
|
||||||
fSamplesSent(0),
|
fSamplesSent(0)
|
||||||
fBufferCycle(1)
|
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
}
|
}
|
||||||
@@ -184,7 +189,6 @@ public:
|
|||||||
BBufferGroup* fBufferGroup;
|
BBufferGroup* fBufferGroup;
|
||||||
bool fOutputEnabled;
|
bool fOutputEnabled;
|
||||||
uint64 fSamplesSent;
|
uint64 fSamplesSent;
|
||||||
volatile uint32 fBufferCycle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -331,8 +335,8 @@ OpenSoundNode::NodeRegistered()
|
|||||||
|
|
||||||
PRINT(("NodeRegistered: %d engines\n", fDevice->CountEngines()));
|
PRINT(("NodeRegistered: %d engines\n", fDevice->CountEngines()));
|
||||||
for (int32 i = 0; i < fDevice->CountEngines(); i++) {
|
for (int32 i = 0; i < fDevice->CountEngines(); i++) {
|
||||||
OpenSoundDeviceEngine *engine = fDevice->EngineAt(i);
|
OpenSoundDeviceEngine* engine = fDevice->EngineAt(i);
|
||||||
if (!engine)
|
if (engine == NULL)
|
||||||
continue;
|
continue;
|
||||||
// skip shadow engines
|
// skip shadow engines
|
||||||
if (engine->Caps() & PCM_CAP_SHADOW)
|
if (engine->Caps() & PCM_CAP_SHADOW)
|
||||||
@@ -344,46 +348,42 @@ OpenSoundNode::NodeRegistered()
|
|||||||
PRINT(("NodeRegistered: engine[%d]: .caps=0x%08x, .oformats=0x%08x\n",
|
PRINT(("NodeRegistered: engine[%d]: .caps=0x%08x, .oformats=0x%08x\n",
|
||||||
i, engine->Caps(), engine->Info()->oformats));
|
i, engine->Caps(), engine->Info()->oformats));
|
||||||
|
|
||||||
|
// iterate over all possible OSS formats/encodings and
|
||||||
|
// create a NodeInput for each
|
||||||
for (int32 f = 0; gSupportedFormats[f]; f++) {
|
for (int32 f = 0; gSupportedFormats[f]; f++) {
|
||||||
|
// figure out if the engine supports the given format
|
||||||
int fmt = gSupportedFormats[f] & engine->Info()->oformats;
|
int fmt = gSupportedFormats[f] & engine->Info()->oformats;
|
||||||
if (fmt == 0)
|
if (fmt == 0)
|
||||||
continue;
|
continue;
|
||||||
PRINT(("NodeRegistered() : creating an input for engine %i, "
|
PRINT(("NodeRegistered() : creating an input for engine %i, "
|
||||||
"format[%i]\n", i, f));
|
"format[%i]\n", i, f));
|
||||||
|
|
||||||
media_format preferredFormat;
|
media_input mediaInput;
|
||||||
status_t err = engine->PreferredFormatFor(fmt, preferredFormat);
|
status_t err = engine->PreferredFormatFor(fmt, mediaInput.format);
|
||||||
if (err < B_OK)
|
if (err < B_OK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
media_input input;
|
mediaInput.destination.port = ControlPort();
|
||||||
|
mediaInput.destination.id = fInputs.CountItems();
|
||||||
//input->format = fPreferredFormat;//XXX
|
mediaInput.node = Node();
|
||||||
input.format = preferredFormat;
|
|
||||||
input.destination.port = ControlPort();
|
|
||||||
input.destination.id = fInputs.CountItems();
|
|
||||||
input.node = Node();
|
|
||||||
char *prefix = "";
|
char *prefix = "";
|
||||||
if (strstr(engine->Info()->name, "SPDIF"))
|
if (strstr(engine->Info()->name, "SPDIF"))
|
||||||
prefix = "S/PDIF ";
|
prefix = "S/PDIF ";
|
||||||
sprintf(input.name, "%s%s output %ld", prefix,
|
sprintf(mediaInput.name, "%sOutput %ld (%s)", prefix,
|
||||||
gSupportedFormatsNames[f], input.destination.id);
|
mediaInput.destination.id, gSupportedFormatsNames[f]);
|
||||||
|
|
||||||
NodeInput* currentInput = new NodeInput(input, preferredFormat);
|
NodeInput* input = new (nothrow) NodeInput(mediaInput, i, fmt,
|
||||||
currentInput->fInput.format = currentInput->fPreferredFormat;
|
this);
|
||||||
currentInput->fEngineIndex = i;
|
if (input == NULL || !fInputs.AddItem(input)) {
|
||||||
currentInput->fOSSFormatFlags = fmt;
|
delete input;
|
||||||
currentInput->fNode = this;
|
continue;
|
||||||
fInputs.AddItem(currentInput);
|
}
|
||||||
|
|
||||||
currentInput->fInput.format.u.raw_audio.format
|
|
||||||
= media_raw_audio_format::wildcard.format;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32 i = 0; i < fDevice->CountEngines(); i++) {
|
for (int32 i = 0; i < fDevice->CountEngines(); i++) {
|
||||||
OpenSoundDeviceEngine *engine = fDevice->EngineAt(i);
|
OpenSoundDeviceEngine* engine = fDevice->EngineAt(i);
|
||||||
if (!engine)
|
if (engine == NULL)
|
||||||
continue;
|
continue;
|
||||||
// skip shadow engines
|
// skip shadow engines
|
||||||
if (engine->Caps() & PCM_CAP_SHADOW)
|
if (engine->Caps() & PCM_CAP_SHADOW)
|
||||||
@@ -407,52 +407,56 @@ OpenSoundNode::NodeRegistered()
|
|||||||
if (err < B_OK)
|
if (err < B_OK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
media_output *output = new media_output;
|
media_output mediaOutput;
|
||||||
|
|
||||||
//output->format = fPreferredFormat; //XXX
|
mediaOutput.format = preferredFormat;
|
||||||
output->format = preferredFormat;
|
mediaOutput.destination = media_destination::null;
|
||||||
output->destination = media_destination::null;
|
mediaOutput.source.port = ControlPort();
|
||||||
output->source.port = ControlPort();
|
mediaOutput.source.id = fOutputs.CountItems();
|
||||||
output->source.id = fOutputs.CountItems();
|
mediaOutput.node = Node();
|
||||||
output->node = Node();
|
|
||||||
char *prefix = "";
|
char *prefix = "";
|
||||||
if (strstr(engine->Info()->name, "SPDIF"))
|
if (strstr(engine->Info()->name, "SPDIF"))
|
||||||
prefix = "S/PDIF ";
|
prefix = "S/PDIF ";
|
||||||
sprintf(output->name, "%s%s input %ld", prefix,
|
sprintf(mediaOutput.name, "%sInput %ld (%s)", prefix,
|
||||||
gSupportedFormatsNames[f], output->source.id);
|
mediaOutput.source.id, gSupportedFormatsNames[f]);
|
||||||
|
|
||||||
NodeOutput* currentOutput = new NodeOutput(*output,
|
NodeOutput* output = new (nothrow) NodeOutput(mediaOutput,
|
||||||
preferredFormat);
|
preferredFormat);
|
||||||
// currentOutput->fPreferredFormat.u.raw_audio.channel_count
|
if (output == NULL || !fOutputs.AddItem(output)) {
|
||||||
|
delete output;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// output->fPreferredFormat.u.raw_audio.channel_count
|
||||||
// = engine->Info()->max_channels;
|
// = engine->Info()->max_channels;
|
||||||
currentOutput->fOutput.format = currentOutput->fPreferredFormat;
|
output->fOutput.format = output->fPreferredFormat;
|
||||||
currentOutput->fEngineIndex = i;
|
output->fEngineIndex = i;
|
||||||
currentOutput->fOSSFormatFlags = fmt;
|
output->fOSSFormatFlags = fmt;
|
||||||
currentOutput->fNode = this;
|
output->fNode = this;
|
||||||
fOutputs.AddItem(currentOutput);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up our parameter web
|
// set up our parameter web
|
||||||
fWeb = MakeParameterWeb();
|
fWeb = MakeParameterWeb();
|
||||||
SetParameterWeb(fWeb);
|
SetParameterWeb(fWeb);
|
||||||
|
|
||||||
/* apply configuration */
|
// apply configuration
|
||||||
#ifdef PRINTING
|
#ifdef PRINTING
|
||||||
bigtime_t start = system_time();
|
bigtime_t start = system_time();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 parameterID = 0;
|
int32 parameterID = 0;
|
||||||
const void *data;
|
while (fConfig.FindInt32("parameterID", index, ¶meterID) == B_OK) {
|
||||||
ssize_t size;
|
const void* data;
|
||||||
while(fConfig.FindInt32("parameterID", index, ¶meterID) == B_OK) {
|
ssize_t size;
|
||||||
if(fConfig.FindData("parameterData", B_RAW_TYPE, index, &data, &size) == B_OK)
|
if (fConfig.FindData("parameterData", B_RAW_TYPE, index, &data,
|
||||||
|
&size) == B_OK) {
|
||||||
SetParameterValue(parameterID, TimeSource()->Now(), data, size);
|
SetParameterValue(parameterID, TimeSource()->Now(), data, size);
|
||||||
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINT(("apply configuration in : %ld\n", system_time() - start));
|
PRINT(("apply configuration in : %lldµs\n", system_time() - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -474,6 +478,10 @@ OpenSoundNode::SetTimeSource(BTimeSource* timeSource)
|
|||||||
// #pragma mark - BBufferConsumer
|
// #pragma mark - BBufferConsumer
|
||||||
|
|
||||||
|
|
||||||
|
//! Someone, probably the producer, is asking you about this format.
|
||||||
|
// Give your honest opinion, possibly modifying *format. Do not ask
|
||||||
|
// upstream producer about the format, since he's synchronously
|
||||||
|
// waiting for your reply.
|
||||||
status_t
|
status_t
|
||||||
OpenSoundNode::AcceptFormat(const media_destination& dest,
|
OpenSoundNode::AcceptFormat(const media_destination& dest,
|
||||||
media_format* format)
|
media_format* format)
|
||||||
@@ -486,15 +494,17 @@ OpenSoundNode::AcceptFormat(const media_destination& dest,
|
|||||||
NodeInput* channel = _FindInput(dest);
|
NodeInput* channel = _FindInput(dest);
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION");
|
fprintf(stderr, "OpenSoundNode::AcceptFormat()"
|
||||||
|
" - B_MEDIA_BAD_DESTINATION");
|
||||||
return B_MEDIA_BAD_DESTINATION;
|
return B_MEDIA_BAD_DESTINATION;
|
||||||
// we only have one input so that better be it
|
// we only have one input so that better be it
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format == 0) {
|
if (format == NULL) {
|
||||||
fprintf(stderr,"<- B_BAD_VALUE\n");
|
fprintf(stderr, "OpenSoundNode::AcceptFormat() - B_BAD_VALUE\n");
|
||||||
return B_BAD_VALUE; // no crashing
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* media_format * myFormat = GetFormat();
|
/* media_format * myFormat = GetFormat();
|
||||||
fprintf(stderr,"proposed format: ");
|
fprintf(stderr,"proposed format: ");
|
||||||
print_media_format(format);
|
print_media_format(format);
|
||||||
@@ -512,7 +522,8 @@ OpenSoundNode::AcceptFormat(const media_destination& dest,
|
|||||||
if (!engine)
|
if (!engine)
|
||||||
return B_BUSY;
|
return B_BUSY;
|
||||||
|
|
||||||
status_t err = engine->AcceptFormatFor(channel->fOSSFormatFlags, *format, false);
|
status_t err = engine->AcceptFormatFor(channel->fOSSFormatFlags, *format,
|
||||||
|
false);
|
||||||
if (err < B_OK)
|
if (err < B_OK)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -529,179 +540,221 @@ OpenSoundNode::AcceptFormat(const media_destination& dest,
|
|||||||
channel->fInput.format = *format;
|
channel->fInput.format = *format;
|
||||||
|
|
||||||
/*if(format->u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT
|
/*if(format->u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT
|
||||||
&& channel->fPreferredFormat.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT)
|
&& channel->fPreferredFormat.u.raw_audio.format
|
||||||
|
== media_raw_audio_format::B_AUDIO_SHORT)
|
||||||
format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||||
else*/
|
else*/
|
||||||
/*
|
/*
|
||||||
format->u.raw_audio.format = channel->fPreferredFormat.u.raw_audio.format;
|
format->u.raw_audio.format = channel->fPreferredFormat.u.raw_audio.format;
|
||||||
format->u.raw_audio.valid_bits = channel->fPreferredFormat.u.raw_audio.valid_bits;
|
format->u.raw_audio.valid_bits
|
||||||
|
= channel->fPreferredFormat.u.raw_audio.valid_bits;
|
||||||
|
|
||||||
format->u.raw_audio.frame_rate = channel->fPreferredFormat.u.raw_audio.frame_rate;
|
format->u.raw_audio.frame_rate
|
||||||
format->u.raw_audio.channel_count = channel->fPreferredFormat.u.raw_audio.channel_count;
|
= channel->fPreferredFormat.u.raw_audio.frame_rate;
|
||||||
format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
|
format->u.raw_audio.channel_count
|
||||||
|
= channel->fPreferredFormat.u.raw_audio.channel_count;
|
||||||
|
format->u.raw_audio.byte_order
|
||||||
|
= B_MEDIA_HOST_ENDIAN;
|
||||||
|
|
||||||
format->u.raw_audio.buffer_size = DEFAULT_BUFFER_SIZE
|
format->u.raw_audio.buffer_size
|
||||||
* (format->u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
|
= DEFAULT_BUFFER_SIZE
|
||||||
* format->u.raw_audio.channel_count;
|
* (format->u.raw_audio.format
|
||||||
*/
|
& media_raw_audio_format::B_AUDIO_SIZE_MASK)
|
||||||
|
* format->u.raw_audio.channel_count;
|
||||||
|
*/
|
||||||
|
|
||||||
/*media_format myFormat;
|
// media_format myFormat;
|
||||||
GetFormat(&myFormat);
|
// GetFormat(&myFormat);
|
||||||
if (!format_is_acceptible(*format,myFormat)) {
|
// if (!format_is_acceptible(*format,myFormat)) {
|
||||||
fprintf(stderr,"<- B_MEDIA_BAD_FORMAT\n");
|
// fprintf(stderr,"<- B_MEDIA_BAD_FORMAT\n");
|
||||||
return B_MEDIA_BAD_FORMAT;
|
// return B_MEDIA_BAD_FORMAT;
|
||||||
}*/
|
// }
|
||||||
//AddRequirements(format);
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t OpenSoundNode::GetNextInput(
|
|
||||||
int32 * cookie,
|
status_t
|
||||||
media_input * out_input)
|
OpenSoundNode::GetNextInput(int32* cookie, media_input* out_input)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
// let's not crash even if they are stupid
|
// let's not crash even if they are stupid
|
||||||
if (out_input == 0) {
|
if (out_input == NULL) {
|
||||||
// no place to write!
|
// no place to write!
|
||||||
fprintf(stderr,"<- B_BAD_VALUE\n");
|
fprintf(stderr,"OpenSoundNode::GetNextInput() - B_BAD_VALUE\n");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*cookie < fInputs.CountItems()) && (*cookie >= 0)) {
|
if (*cookie >= fInputs.CountItems() || *cookie < 0)
|
||||||
NodeInput *channel = (NodeInput *)fInputs.ItemAt(*cookie);
|
|
||||||
*out_input = channel->fInput;
|
|
||||||
*cookie += 1;
|
|
||||||
PRINT(("input.format : %u\n", channel->fInput.format.u.raw_audio.format));
|
|
||||||
return B_OK;
|
|
||||||
} else
|
|
||||||
return B_BAD_INDEX;
|
return B_BAD_INDEX;
|
||||||
|
|
||||||
|
NodeInput* channel = (NodeInput*)fInputs.ItemAt(*cookie);
|
||||||
|
*out_input = channel->fInput;
|
||||||
|
*cookie += 1;
|
||||||
|
|
||||||
|
PRINT(("input.format : %u\n", channel->fInput.format.u.raw_audio.format));
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSoundNode::DisposeInputCookie(
|
|
||||||
int32 cookie)
|
void
|
||||||
|
OpenSoundNode::DisposeInputCookie(int32 cookie)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
// nothing to do since our cookies are just integers
|
// nothing to do since our cookies are just integers
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSoundNode::BufferReceived(
|
|
||||||
BBuffer * buffer)
|
void
|
||||||
|
OpenSoundNode::BufferReceived(BBuffer* buffer)
|
||||||
{
|
{
|
||||||
/**/CALLED();
|
CALLED();
|
||||||
|
|
||||||
switch (buffer->Header()->type) {
|
switch (buffer->Header()->type) {
|
||||||
/*case B_MEDIA_PARAMETERS:
|
// case B_MEDIA_PARAMETERS:
|
||||||
{
|
// {
|
||||||
status_t status = ApplyParameterData(buffer->Data(),buffer->SizeUsed());
|
// status_t status = ApplyParameterData(buffer->Data(),
|
||||||
if (status != B_OK) {
|
// buffer->SizeUsed());
|
||||||
fprintf(stderr,"ApplyParameterData in OpenSoundNode::BufferReceived failed\n");
|
// if (status != B_OK) {
|
||||||
}
|
// fprintf(stderr, "ApplyParameterData() in "
|
||||||
buffer->Recycle();
|
// "OpenSoundNode::BufferReceived() failed: %s\n",
|
||||||
}
|
// strerror(status));
|
||||||
break;*/
|
// }
|
||||||
|
// buffer->Recycle();
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
case B_MEDIA_RAW_AUDIO:
|
case B_MEDIA_RAW_AUDIO:
|
||||||
if (buffer->Flags() & BBuffer::B_SMALL_BUFFER) {
|
if (buffer->Flags() & BBuffer::B_SMALL_BUFFER) {
|
||||||
fprintf(stderr,"NOT IMPLEMENTED: B_SMALL_BUFFER in OpenSoundNode::BufferReceived\n");
|
fprintf(stderr, "OpenSoundNode::BufferReceived() - "
|
||||||
|
"B_SMALL_BUFFER not implemented\n");
|
||||||
// XXX: implement this part
|
// XXX: implement this part
|
||||||
buffer->Recycle();
|
buffer->Recycle();
|
||||||
} else {
|
} else {
|
||||||
media_timed_event event(buffer->Header()->start_time, BTimedEventQueue::B_HANDLE_BUFFER,
|
media_timed_event event(buffer->Header()->start_time,
|
||||||
buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
|
BTimedEventQueue::B_HANDLE_BUFFER, buffer,
|
||||||
|
BTimedEventQueue::B_RECYCLE_BUFFER);
|
||||||
status_t status = EventQueue()->AddEvent(event);
|
status_t status = EventQueue()->AddEvent(event);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
fprintf(stderr,"EventQueue()->AddEvent(event) in OpenSoundNode::BufferReceived failed\n");
|
fprintf(stderr, "OpenSoundNode::BufferReceived() - "
|
||||||
|
"EventQueue()->AddEvent() failed: %s\n",
|
||||||
|
strerror(status));
|
||||||
buffer->Recycle();
|
buffer->Recycle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"unexpected buffer type in OpenSoundNode::BufferReceived\n");
|
fprintf(stderr, "OpenSoundNode::BufferReceived() - unexpected "
|
||||||
|
"buffer type\n");
|
||||||
buffer->Recycle();
|
buffer->Recycle();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSoundNode::ProducerDataStatus(
|
|
||||||
const media_destination & for_whom,
|
void
|
||||||
int32 status,
|
OpenSoundNode::ProducerDataStatus(const media_destination& for_whom,
|
||||||
bigtime_t at_performance_time)
|
int32 status, bigtime_t at_performance_time)
|
||||||
{
|
{
|
||||||
/**/CALLED();
|
CALLED();
|
||||||
|
|
||||||
NodeInput *channel = _FindInput(for_whom);
|
NodeInput* channel = _FindInput(for_whom);
|
||||||
|
|
||||||
if(channel==NULL) {
|
if (channel == NULL) {
|
||||||
fprintf(stderr,"invalid destination received in OpenSoundNode::ProducerDataStatus\n");
|
fprintf(stderr,"OpenSoundNode::ProducerDataStatus() - "
|
||||||
|
"invalid destination\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//PRINT(("************ ProducerDataStatus: queuing event ************\n"));
|
// PRINT(("************ ProducerDataStatus: queuing event ************\n"));
|
||||||
//PRINT(("************ status=%d ************\n", status));
|
// PRINT(("************ status=%d ************\n", status));
|
||||||
|
|
||||||
media_timed_event event(at_performance_time, BTimedEventQueue::B_DATA_STATUS,
|
media_timed_event event(at_performance_time,
|
||||||
&channel->fInput, BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
|
BTimedEventQueue::B_DATA_STATUS, &channel->fInput,
|
||||||
|
BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
|
||||||
EventQueue()->AddEvent(event);
|
EventQueue()->AddEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t OpenSoundNode::GetLatencyFor(
|
|
||||||
const media_destination & for_whom,
|
status_t
|
||||||
bigtime_t * out_latency,
|
OpenSoundNode::GetLatencyFor(const media_destination& for_whom,
|
||||||
media_node_id * out_timesource)
|
bigtime_t* out_latency, media_node_id* out_timesource)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
if ((out_latency == 0) || (out_timesource == 0)) {
|
|
||||||
fprintf(stderr,"<- B_BAD_VALUE\n");
|
if (out_latency == NULL || out_timesource == NULL) {
|
||||||
|
fprintf(stderr,"OpenSoundNode::GetLatencyFor() - B_BAD_VALUE\n");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInput *channel = _FindInput(for_whom);
|
NodeInput* channel = _FindInput(for_whom);
|
||||||
|
|
||||||
if(channel==NULL || channel->fRealEngine==NULL) {
|
if (channel == NULL || channel->fRealEngine == NULL) {
|
||||||
fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
|
fprintf(stderr,"OpenSoundNode::GetLatencyFor() - "
|
||||||
|
"B_MEDIA_BAD_DESTINATION\n");
|
||||||
return B_MEDIA_BAD_DESTINATION;
|
return B_MEDIA_BAD_DESTINATION;
|
||||||
}
|
}
|
||||||
*out_latency = EventLatency(); // mmu_man: that's the own node latency (1 buffer)
|
|
||||||
|
// start with the node latency (1 buffer duration)
|
||||||
|
*out_latency = EventLatency();
|
||||||
|
|
||||||
// add the OSS driver buffer's latency as well
|
// add the OSS driver buffer's latency as well
|
||||||
*out_latency += channel->fRealEngine->PlaybackLatency();
|
*out_latency += channel->fRealEngine->PlaybackLatency();
|
||||||
PRINT(("############ OpenSoundNode::%s: EventLatency %Ld, OSS %Ld\n", __FUNCTION__, EventLatency(), channel->fRealEngine->PlaybackLatency()));
|
|
||||||
//*out_latency += MIN_SNOOZING;
|
PRINT(("OpenSoundNode::GetLatencyFor() - EventLatency %lld, OSS %lld\n",
|
||||||
|
EventLatency(), channel->fRealEngine->PlaybackLatency()));
|
||||||
|
|
||||||
*out_timesource = TimeSource()->ID();
|
*out_timesource = TimeSource()->ID();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t OpenSoundNode::Connected(
|
|
||||||
const media_source & producer, /* here's a good place to request buffer group usage */
|
status_t
|
||||||
const media_destination & where,
|
OpenSoundNode::Connected(const media_source& producer,
|
||||||
const media_format & with_format,
|
const media_destination& where, const media_format& with_format,
|
||||||
media_input * out_input)
|
media_input* out_input)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
if (out_input == 0) {
|
|
||||||
fprintf(stderr,"<- B_BAD_VALUE\n");
|
if (out_input == NULL) {
|
||||||
return B_BAD_VALUE; // no crashing
|
fprintf(stderr,"OpenSoundNode::Connected() - B_BAD_VALUE\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInput *channel = _FindInput(where);
|
NodeInput *channel = _FindInput(where);
|
||||||
|
|
||||||
if(channel==NULL) {
|
if (channel == NULL) {
|
||||||
fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
|
fprintf(stderr,"OpenSoundNode::Connected() - "
|
||||||
|
"B_MEDIA_BAD_DESTINATION\n");
|
||||||
return B_MEDIA_BAD_DESTINATION;
|
return B_MEDIA_BAD_DESTINATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAutolock L(fDevice->Locker());
|
BAutolock L(fDevice->Locker());
|
||||||
|
|
||||||
// use one buffer length latency
|
// use one buffer length latency
|
||||||
fInternalLatency = with_format.u.raw_audio.buffer_size * 10000 / 2
|
size_t bufferSize = with_format.u.raw_audio.buffer_size;
|
||||||
/ ( (with_format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
|
int32 channelCount = with_format.u.raw_audio.channel_count;
|
||||||
* with_format.u.raw_audio.channel_count)
|
size_t sampleSize = with_format.u.raw_audio.format
|
||||||
/ ((int32)(with_format.u.raw_audio.frame_rate / 100));
|
& media_raw_audio_format::B_AUDIO_SIZE_MASK;
|
||||||
|
size_t frameSize = sampleSize * channelCount;
|
||||||
|
float frameRate = with_format.u.raw_audio.frame_rate;
|
||||||
|
|
||||||
|
fInternalLatency = bufferSize * 10000 / 2
|
||||||
|
/ frameSize / (int32)(frameRate / 100);
|
||||||
|
|
||||||
PRINT((" internal latency = %lld\n",fInternalLatency));
|
PRINT((" internal latency = %lld\n", fInternalLatency));
|
||||||
//fInternalLatency = 0;
|
|
||||||
|
// TODO: A global node value is assigned a channel specific value!
|
||||||
|
// That can't be correct. For as long as there is only one output
|
||||||
|
// in use at a time, this will not matter of course.
|
||||||
SetEventLatency(fInternalLatency);
|
SetEventLatency(fInternalLatency);
|
||||||
|
|
||||||
// record the agreed upon values
|
// record the agreed upon values
|
||||||
channel->fInput.source = producer;
|
channel->fInput.source = producer;
|
||||||
channel->fInput.format = with_format;
|
channel->fInput.format = with_format;
|
||||||
|
|
||||||
*out_input = channel->fInput;
|
*out_input = channel->fInput;
|
||||||
|
|
||||||
// we are sure the thread is started
|
// we are sure the thread is started
|
||||||
@@ -2479,7 +2532,7 @@ int32
|
|||||||
OpenSoundNode::_PlayThreadEntry(void* data)
|
OpenSoundNode::_PlayThreadEntry(void* data)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
NodeInput *channel = static_cast<NodeInput*>(data);
|
NodeInput* channel = static_cast<NodeInput*>(data);
|
||||||
return channel->fNode->_PlayThread(channel);
|
return channel->fNode->_PlayThread(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2488,7 +2541,7 @@ int32
|
|||||||
OpenSoundNode::_RecThreadEntry(void* data)
|
OpenSoundNode::_RecThreadEntry(void* data)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
NodeOutput *channel = static_cast<NodeOutput *>(data);
|
NodeOutput* channel = static_cast<NodeOutput*>(data);
|
||||||
return channel->fNode->_RecThread(channel);
|
return channel->fNode->_RecThread(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,10 +72,6 @@ protected:
|
|||||||
virtual status_t AcceptFormat(
|
virtual status_t AcceptFormat(
|
||||||
const media_destination& dest,
|
const media_destination& dest,
|
||||||
media_format* format);
|
media_format* format);
|
||||||
// Someone, probably the producer, is asking you about this format.
|
|
||||||
// Give your honest opinion, possibly modifying *format. Do not ask
|
|
||||||
// upstream producer about the format, since he's synchronously
|
|
||||||
// waiting for your reply.
|
|
||||||
virtual status_t GetNextInput(int32* cookie,
|
virtual status_t GetNextInput(int32* cookie,
|
||||||
media_input* out_input);
|
media_input* out_input);
|
||||||
virtual void DisposeInputCookie(int32 cookie);
|
virtual void DisposeInputCookie(int32 cookie);
|
||||||
|
|||||||
Reference in New Issue
Block a user