* Minor cleanup.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30074 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-04-09 17:22:00 +00:00
parent 9cfc4c2ff8
commit e7cdf7f3f5
@@ -1,9 +1,11 @@
/*
* Copyright 2002 David Shipman,
* Copyright 2003-2007 Marcus Overhagen
* Copyright 2007 Haiku Inc. All rights reserved.
* Copyright 2007-2009 Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#include "AudioMixer.h"
#include "MixerCore.h"
#include "MixerInput.h"
@@ -31,29 +33,69 @@
#define USE_MEDIA_FORMAT_WORKAROUND 1
#define DB_TO_GAIN(db) dB_to_Gain((db))
#define GAIN_TO_DB(gain) Gain_to_dB((gain))
#define PERCENT_TO_GAIN(pct) ((pct) / 100.0)
#define GAIN_TO_PERCENT(gain) ((gain) * 100.0)
// the id is encoded with 16 bits
// then chan and src (or dst) are encoded with 6 bits
// the unique number with 4 bits
// the PARAM_ETC etc is encoded with 26 bits
#define PARAM_SRC_ENABLE(id, chan, src) (((id) << 16) | ((chan) << 10) | ((src) << 4) | 0x1)
#define PARAM_SRC_GAIN(id, chan, src) (((id) << 16) | ((chan) << 10) | ((src) << 4) | 0x2)
#define PARAM_DST_ENABLE(id, chan, dst) (((id) << 16) | ((chan) << 10) | ((dst) << 4) | 0x3)
#define PARAM_ETC(etc) (((etc) << 16) | 0x4)
#define PARAM_SRC_STR(id, chan) (((id) << 16) | ((chan) << 10) | 0x5)
#define PARAM_DST_STR(id, chan) (((id) << 16) | ((chan) << 10) | 0x6)
#define PARAM_MUTE(id) (((id) << 16) | 0x7)
#define PARAM_GAIN(id) (((id) << 16) | 0x8)
#define PARAM_BALANCE(id) (((id) << 16) | 0x9)
#define PARAM_STR1(id) (((id) << 16) | ((1) << 10) | 0xa)
#define PARAM_STR2(id) (((id) << 16) | ((2) << 10) | 0xa)
#define PARAM_STR3(id) (((id) << 16) | ((3) << 10) | 0xa)
#define PARAM_STR4(id) (((id) << 16) | ((4) << 10) | 0xa)
#define PARAM_STR5(id) (((id) << 16) | ((5) << 10) | 0xa)
#define PARAM_STR6(id) (((id) << 16) | ((6) << 10) | 0xa)
#define PARAM_STR7(id) (((id) << 16) | ((7) << 10) | 0xa)
#define PARAM(id) ((id) >> 16)
#define ETC(id) ((id) >> 16)
#define PARAM_CHAN(id) (((id) >> 10) & 0x3f)
#define PARAM_SRC(id) (((id) >> 4) & 0x3f)
#define PARAM_DST(id) (((id) >> 4) & 0x3f)
#define PARAM_IS_SRC_ENABLE(id) (((id) & 0xf) == 0x1)
#define PARAM_IS_SRC_GAIN(id) (((id) & 0xf) == 0x2)
#define PARAM_IS_DST_ENABLE(id) (((id) & 0xf) == 0x3)
#define PARAM_IS_ETC(id) (((id) & 0xf) == 0x4)
#define PARAM_IS_MUTE(id) (((id) & 0xf) == 0x7)
#define PARAM_IS_GAIN(id) (((id) & 0xf) == 0x8)
#define PARAM_IS_BALANCE(id) (((id) & 0xf) == 0x9)
#if USE_MEDIA_FORMAT_WORKAROUND
static void
multi_audio_format_specialize(media_multi_audio_format *format,
const media_multi_audio_format *other);
const media_multi_audio_format *other);
#endif
#define FORMAT_USER_DATA_TYPE 0x7294a8f3
#define FORMAT_USER_DATA_MAGIC_1 0xc84173bd
#define FORMAT_USER_DATA_MAGIC_2 0x4af62b7d
AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer)
: BMediaNode("Audio Mixer"),
BBufferConsumer(B_MEDIA_RAW_AUDIO),
BBufferProducer(B_MEDIA_RAW_AUDIO),
BControllable(),
BMediaEventLooper(),
fAddOn(addOn),
fCore(new MixerCore(this)),
fWeb(0),
fBufferGroup(0),
fDownstreamLatency(1),
fInternalLatency(1),
fDisableStop(false)
: BMediaNode("Audio Mixer"),
BBufferConsumer(B_MEDIA_RAW_AUDIO),
BBufferProducer(B_MEDIA_RAW_AUDIO),
BControllable(),
BMediaEventLooper(),
fAddOn(addOn),
fCore(new MixerCore(this)),
fWeb(0),
fBufferGroup(0),
fDownstreamLatency(1),
fInternalLatency(1),
fDisableStop(false)
{
BMediaNode::AddNodeKind(B_SYSTEM_MIXER);
@@ -83,6 +125,7 @@ AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer)
ApplySettings();
}
AudioMixer::~AudioMixer()
{
BMediaEventLooper::Quit();
@@ -102,6 +145,7 @@ AudioMixer::~AudioMixer()
DEBUG_ONLY(fCore = 0; fBufferGroup = 0; fWeb = 0);
}
void
AudioMixer::ApplySettings()
{
@@ -110,17 +154,19 @@ AudioMixer::ApplySettings()
fCore->Unlock();
}
void
AudioMixer::DisableNodeStop()
{
fDisableStop = true;
}
//
// BMediaNode methods
//
void AudioMixer::Stop(bigtime_t performance_time, bool immediate)
// #pragma mark - BMediaNode methods
void
AudioMixer::Stop(bigtime_t performance_time, bool immediate)
{
if (fDisableStop) {
TRACE("AudioMixer STOP is disabled\n");
@@ -130,16 +176,17 @@ void AudioMixer::Stop(bigtime_t performance_time, bool immediate)
}
}
BMediaAddOn *
BMediaAddOn*
AudioMixer::AddOn(int32 *internal_id) const
{
*internal_id = 0;
return fAddOn;
}
//
// BBufferConsumer methods
//
// #pragma mark - BBufferConsumer methods
status_t
AudioMixer::HandleMessage(int32 message, const void *data, size_t size)
@@ -148,6 +195,7 @@ AudioMixer::HandleMessage(int32 message, const void *data, size_t size)
return B_ERROR;
}
status_t
AudioMixer::AcceptFormat(const media_destination &dest, media_format *ioFormat)
{
@@ -187,6 +235,7 @@ AudioMixer::AcceptFormat(const media_destination &dest, media_format *ioFormat)
return B_OK;
}
status_t
AudioMixer::GetNextInput(int32 *cookie, media_input *out_input)
{
@@ -219,12 +268,14 @@ AudioMixer::GetNextInput(int32 *cookie, media_input *out_input)
return B_OK;
}
void
AudioMixer::DisposeInputCookie(int32 cookie)
{
// nothing to do
}
void
AudioMixer::BufferReceived(BBuffer *buffer)
{
@@ -248,9 +299,8 @@ AudioMixer::BufferReceived(BBuffer *buffer)
// to receive the buffer at the right time,
// push it through the event looper
media_timed_event event(buffer->Header()->start_time,
BTimedEventQueue::B_HANDLE_BUFFER,
buffer,
BTimedEventQueue::B_RECYCLE_BUFFER);
BTimedEventQueue::B_HANDLE_BUFFER, buffer,
BTimedEventQueue::B_RECYCLE_BUFFER);
EventQueue()->AddEvent(event);
}
@@ -289,9 +339,10 @@ AudioMixer::HandleInputBuffer(BBuffer *buffer, bigtime_t lateness)
*/
}
void
AudioMixer::ProducerDataStatus( const media_destination &for_whom,
int32 status, bigtime_t at_performance_time)
AudioMixer::ProducerDataStatus(const media_destination& for_whom,
int32 status, bigtime_t at_performance_time)
{
/*
if (IsValidDest(for_whom))
@@ -307,10 +358,10 @@ AudioMixer::ProducerDataStatus( const media_destination &for_whom,
*/
}
status_t
AudioMixer::GetLatencyFor(const media_destination &for_whom,
bigtime_t *out_latency,
media_node_id *out_timesource)
bigtime_t *out_latency, media_node_id *out_timesource)
{
// we have multiple inputs with different IDs, but
// the port number must match our ControlPort()
@@ -323,15 +374,16 @@ AudioMixer::GetLatencyFor(const media_destination &for_whom,
*out_timesource = TimeSource()->ID();
printf("AudioMixer::GetLatencyFor %Ld, timesource is %ld\n",
*out_latency,
*out_timesource);
*out_latency, *out_timesource);
return B_OK;
}
status_t
AudioMixer::Connected(const media_source &producer, const media_destination &where,
const media_format &with_format, media_input *out_input)
AudioMixer::Connected(const media_source &producer,
const media_destination &where, const media_format &with_format,
media_input *out_input)
{
PRINT_FORMAT("AudioMixer::Connected: ", with_format);
@@ -339,11 +391,11 @@ AudioMixer::Connected(const media_source &producer, const media_destination &whe
// BBufferProducer::PrepareToConnect() should have removed all wildcards.
if (out_input->format.u.raw_audio.frame_rate == 0) {
fprintf(stderr, "Audio Mixer Warning: "
"Producer (port %ld, id %ld) connected with frame_rate=0\n",
producer.port,
producer.id);
"Producer (port %ld, id %ld) connected with frame_rate=0\n",
producer.port, producer.id);
MixerOutput *output = fCore->Output();
float frame_rate = output ? output->MediaOutput().format.u.raw_audio.frame_rate : 44100.0f;
float frame_rate = output
? output->MediaOutput().format.u.raw_audio.frame_rate : 44100.0f;
out_input->format.u.raw_audio.frame_rate = frame_rate;
}
@@ -359,8 +411,9 @@ AudioMixer::Connected(const media_source &producer, const media_destination &whe
// we assign a new id (!= 0) to the newly created input
out_input->destination.id = fCore->CreateInputID();
// We need to make sure that the outInput's name field contains a valid name,
// the name given the connection by the producer may still be an empty string.
// We need to make sure that the outInput's name field contains a valid
// name, the name given the connection by the producer may still be an
// empty string.
// if the input has no name, assign one
if (strlen(out_input->name) == 0)
sprintf(out_input->name, "Input %ld", out_input->destination.id);
@@ -373,8 +426,9 @@ AudioMixer::Connected(const media_source &producer, const media_destination &whe
fCore->Unlock();
// If we want the producer to use a specific BBufferGroup, we now need to call
// BMediaRoster::SetOutputBuffersFor() here to set the producer's buffer group.
// If we want the producer to use a specific BBufferGroup, we now need
// to call BMediaRoster::SetOutputBuffersFor() here to set the producer's
// buffer group.
// But we have no special buffer requirements anyway...
UpdateParameterWeb();
@@ -382,8 +436,10 @@ AudioMixer::Connected(const media_source &producer, const media_destination &whe
return B_OK;
}
void
AudioMixer::Disconnected(const media_source &producer, const media_destination &where)
AudioMixer::Disconnected(const media_source &producer,
const media_destination &where)
{
// One of our inputs has been disconnected
@@ -403,9 +459,11 @@ AudioMixer::Disconnected(const media_source &producer, const media_destination &
UpdateParameterWeb();
}
status_t
AudioMixer::FormatChanged(const media_source &producer, const media_destination &consumer,
int32 change_tag, const media_format &format)
AudioMixer::FormatChanged(const media_source &producer,
const media_destination &consumer, int32 change_tag,
const media_format &format)
{
// at some point in the future (indicated by change_tag and RequestCompleted()),
// we will receive buffers in a different format
@@ -430,12 +488,13 @@ AudioMixer::FormatChanged(const media_source &producer, const media_destination
return B_OK;
}
//
// BBufferProducer methods
//
// #pragma mark - BBufferProducer methods
status_t
AudioMixer::FormatSuggestionRequested(media_type type, int32 quality, media_format *format)
AudioMixer::FormatSuggestionRequested(media_type type, int32 quality,
media_format *format)
{
TRACE("AudioMixer::FormatSuggestionRequested\n");
@@ -451,6 +510,7 @@ AudioMixer::FormatSuggestionRequested(media_type type, int32 quality, media_form
return B_OK;
}
status_t
AudioMixer::FormatProposal(const media_source &output, media_format *ioFormat)
{
@@ -476,14 +536,16 @@ AudioMixer::FormatProposal(const media_source &output, media_format *ioFormat)
return B_OK;
}
// If the format isn't good, put a good format into *io_format and return error
// If format has wildcard, specialize to what you can do (and change).
// If you can change the format, return OK.
// The request comes from your destination sychronously, so you cannot ask it
// whether it likes it -- you should assume it will since it asked.
/*! If the format isn't good, put a good format into *io_format and return error
If format has wildcard, specialize to what you can do (and change).
If you can change the format, return OK.
The request comes from your destination sychronously, so you cannot ask it
whether it likes it -- you should assume it will since it asked.
*/
status_t
AudioMixer::FormatChangeRequested(const media_source &source, const media_destination &destination,
media_format *io_format, int32 *_deprecated_)
AudioMixer::FormatChangeRequested(const media_source &source,
const media_destination &destination, media_format *io_format,
int32 *_deprecated_)
{
// the downstream consumer node (soundcard) requested that we produce
// another format, we need to check if the format is acceptable and
@@ -508,25 +570,30 @@ AudioMixer::FormatChangeRequested(const media_source &source, const media_destin
goto err;
}
if (destination != output->MediaOutput().destination) {
ERROR("AudioMixer::FormatChangeRequested: wrong output destination (port %ld, id %ld), our is (port %ld, id %ld)\n", destination.port, destination.id, output->MediaOutput().destination.port, output->MediaOutput().destination.id);
if (destination.port == output->MediaOutput().destination.port && destination.id == output->MediaOutput().destination.id + 1) {
ERROR("AudioMixer::FormatChangeRequested: this might be the broken R5 multi audio add-on\n");
goto err;
} else {
goto err;
ERROR("AudioMixer::FormatChangeRequested: wrong output destination "
"(port %ld, id %ld), our is (port %ld, id %ld)\n", destination.port,
destination.id, output->MediaOutput().destination.port,
output->MediaOutput().destination.id);
if (destination.port == output->MediaOutput().destination.port
&& destination.id == output->MediaOutput().destination.id + 1) {
ERROR("AudioMixer::FormatChangeRequested: this might be the broken "
"R5 multi audio add-on\n");
}
goto err;
}
if (io_format->type != B_MEDIA_RAW_AUDIO && io_format->type != B_MEDIA_UNKNOWN_TYPE) {
if (io_format->type != B_MEDIA_RAW_AUDIO
&& io_format->type != B_MEDIA_UNKNOWN_TYPE) {
ERROR("AudioMixer::FormatChangeRequested: wrong format type\n");
goto err;
}
/* remove wildcards */
#if USE_MEDIA_FORMAT_WORKAROUND
multi_audio_format_specialize(&io_format->u.raw_audio, &fDefaultFormat.u.raw_audio);
#else
io_format->SpecializeTo(&fDefaultFormat);
#endif
#if USE_MEDIA_FORMAT_WORKAROUND
multi_audio_format_specialize(&io_format->u.raw_audio,
&fDefaultFormat.u.raw_audio);
#else
io_format->SpecializeTo(&fDefaultFormat);
#endif
media_node_id id;
FindLatencyFor(destination, &fDownstreamLatency, &id);
@@ -537,7 +604,8 @@ AudioMixer::FormatChangeRequested(const media_source &source, const media_destin
TRACE("AudioMixer: buffer duration is %Ld usecs\n", BufferDuration());
// Our internal latency is at least the length of a full output buffer
fInternalLatency = BufferDuration() + max(4500LL, bigtime_t(0.5 * BufferDuration()));
fInternalLatency = BufferDuration()
+ max(4500LL, bigtime_t(0.5 * BufferDuration()));
TRACE("AudioMixer: Internal latency is %Ld usecs\n", fInternalLatency);
SetEventLatency(fDownstreamLatency + fInternalLatency);
@@ -545,7 +613,8 @@ AudioMixer::FormatChangeRequested(const media_source &source, const media_destin
// we need to inform all connected *inputs* about *our* change in latency
PublishEventLatencyChange();
// XXX we might need to create more buffers, to span a larger downstream latency
// TODO: we might need to create more buffers, to span a larger downstream
// latency
// apply latency change
fCore->SetTimingInfo(TimeSource(), fDownstreamLatency);
@@ -565,6 +634,7 @@ err:
return B_ERROR;
}
status_t
AudioMixer::GetNextOutput(int32 *cookie, media_output *out_output)
{
@@ -592,6 +662,7 @@ AudioMixer::GetNextOutput(int32 *cookie, media_output *out_output)
return B_OK;
}
status_t
AudioMixer::DisposeOutputCookie(int32 cookie)
{
@@ -599,8 +670,10 @@ AudioMixer::DisposeOutputCookie(int32 cookie)
return B_OK;
}
status_t
AudioMixer::SetBufferGroup(const media_source &for_source, BBufferGroup *newGroup)
AudioMixer::SetBufferGroup(const media_source &for_source,
BBufferGroup *newGroup)
{
PRINT("AudioMixer::SetBufferGroup\n");
// the downstream consumer (soundcard) node asks us to use another
@@ -624,6 +697,7 @@ AudioMixer::SetBufferGroup(const media_source &for_source, BBufferGroup *newGrou
return B_OK;
}
status_t
AudioMixer::GetLatency(bigtime_t *out_latency)
{
@@ -635,17 +709,20 @@ AudioMixer::GetLatency(bigtime_t *out_latency)
return B_OK;
}
void
AudioMixer::LatencyChanged(const media_source & source, const media_destination & destination,
bigtime_t new_latency, uint32 flags)
AudioMixer::LatencyChanged(const media_source& source,
const media_destination& destination, bigtime_t new_latency, uint32 flags)
{
if (source.port != ControlPort() || source.id != 0) {
ERROR("AudioMixer::LatencyChanged: received but has wrong source %ld/%ld\n", source.port, source.id);
ERROR("AudioMixer::LatencyChanged: received but has wrong source "
"%ld/%ld\n", source.port, source.id);
return;
}
TRACE("AudioMixer::LatencyChanged: downstream latency from %ld/%ld to %ld/%ld changed from %Ld to %Ld\n",
source.port, source.id, destination.port, destination.id, fDownstreamLatency, new_latency);
TRACE("AudioMixer::LatencyChanged: downstream latency from %ld/%ld to "
"%ld/%ld changed from %Ld to %Ld\n", source.port, source.id,
destination.port, destination.id, fDownstreamLatency, new_latency);
#if DEBUG
{
@@ -659,7 +736,8 @@ AudioMixer::LatencyChanged(const media_source & source, const media_destination
fDownstreamLatency = new_latency;
SetEventLatency(fDownstreamLatency + fInternalLatency);
// XXX we might need to create more buffers, to span a larger downstream latency
// XXX we might need to create more buffers, to span a larger downstream
// latency
fCore->Lock();
fCore->SetTimingInfo(TimeSource(), fDownstreamLatency);
@@ -669,16 +747,15 @@ AudioMixer::LatencyChanged(const media_source & source, const media_destination
status_t
AudioMixer::PrepareToConnect(const media_source &what,
const media_destination &where,
media_format *format,
media_source *out_source,
char *out_name)
const media_destination &where, media_format *format,
media_source *out_source, char *out_name)
{
TRACE("AudioMixer::PrepareToConnect\n");
// PrepareToConnect() is the second stage of format negotiations that happens
// inside BMediaRoster::Connect(). At this point, the consumer's AcceptFormat()
// method has been called, and that node has potentially changed the proposed
// format. It may also have left wildcards in the format. PrepareToConnect()
// PrepareToConnect() is the second stage of format negotiations that
// happens inside BMediaRoster::Connect(). At this point, the consumer's
// AcceptFormat() method has been called, and that node has potentially
// changed the proposed format.
// It may also have left wildcards in the format. PrepareToConnect()
// *must* fully specialize the format before returning!
// we also create the new output connection and return it in out_source.
@@ -693,7 +770,8 @@ AudioMixer::PrepareToConnect(const media_source &what,
return B_MEDIA_BAD_SOURCE;
// is the format acceptable?
if (format->type != B_MEDIA_RAW_AUDIO && format->type != B_MEDIA_UNKNOWN_TYPE) {
if (format->type != B_MEDIA_RAW_AUDIO
&& format->type != B_MEDIA_UNKNOWN_TYPE) {
PRINT_FORMAT("AudioMixer::PrepareToConnect: bad format", *format);
return B_MEDIA_BAD_FORMAT;
}
@@ -732,14 +810,23 @@ AudioMixer::PrepareToConnect(const media_source &what,
media_output out;
media_input in;
int32 count;
if (B_OK == roster->GetAudioMixer(&node) && B_OK == roster->GetConnectedOutputsFor(node, &out, 1, &count) && count == 1) {
if (roster->GetAudioMixer(&node) == B_OK
&& roster->GetConnectedOutputsFor(node, &out, 1, &count)
== B_OK
&& count == 1) {
// use mixer output format
format->u.raw_audio.channel_count = out.format.u.raw_audio.channel_count;
format->u.raw_audio.frame_rate = out.format.u.raw_audio.frame_rate;
} else if (B_OK == roster->GetAudioOutput(&node) && B_OK == roster->GetAllInputsFor(node, &in, 1, &count) && count == 1) {
format->u.raw_audio.channel_count
= out.format.u.raw_audio.channel_count;
format->u.raw_audio.frame_rate
= out.format.u.raw_audio.frame_rate;
} else if (roster->GetAudioOutput(&node) == B_OK
&& roster->GetAllInputsFor(node, &in, 1, &count) == B_OK
&& count == 1) {
// use DAC input format
format->u.raw_audio.channel_count = in.format.u.raw_audio.channel_count;
format->u.raw_audio.frame_rate = in.format.u.raw_audio.frame_rate;
format->u.raw_audio.channel_count
= in.format.u.raw_audio.channel_count;
format->u.raw_audio.frame_rate
= in.format.u.raw_audio.frame_rate;
}
}
}
@@ -749,11 +836,12 @@ AudioMixer::PrepareToConnect(const media_source &what,
strcpy(out_name, "Mixer Output");
/* remove wildcards */
#if USE_MEDIA_FORMAT_WORKAROUND
multi_audio_format_specialize(&format->u.raw_audio, &fDefaultFormat.u.raw_audio);
#else
format->SpecializeTo(&fDefaultFormat);
#endif
#if USE_MEDIA_FORMAT_WORKAROUND
multi_audio_format_specialize(&format->u.raw_audio,
&fDefaultFormat.u.raw_audio);
#else
format->SpecializeTo(&fDefaultFormat);
#endif
PRINT_FORMAT("AudioMixer::PrepareToConnect: final format", *format);
@@ -772,11 +860,10 @@ AudioMixer::PrepareToConnect(const media_source &what,
return B_OK;
}
void
AudioMixer::Connect(status_t error, const media_source &source,
const media_destination &dest,
const media_format &format,
char *io_name)
const media_destination &dest, const media_format &format, char *io_name)
{
TRACE("AudioMixer::Connect\n");
@@ -791,7 +878,8 @@ AudioMixer::Connect(status_t error, const media_source &source,
if (error != B_OK) {
// if an error occured, remove output from core
ERROR("AudioMixer::Connect failed with error 0x%08lX, removing connection\n", error);
ERROR("AudioMixer::Connect failed with error 0x%08lX, removing "
"connection\n", error);
fCore->Lock();
fCore->RemoveOutput();
fCore->Unlock();
@@ -818,7 +906,8 @@ AudioMixer::Connect(status_t error, const media_source &source,
TRACE("AudioMixer: buffer duration is %Ld usecs\n", BufferDuration());
// Our internal latency is at least the length of a full output buffer
fInternalLatency = BufferDuration() + max(4500LL, bigtime_t(0.5 * BufferDuration()));
fInternalLatency = BufferDuration()
+ max(4500LL, bigtime_t(0.5 * BufferDuration()));
TRACE("AudioMixer: Internal latency is %Ld usecs\n", fInternalLatency);
SetEventLatency(fDownstreamLatency + fInternalLatency);
@@ -826,10 +915,10 @@ AudioMixer::Connect(status_t error, const media_source &source,
// we need to inform all connected *inputs* about *our* change in latency
PublishEventLatencyChange();
// Set up the buffer group for our connection, as long as nobody handed us a
// buffer group (via SetBufferGroup()) prior to this. That can happen, for example,
// if the consumer calls SetOutputBuffersFor() on us from within its Connected()
// method.
// Set up the buffer group for our connection, as long as nobody handed
// us a buffer group (via SetBufferGroup()) prior to this. That can
// happen, for example, if the consumer calls SetOutputBuffersFor() on
// us from within its Connected() method.
if (!fBufferGroup)
fBufferGroup = CreateBufferGroup();
@@ -864,7 +953,10 @@ AudioMixer::Disconnect(const media_source &what, const media_destination &where)
// Make sure that our connection is the one being disconnected
MixerOutput * output = fCore->Output();
if (!output || output->MediaOutput().node != Node() || output->MediaOutput().source != what || output->MediaOutput().destination != where) {
if (!output
|| output->MediaOutput().node != Node()
|| output->MediaOutput().source != what
|| output->MediaOutput().destination != where) {
ERROR("AudioMixer::Disconnect can't disconnect (wrong connection)\n");
fCore->Unlock();
return;
@@ -891,12 +983,14 @@ AudioMixer::Disconnect(const media_source &what, const media_destination &where)
void
AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much, bigtime_t performance_time)
AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much,
bigtime_t performance_time)
{
// We've produced some late buffers... Increase Latency
// is the only runmode in which we can do anything about this
ERROR("AudioMixer::LateNoticeReceived, %Ld too late at %Ld\n", how_much, performance_time);
ERROR("AudioMixer::LateNoticeReceived, %Ld too late at %Ld\n", how_much,
performance_time);
// Note: The following code is outcommented on purpose
// and is about to be modified at a later point
/*
@@ -918,7 +1012,8 @@ AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much, big
void
AudioMixer::EnableOutput(const media_source &what, bool enabled, int32 *_deprecated_)
AudioMixer::EnableOutput(const media_source &what, bool enabled,
int32 *_deprecated_)
{
// we only have one output
if (what.id != 0 || what.port != ControlPort())
@@ -930,9 +1025,8 @@ AudioMixer::EnableOutput(const media_source &what, bool enabled, int32 *_depreca
}
//
// BMediaEventLooper methods
//
// #pragma mark - BMediaEventLooper methods
void
AudioMixer::NodeRegistered()
@@ -942,21 +1036,23 @@ AudioMixer::NodeRegistered()
UpdateParameterWeb();
}
void
AudioMixer::SetTimeSource(BTimeSource * time_source)
{
TRACE("AudioMixer::SetTimeSource: timesource is now %ld\n", time_source->ID());
TRACE("AudioMixer::SetTimeSource: timesource is now %ld\n",
time_source->ID());
fCore->Lock();
fCore->SetTimingInfo(time_source, fDownstreamLatency);
fCore->Unlock();
}
void
AudioMixer::HandleEvent(const media_timed_event *event, bigtime_t lateness, bool realTimeEvent)
{
switch (event->type)
{
void
AudioMixer::HandleEvent(const media_timed_event *event, bigtime_t lateness,
bool realTimeEvent)
{
switch (event->type) {
case BTimedEventQueue::B_HANDLE_BUFFER:
{
HandleInputBuffer((BBuffer *)event->pointer, lateness);
@@ -978,8 +1074,10 @@ AudioMixer::HandleEvent(const media_timed_event *event, bigtime_t lateness, bool
case BTimedEventQueue::B_STOP:
{
TRACE("AudioMixer::HandleEvent: B_STOP\n");
// stopped - don't process any more buffers, flush all buffers from eventqueue
EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
// stopped - don't process any more buffers, flush all buffers
// from event queue
EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true,
BTimedEventQueue::B_HANDLE_BUFFER);
fCore->Lock();
fCore->Stop();
fCore->Unlock();
@@ -994,13 +1092,12 @@ AudioMixer::HandleEvent(const media_timed_event *event, bigtime_t lateness, bool
default:
break;
}
}
//
// AudioMixer methods
//
// #pragma mark - AudioMixer methods
void
AudioMixer::PublishEventLatencyChange()
@@ -1014,24 +1111,29 @@ AudioMixer::PublishEventLatencyChange()
MixerInput *input;
for (int i = 0; (input = fCore->Input(i)) != 0; i++) {
TRACE("AudioMixer::PublishEventLatencyChange: SendLatencyChange, connection %ld/%ld to %ld/%ld event latency is now %Ld\n",
TRACE("AudioMixer::PublishEventLatencyChange: SendLatencyChange, "
"connection %ld/%ld to %ld/%ld event latency is now %Ld\n",
input->MediaInput().source.port, input->MediaInput().source.id,
input->MediaInput().destination.port, input->MediaInput().destination.id,
EventLatency());
SendLatencyChange(input->MediaInput().source, input->MediaInput().destination, EventLatency());
input->MediaInput().destination.port,
input->MediaInput().destination.id, EventLatency());
SendLatencyChange(input->MediaInput().source,
input->MediaInput().destination, EventLatency());
}
fCore->Unlock();
}
BBufferGroup *
BBufferGroup*
AudioMixer::CreateBufferGroup()
{
// allocate enough buffers to span our downstream latency
// (plus one for rounding up), plus one extra
int32 count = int32(fDownstreamLatency / BufferDuration()) + 2;
TRACE("AudioMixer::CreateBufferGroup: fDownstreamLatency %Ld, BufferDuration %Ld, buffer count = %ld\n", fDownstreamLatency, BufferDuration(), count);
TRACE("AudioMixer::CreateBufferGroup: fDownstreamLatency %Ld, "
"BufferDuration %Ld, buffer count = %ld\n", fDownstreamLatency,
BufferDuration(), count);
if (count < 3)
count = 3;
@@ -1040,21 +1142,25 @@ AudioMixer::CreateBufferGroup()
uint32 size = fCore->Output()->MediaOutput().format.u.raw_audio.buffer_size;
fCore->Unlock();
TRACE("AudioMixer: allocating %ld buffers of %ld bytes each\n", count, size);
TRACE("AudioMixer: allocating %ld buffers of %ld bytes each\n",
count, size);
return new BBufferGroup(size, count);
}
float
AudioMixer::dB_to_Gain(float db)
{
TRACE("dB_to_Gain: dB in: %01.2f ", db);
if (fCore->Settings()->NonLinearGainSlider()) {
if (db > 0) {
db = db * (pow(abs(DB_MAX), (1.0 / DB_EXPONENT_POSITIVE)) / abs(DB_MAX));
db = db * (pow(abs(DB_MAX), (1.0 / DB_EXPONENT_POSITIVE))
/ abs(DB_MAX));
db = pow(db, DB_EXPONENT_POSITIVE);
} else {
db = -db;
db = db * (pow(abs(DB_MIN), (1.0 / DB_EXPONENT_NEGATIVE)) / abs(DB_MIN));
db = db * (pow(abs(DB_MIN), (1.0 / DB_EXPONENT_NEGATIVE))
/ abs(DB_MIN));
db = pow(db, DB_EXPONENT_NEGATIVE);
db = -db;
}
@@ -1063,6 +1169,7 @@ AudioMixer::dB_to_Gain(float db)
return pow(10.0, db / 20.0);
}
float
AudioMixer::Gain_to_dB(float gain)
{
@@ -1071,59 +1178,21 @@ AudioMixer::Gain_to_dB(float gain)
if (fCore->Settings()->NonLinearGainSlider()) {
if (db > 0) {
db = pow(db, (1.0 / DB_EXPONENT_POSITIVE));
db = db * (abs(DB_MAX) / pow(abs(DB_MAX), (1.0 / DB_EXPONENT_POSITIVE)));
db = db * (abs(DB_MAX) / pow(abs(DB_MAX),
(1.0 / DB_EXPONENT_POSITIVE)));
} else {
db = -db;
db = pow(db, (1.0 / DB_EXPONENT_NEGATIVE));
db = db * (abs(DB_MIN) / pow(abs(DB_MIN), (1.0 / DB_EXPONENT_NEGATIVE)));
db = db * (abs(DB_MIN) / pow(abs(DB_MIN),
(1.0 / DB_EXPONENT_NEGATIVE)));
db = -db;
}
}
return db;
}
//
// BControllable methods
//
#define DB_TO_GAIN(db) dB_to_Gain((db))
#define GAIN_TO_DB(gain) Gain_to_dB((gain))
#define PERCENT_TO_GAIN(pct) ((pct) / 100.0)
#define GAIN_TO_PERCENT(gain) ((gain) * 100.0)
// the id is encoded with 16 bits
// then chan and src (or dst) are encoded with 6 bits
// the unique number with 4 bits
// the PARAM_ETC etc is encoded with 26 bits
#define PARAM_SRC_ENABLE(id, chan, src) (((id) << 16) | ((chan) << 10) | ((src) << 4) | 0x1)
#define PARAM_SRC_GAIN(id, chan, src) (((id) << 16) | ((chan) << 10) | ((src) << 4) | 0x2)
#define PARAM_DST_ENABLE(id, chan, dst) (((id) << 16) | ((chan) << 10) | ((dst) << 4) | 0x3)
#define PARAM_ETC(etc) (((etc) << 16) | 0x4)
#define PARAM_SRC_STR(id, chan) (((id) << 16) | ((chan) << 10) | 0x5)
#define PARAM_DST_STR(id, chan) (((id) << 16) | ((chan) << 10) | 0x6)
#define PARAM_MUTE(id) (((id) << 16) | 0x7)
#define PARAM_GAIN(id) (((id) << 16) | 0x8)
#define PARAM_BALANCE(id) (((id) << 16) | 0x9)
#define PARAM_STR1(id) (((id) << 16) | ((1) << 10) | 0xa)
#define PARAM_STR2(id) (((id) << 16) | ((2) << 10) | 0xa)
#define PARAM_STR3(id) (((id) << 16) | ((3) << 10) | 0xa)
#define PARAM_STR4(id) (((id) << 16) | ((4) << 10) | 0xa)
#define PARAM_STR5(id) (((id) << 16) | ((5) << 10) | 0xa)
#define PARAM_STR6(id) (((id) << 16) | ((6) << 10) | 0xa)
#define PARAM_STR7(id) (((id) << 16) | ((7) << 10) | 0xa)
#define PARAM(id) ((id) >> 16)
#define ETC(id) ((id) >> 16)
#define PARAM_CHAN(id) (((id) >> 10) & 0x3f)
#define PARAM_SRC(id) (((id) >> 4) & 0x3f)
#define PARAM_DST(id) (((id) >> 4) & 0x3f)
#define PARAM_IS_SRC_ENABLE(id) (((id) & 0xf) == 0x1)
#define PARAM_IS_SRC_GAIN(id) (((id) & 0xf) == 0x2)
#define PARAM_IS_DST_ENABLE(id) (((id) & 0xf) == 0x3)
#define PARAM_IS_ETC(id) (((id) & 0xf) == 0x4)
#define PARAM_IS_MUTE(id) (((id) & 0xf) == 0x7)
#define PARAM_IS_GAIN(id) (((id) & 0xf) == 0x8)
#define PARAM_IS_BALANCE(id) (((id) & 0xf) == 0x9)
// #pragma markß - BControllable methods
status_t
@@ -1570,7 +1639,7 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when, const void *value,
} else {
input->RemoveInputChannelDestination(PARAM_CHAN(id), PARAM_DST(id));
}
// XXX this is really annoying
// TODO: this is really annoying
// The slider count of the gain control needs to be changed,
// but calling SetChannelCount(input->GetMixerChannelCount())
// on it has no effect on remote BParameterWebs in other apps.
@@ -1582,13 +1651,16 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when, const void *value,
}
fCore->Settings()->SaveConnectionSettings(input);
}
BroadcastNewParameterValue(when, id, const_cast<void *>(value), size);
err:
fCore->Unlock();
if (update)
UpdateParameterWeb();
}
void
AudioMixer::UpdateParameterWeb()
{
@@ -1673,13 +1745,18 @@ AudioMixer::UpdateParameterWeb()
} else {
for (int chan = 0; chan < out->GetOutputChannelCount(); chan++) {
subgroup = group->MakeGroup("");
subgroup->MakeNullParameter(PARAM_SRC_STR(0, chan), B_MEDIA_RAW_AUDIO,
StringForChannelType(buf, out->GetOutputChannelType(chan)), B_GENERIC);
subgroup->MakeNullParameter(PARAM_SRC_STR(0, chan),
B_MEDIA_RAW_AUDIO, StringForChannelType(buf,
out->GetOutputChannelType(chan)), B_GENERIC);
for (int src = 0; src < MAX_CHANNEL_TYPES; src++) {
subsubgroup = subgroup->MakeGroup("");
subsubgroup->MakeDiscreteParameter(PARAM_SRC_ENABLE(0, chan, src), B_MEDIA_RAW_AUDIO, "", B_ENABLE);
subsubgroup->MakeContinuousParameter(PARAM_SRC_GAIN(0, chan, src), B_MEDIA_RAW_AUDIO,
StringForChannelType(buf, src), B_GAIN, "%", 0.0, 100.0, 0.1);
subsubgroup->MakeDiscreteParameter(
PARAM_SRC_ENABLE(0, chan, src), B_MEDIA_RAW_AUDIO, "",
B_ENABLE);
subsubgroup->MakeContinuousParameter(
PARAM_SRC_GAIN(0, chan, src), B_MEDIA_RAW_AUDIO,
StringForChannelType(buf, src), B_GAIN, "%", 0.0,
100.0, 0.1);
}
}
}
@@ -1737,9 +1814,11 @@ AudioMixer::UpdateParameterWeb()
SetParameterWeb(web);
}
#if USE_MEDIA_FORMAT_WORKAROUND
static void
raw_audio_format_specialize(media_raw_audio_format *format, const media_raw_audio_format *other)
raw_audio_format_specialize(media_raw_audio_format *format,
const media_raw_audio_format *other)
{
if (format->frame_rate == 0)
format->frame_rate = other->frame_rate;
@@ -1755,8 +1834,10 @@ raw_audio_format_specialize(media_raw_audio_format *format, const media_raw_audi
format->frame_rate = other->frame_rate;
}
static void
multi_audio_info_specialize(media_multi_audio_info *format, const media_multi_audio_info *other)
multi_audio_info_specialize(media_multi_audio_info *format,
const media_multi_audio_info *other)
{
if (format->channel_mask == 0)
format->channel_mask = other->channel_mask;
@@ -1766,8 +1847,10 @@ multi_audio_info_specialize(media_multi_audio_info *format, const media_multi_au
format->matrix_mask = other->matrix_mask;
}
static void
multi_audio_format_specialize(media_multi_audio_format *format, const media_multi_audio_format *other)
multi_audio_format_specialize(media_multi_audio_format *format,
const media_multi_audio_format *other)
{
raw_audio_format_specialize(format, other);
multi_audio_info_specialize(format, other);