Use the system mixer instead of trying to instanciate another one in the game kit. This allows to use the game kit class in an hybrid way, and closes #7351.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43127 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4a586de04d
commit
d3fdcc312a
@ -101,12 +101,13 @@ GameSoundBuffer::~GameSoundBuffer()
|
|||||||
BMediaRoster* roster = BMediaRoster::Roster();
|
BMediaRoster* roster = BMediaRoster::Roster();
|
||||||
|
|
||||||
if (fIsConnected) {
|
if (fIsConnected) {
|
||||||
// Ordinarily we'd stop *all* of the nodes in the chain at this point. However,
|
// Ordinarily we'd stop *all* of the nodes in the chain at this point.
|
||||||
// one of the nodes is the System Mixer, and stopping the Mixer is a Bad Idea (tm).
|
// However, one of the nodes is the System Mixer, and stopping the Mixer
|
||||||
// So, we just disconnect from it, and release our references to the nodes that
|
// is a Bad Idea (tm). So, we just disconnect from it, and release our
|
||||||
// we're using. We *are* supposed to do that even for global nodes like the Mixer.
|
// references to the nodes that we're using. We *are* supposed to do
|
||||||
|
// that even for global nodes like the Mixer.
|
||||||
roster->Disconnect(fConnection->producer.node, fConnection->source,
|
roster->Disconnect(fConnection->producer.node, fConnection->source,
|
||||||
fConnection->consumer.node, fConnection->destination);
|
fConnection->consumer.node, fConnection->destination);
|
||||||
|
|
||||||
roster->ReleaseNode(fConnection->producer);
|
roster->ReleaseNode(fConnection->producer);
|
||||||
roster->ReleaseNode(fConnection->consumer);
|
roster->ReleaseNode(fConnection->consumer);
|
||||||
@ -390,9 +391,10 @@ GameSoundBuffer::Connect(media_node * consumer)
|
|||||||
if (err != B_OK)
|
if (err != B_OK)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = roster->SetTimeSourceFor(fConnection->producer.node, fConnection->timeSource.node);
|
err = roster->SetTimeSourceFor(fConnection->producer.node,
|
||||||
if (err != B_OK)
|
fConnection->timeSource.node);
|
||||||
return err;
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
// got the nodes; now we find the endpoints of the connection
|
// got the nodes; now we find the endpoints of the connection
|
||||||
media_input mixerInput;
|
media_input mixerInput;
|
||||||
media_output soundOutput;
|
media_output soundOutput;
|
||||||
|
@ -85,10 +85,9 @@ BGameSoundDevice::BGameSoundDevice()
|
|||||||
fIsConnected(false),
|
fIsConnected(false),
|
||||||
fSoundCount(kInitSoundCount)
|
fSoundCount(kInitSoundCount)
|
||||||
{
|
{
|
||||||
fConnection = new Connection;
|
|
||||||
memset(&fFormat, 0, sizeof(gs_audio_format));
|
memset(&fFormat, 0, sizeof(gs_audio_format));
|
||||||
|
|
||||||
fInitError = Connect();
|
fInitError = B_OK;
|
||||||
|
|
||||||
fSounds = new GameSoundBuffer*[kInitSoundCount];
|
fSounds = new GameSoundBuffer*[kInitSoundCount];
|
||||||
for (int32 i = 0; i < kInitSoundCount; i++)
|
for (int32 i = 0; i < kInitSoundCount; i++)
|
||||||
@ -98,8 +97,6 @@ BGameSoundDevice::BGameSoundDevice()
|
|||||||
|
|
||||||
BGameSoundDevice::~BGameSoundDevice()
|
BGameSoundDevice::~BGameSoundDevice()
|
||||||
{
|
{
|
||||||
BMediaRoster* roster = BMediaRoster::Roster();
|
|
||||||
|
|
||||||
// We need to stop all the sounds before we stop the mixer
|
// We need to stop all the sounds before we stop the mixer
|
||||||
for (int32 i = 0; i < fSoundCount; i++) {
|
for (int32 i = 0; i < fSoundCount; i++) {
|
||||||
if (fSounds[i])
|
if (fSounds[i])
|
||||||
@ -107,25 +104,7 @@ BGameSoundDevice::~BGameSoundDevice()
|
|||||||
delete fSounds[i];
|
delete fSounds[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fIsConnected) {
|
|
||||||
// stop the nodes if they are running
|
|
||||||
roster->StopNode(fConnection->producer, 0, true);
|
|
||||||
// synchronous stop
|
|
||||||
|
|
||||||
// Ordinarily we'd stop *all* of the nodes in the chain at this point.
|
|
||||||
// However, one of the nodes is the System Mixer, and stopping the
|
|
||||||
// Mixer is a Bad Idea (tm). So, we just disconnect from it, and
|
|
||||||
// release our references to the nodes that we're using. We *are*
|
|
||||||
// supposed to do that even for global nodes like the Mixer.
|
|
||||||
roster->Disconnect(fConnection->producer.node, fConnection->source,
|
|
||||||
fConnection->consumer.node, fConnection->destination);
|
|
||||||
|
|
||||||
roster->ReleaseNode(fConnection->producer);
|
|
||||||
roster->ReleaseNode(fConnection->consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] fSounds;
|
delete[] fSounds;
|
||||||
delete fConnection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -168,8 +147,10 @@ BGameSoundDevice::CreateBuffer(gs_id* sound, const gs_audio_format* format,
|
|||||||
int32 position = AllocateSound();
|
int32 position = AllocateSound();
|
||||||
|
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
|
media_node systemMixer;
|
||||||
|
BMediaRoster::Roster()->GetAudioMixer(&systemMixer);
|
||||||
fSounds[position] = new SimpleSoundBuffer(format, data, frames);
|
fSounds[position] = new SimpleSoundBuffer(format, data, frames);
|
||||||
err = fSounds[position]->Connect(&fConnection->producer);
|
err = fSounds[position]->Connect(&systemMixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == B_OK)
|
if (err == B_OK)
|
||||||
@ -189,8 +170,10 @@ BGameSoundDevice::CreateBuffer(gs_id* sound, const void* object,
|
|||||||
int32 position = AllocateSound();
|
int32 position = AllocateSound();
|
||||||
|
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
|
media_node systemMixer;
|
||||||
|
BMediaRoster::Roster()->GetAudioMixer(&systemMixer);
|
||||||
fSounds[position] = new StreamingSoundBuffer(format, object);
|
fSounds[position] = new StreamingSoundBuffer(format, object);
|
||||||
err = fSounds[position]->Connect(&fConnection->producer);
|
err = fSounds[position]->Connect(&systemMixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == B_OK)
|
if (err == B_OK)
|
||||||
@ -296,100 +279,6 @@ BGameSoundDevice::SetAttributes(gs_id sound, gs_attribute* attributes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BGameSoundDevice::Connect()
|
|
||||||
{
|
|
||||||
BMediaRoster* roster = BMediaRoster::Roster();
|
|
||||||
|
|
||||||
// create your own audio mixer
|
|
||||||
// TODO: Don't do this!!! See bug #575
|
|
||||||
// from #575.
|
|
||||||
// marcusoverhagen : tries to instantiate a new audio mixer, which is bad.
|
|
||||||
// It should use the system mixer.
|
|
||||||
dormant_node_info mixer_dormant_info;
|
|
||||||
int32 mixer_count = 1; // for now, we only care about the first we find.
|
|
||||||
status_t err = roster->GetDormantNodes(&mixer_dormant_info,
|
|
||||||
&mixer_count, 0, 0, 0, B_SYSTEM_MIXER, 0);
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
//fMixer = new media_node;
|
|
||||||
err = roster->InstantiateDormantNode(mixer_dormant_info,
|
|
||||||
&fConnection->producer);
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
// retieve the system's audio mixer
|
|
||||||
err = roster->GetAudioMixer(&fConnection->consumer);
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
int32 count = 1;
|
|
||||||
media_input mixerInput;
|
|
||||||
err = roster->GetFreeInputsFor(fConnection->consumer, &mixerInput, 1,
|
|
||||||
&count);
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
count = 1;
|
|
||||||
media_output mixerOutput;
|
|
||||||
err = roster->GetFreeOutputsFor(fConnection->producer, &mixerOutput, 1,
|
|
||||||
&count);
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
media_format format(mixerOutput.format);
|
|
||||||
err = roster->Connect(mixerOutput.source, mixerInput.destination,
|
|
||||||
&format, &mixerOutput, &mixerInput);
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
// set the producer's time source to be the "default" time source, which
|
|
||||||
// the Mixer uses too.
|
|
||||||
roster->GetTimeSource(&fConnection->timeSource);
|
|
||||||
roster->SetTimeSourceFor(fConnection->producer.node,
|
|
||||||
fConnection->timeSource.node);
|
|
||||||
|
|
||||||
// Start our mixer's time source if need be. Chances are, it won't need to
|
|
||||||
// be, but if we forget to do this, our mixer might not do anything at all.
|
|
||||||
BTimeSource* mixerTimeSource = roster->MakeTimeSourceFor(
|
|
||||||
fConnection->producer);
|
|
||||||
if (!mixerTimeSource)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
if (!mixerTimeSource->IsRunning()) {
|
|
||||||
status_t err = roster->StartNode(mixerTimeSource->Node(),
|
|
||||||
BTimeSource::RealTime());
|
|
||||||
if (err != B_OK) {
|
|
||||||
mixerTimeSource->Release();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start up our mixer
|
|
||||||
bigtime_t tpNow = mixerTimeSource->Now();
|
|
||||||
err = roster->StartNode(fConnection->producer, tpNow + 10000);
|
|
||||||
mixerTimeSource->Release();
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
// the inputs and outputs might have been reassigned during the
|
|
||||||
// nodes' negotiation of the Connect(). That's why we wait until
|
|
||||||
// after Connect() finishes to save their contents.
|
|
||||||
fConnection->format = format;
|
|
||||||
fConnection->source = mixerOutput.source;
|
|
||||||
fConnection->destination = mixerInput.destination;
|
|
||||||
|
|
||||||
// Set an appropriate run mode for the producer
|
|
||||||
roster->SetRunModeNode(fConnection->producer,
|
|
||||||
BMediaNode::B_INCREASE_LATENCY);
|
|
||||||
|
|
||||||
media_to_gs_format(&fFormat, &format.u.raw_audio);
|
|
||||||
fIsConnected = true;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BGameSoundDevice::AllocateSound()
|
BGameSoundDevice::AllocateSound()
|
||||||
{
|
{
|
||||||
|
@ -38,48 +38,46 @@ struct Connection;
|
|||||||
|
|
||||||
class BGameSoundDevice {
|
class BGameSoundDevice {
|
||||||
public:
|
public:
|
||||||
BGameSoundDevice();
|
BGameSoundDevice();
|
||||||
virtual ~BGameSoundDevice();
|
virtual ~BGameSoundDevice();
|
||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
virtual const gs_audio_format & Format() const;
|
virtual const gs_audio_format & Format() const;
|
||||||
virtual const gs_audio_format & Format(gs_id sound) const;
|
virtual const gs_audio_format & Format(gs_id sound) const;
|
||||||
|
|
||||||
virtual status_t CreateBuffer(gs_id * sound,
|
virtual status_t CreateBuffer(gs_id * sound,
|
||||||
const gs_audio_format * format,
|
const gs_audio_format * format,
|
||||||
const void * data,
|
const void * data,
|
||||||
int64 frames);
|
int64 frames);
|
||||||
virtual status_t CreateBuffer(gs_id * sound,
|
virtual status_t CreateBuffer(gs_id * sound,
|
||||||
const void * object,
|
const void * object,
|
||||||
const gs_audio_format * format);
|
const gs_audio_format * format);
|
||||||
virtual void ReleaseBuffer(gs_id sound);
|
virtual void ReleaseBuffer(gs_id sound);
|
||||||
|
|
||||||
virtual status_t Buffer(gs_id sound,
|
virtual status_t Buffer(gs_id sound,
|
||||||
gs_audio_format * format,
|
gs_audio_format * format,
|
||||||
void *& data);
|
void *& data);
|
||||||
|
|
||||||
virtual bool IsPlaying(gs_id sound);
|
virtual bool IsPlaying(gs_id sound);
|
||||||
virtual status_t StartPlaying(gs_id sound);
|
virtual status_t StartPlaying(gs_id sound);
|
||||||
virtual status_t StopPlaying(gs_id sound);
|
virtual status_t StopPlaying(gs_id sound);
|
||||||
|
|
||||||
virtual status_t GetAttributes(gs_id sound,
|
virtual status_t GetAttributes(gs_id sound,
|
||||||
gs_attribute * attributes,
|
gs_attribute * attributes,
|
||||||
size_t attributeCount);
|
size_t attributeCount);
|
||||||
virtual status_t SetAttributes(gs_id sound,
|
virtual status_t SetAttributes(gs_id sound,
|
||||||
gs_attribute * attributes,
|
gs_attribute * attributes,
|
||||||
size_t attributeCount);
|
size_t attributeCount);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetInitError(status_t error);
|
void SetInitError(status_t error);
|
||||||
|
|
||||||
gs_audio_format fFormat;
|
gs_audio_format fFormat;
|
||||||
private:
|
private:
|
||||||
status_t Connect();
|
|
||||||
int32 AllocateSound();
|
int32 AllocateSound();
|
||||||
|
|
||||||
status_t fInitError;
|
status_t fInitError;
|
||||||
|
|
||||||
Connection * fConnection;
|
|
||||||
bool fIsConnected;
|
bool fIsConnected;
|
||||||
|
|
||||||
int32 fSoundCount;
|
int32 fSoundCount;
|
||||||
|
Loading…
Reference in New Issue
Block a user