* Moved _SoundPlayNode into the BPrivate namespace and dismissed the '_' prefix.

* Further cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34482 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-12-03 22:16:54 +00:00
parent e508a7fbd3
commit 4ed344af25
4 changed files with 332 additions and 352 deletions
+11 -9
View File
@@ -16,7 +16,9 @@
class BContinuousParameter; class BContinuousParameter;
class BParameterWeb; class BParameterWeb;
class BSound; class BSound;
class _SoundPlayNode; namespace BPrivate {
class SoundPlayNode;
}
class sound_error : public std::exception { class sound_error : public std::exception {
@@ -155,10 +157,10 @@ private:
const media_raw_audio_format& format); const media_raw_audio_format& format);
private: private:
friend class _SoundPlayNode; friend class BPrivate::SoundPlayNode;
struct _playing_sound { struct playing_sound {
_playing_sound* next; playing_sound* next;
off_t current_offset; off_t current_offset;
BSound* sound; BSound* sound;
play_id id; play_id id;
@@ -168,8 +170,8 @@ private:
float volume; float volume;
}; };
struct _waiting_sound { struct waiting_sound {
_waiting_sound* next; waiting_sound* next;
bigtime_t start_time; bigtime_t start_time;
BSound* sound; BSound* sound;
play_id id; play_id id;
@@ -177,10 +179,10 @@ private:
float volume; float volume;
}; };
_SoundPlayNode* fPlayerNode; BPrivate::SoundPlayNode* fPlayerNode;
_playing_sound* fPlayingSounds; playing_sound* fPlayingSounds;
_waiting_sound* fWaitingSounds; waiting_sound* fWaitingSounds;
BufferPlayerFunc fPlayBufferFunc; BufferPlayerFunc fPlayBufferFunc;
EventNotifierFunc fNotifierFunc; EventNotifierFunc fNotifierFunc;
+183 -179
View File
@@ -8,9 +8,7 @@
*/ */
/*! This is the BBufferProducer, used internally by BSoundPlayer /*! This is the BBufferProducer used internally by BSoundPlayer.
This belongs into a private namespace, but isn't for
compatibility reasons.
*/ */
@@ -28,25 +26,28 @@
#define SEND_NEW_BUFFER_EVENT (BTimedEventQueue::B_USER_EVENT + 1) #define SEND_NEW_BUFFER_EVENT (BTimedEventQueue::B_USER_EVENT + 1)
_SoundPlayNode::_SoundPlayNode(const char* name, BSoundPlayer* player) namespace BPrivate {
SoundPlayNode::SoundPlayNode(const char* name, BSoundPlayer* player)
: :
BMediaNode(name), BMediaNode(name),
BBufferProducer(B_MEDIA_RAW_AUDIO), BBufferProducer(B_MEDIA_RAW_AUDIO),
BMediaEventLooper(), BMediaEventLooper(),
mPlayer(player), fPlayer(player),
mInitCheckStatus(B_OK), fInitStatus(B_OK),
mOutputEnabled(true), fOutputEnabled(true),
mBufferGroup(NULL), fBufferGroup(NULL),
mFramesSent(0), fFramesSent(0),
mTooEarlyCount(0) fTooEarlyCount(0)
{ {
CALLED(); CALLED();
mOutput.format.type = B_MEDIA_RAW_AUDIO; fOutput.format.type = B_MEDIA_RAW_AUDIO;
mOutput.format.u.raw_audio = media_multi_audio_format::wildcard; fOutput.format.u.raw_audio = media_multi_audio_format::wildcard;
} }
_SoundPlayNode::~_SoundPlayNode() SoundPlayNode::~SoundPlayNode()
{ {
CALLED(); CALLED();
Quit(); Quit();
@@ -54,25 +55,25 @@ _SoundPlayNode::~_SoundPlayNode()
bool bool
_SoundPlayNode::IsPlaying() SoundPlayNode::IsPlaying()
{ {
return RunState() == B_STARTED; return RunState() == B_STARTED;
} }
bigtime_t bigtime_t
_SoundPlayNode::CurrentTime() SoundPlayNode::CurrentTime()
{ {
int frameRate = (int)mOutput.format.u.raw_audio.frame_rate; int frameRate = (int)fOutput.format.u.raw_audio.frame_rate;
return frameRate == 0 ? 0 return frameRate == 0 ? 0
: bigtime_t((1000000LL * mFramesSent) / frameRate); : bigtime_t((1000000LL * fFramesSent) / frameRate);
} }
media_multi_audio_format media_multi_audio_format
_SoundPlayNode::Format() const SoundPlayNode::Format() const
{ {
return mOutput.format.u.raw_audio; return fOutput.format.u.raw_audio;
} }
@@ -80,7 +81,7 @@ _SoundPlayNode::Format() const
BMediaAddOn* BMediaAddOn*
_SoundPlayNode::AddOn(int32* _internalID) const SoundPlayNode::AddOn(int32* _internalID) const
{ {
CALLED(); CALLED();
// This only gets called if we are in an add-on. // This only gets called if we are in an add-on.
@@ -89,7 +90,7 @@ _SoundPlayNode::AddOn(int32* _internalID) const
void void
_SoundPlayNode::Preroll() SoundPlayNode::Preroll()
{ {
CALLED(); CALLED();
// TODO: Performance opportunity // TODO: Performance opportunity
@@ -98,7 +99,7 @@ _SoundPlayNode::Preroll()
status_t status_t
_SoundPlayNode::HandleMessage(int32 message, const void* data, size_t size) SoundPlayNode::HandleMessage(int32 message, const void* data, size_t size)
{ {
CALLED(); CALLED();
return B_ERROR; return B_ERROR;
@@ -106,31 +107,31 @@ _SoundPlayNode::HandleMessage(int32 message, const void* data, size_t size)
void void
_SoundPlayNode::NodeRegistered() SoundPlayNode::NodeRegistered()
{ {
CALLED(); CALLED();
if (mInitCheckStatus != B_OK) { if (fInitStatus != B_OK) {
ReportError(B_NODE_IN_DISTRESS); ReportError(B_NODE_IN_DISTRESS);
return; return;
} }
SetPriority(B_URGENT_PRIORITY); SetPriority(B_URGENT_PRIORITY);
mOutput.format.type = B_MEDIA_RAW_AUDIO; fOutput.format.type = B_MEDIA_RAW_AUDIO;
mOutput.format.u.raw_audio = media_multi_audio_format::wildcard; fOutput.format.u.raw_audio = media_multi_audio_format::wildcard;
mOutput.destination = media_destination::null; fOutput.destination = media_destination::null;
mOutput.source.port = ControlPort(); fOutput.source.port = ControlPort();
mOutput.source.id = 0; fOutput.source.id = 0;
mOutput.node = Node(); fOutput.node = Node();
strcpy(mOutput.name, Name()); strcpy(fOutput.name, Name());
Run(); Run();
} }
status_t status_t
_SoundPlayNode::RequestCompleted(const media_request_info& info) SoundPlayNode::RequestCompleted(const media_request_info& info)
{ {
CALLED(); CALLED();
return B_OK; return B_OK;
@@ -138,7 +139,7 @@ _SoundPlayNode::RequestCompleted(const media_request_info& info)
void void
_SoundPlayNode::SetTimeSource(BTimeSource* timeSource) SoundPlayNode::SetTimeSource(BTimeSource* timeSource)
{ {
CALLED(); CALLED();
BMediaNode::SetTimeSource(timeSource); BMediaNode::SetTimeSource(timeSource);
@@ -146,9 +147,9 @@ _SoundPlayNode::SetTimeSource(BTimeSource* timeSource)
void void
_SoundPlayNode::SetRunMode(run_mode mode) SoundPlayNode::SetRunMode(run_mode mode)
{ {
TRACE("_SoundPlayNode::SetRunMode mode:%i\n", mode); TRACE("SoundPlayNode::SetRunMode mode:%i\n", mode);
BMediaNode::SetRunMode(mode); BMediaNode::SetRunMode(mode);
} }
@@ -157,7 +158,7 @@ _SoundPlayNode::SetRunMode(run_mode mode)
status_t status_t
_SoundPlayNode::FormatSuggestionRequested(media_type type, int32 /*quality*/, SoundPlayNode::FormatSuggestionRequested(media_type type, int32 /*quality*/,
media_format* format) media_format* format)
{ {
// FormatSuggestionRequested() is not necessarily part of the format // FormatSuggestionRequested() is not necessarily part of the format
@@ -179,7 +180,7 @@ _SoundPlayNode::FormatSuggestionRequested(media_type type, int32 /*quality*/,
status_t status_t
_SoundPlayNode::FormatProposal(const media_source& output, media_format* format) SoundPlayNode::FormatProposal(const media_source& output, media_format* format)
{ {
// FormatProposal() is the first stage in the BMediaRoster::Connect() // FormatProposal() is the first stage in the BMediaRoster::Connect()
// process. We hand out a suggested format, with wildcards for any // process. We hand out a suggested format, with wildcards for any
@@ -187,8 +188,8 @@ _SoundPlayNode::FormatProposal(const media_source& output, media_format* format)
CALLED(); CALLED();
// is this a proposal for our one output? // is this a proposal for our one output?
if (output != mOutput.source) { if (output != fOutput.source) {
TRACE("_SoundPlayNode::FormatProposal returning B_MEDIA_BAD_SOURCE\n"); TRACE("SoundPlayNode::FormatProposal returning B_MEDIA_BAD_SOURCE\n");
return B_MEDIA_BAD_SOURCE; return B_MEDIA_BAD_SOURCE;
} }
@@ -198,14 +199,14 @@ _SoundPlayNode::FormatProposal(const media_source& output, media_format* format)
// if not raw audio, we can't support it // if not raw audio, we can't support it
if (format->type != B_MEDIA_RAW_AUDIO) { if (format->type != B_MEDIA_RAW_AUDIO) {
TRACE("_SoundPlayNode::FormatProposal returning B_MEDIA_BAD_FORMAT\n"); TRACE("SoundPlayNode::FormatProposal returning B_MEDIA_BAD_FORMAT\n");
return B_MEDIA_BAD_FORMAT; return B_MEDIA_BAD_FORMAT;
} }
#if DEBUG >0 #if DEBUG >0
char buf[100]; char buf[100];
string_for_format(*format, buf, sizeof(buf)); string_for_format(*format, buf, sizeof(buf));
TRACE("_SoundPlayNode::FormatProposal: format %s\n", buf); TRACE("SoundPlayNode::FormatProposal: format %s\n", buf);
#endif #endif
return B_OK; return B_OK;
@@ -213,7 +214,7 @@ _SoundPlayNode::FormatProposal(const media_source& output, media_format* format)
status_t status_t
_SoundPlayNode::FormatChangeRequested(const media_source& source, SoundPlayNode::FormatChangeRequested(const media_source& source,
const media_destination& destination, media_format* _format, const media_destination& destination, media_format* _format,
int32* /* deprecated */) int32* /* deprecated */)
{ {
@@ -225,12 +226,12 @@ _SoundPlayNode::FormatChangeRequested(const media_source& source,
status_t status_t
_SoundPlayNode::GetNextOutput(int32* cookie, media_output* _output) SoundPlayNode::GetNextOutput(int32* cookie, media_output* _output)
{ {
CALLED(); CALLED();
if (*cookie == 0) { if (*cookie == 0) {
*_output = mOutput; *_output = fOutput;
*cookie += 1; *cookie += 1;
return B_OK; return B_OK;
} else { } else {
@@ -240,7 +241,7 @@ _SoundPlayNode::GetNextOutput(int32* cookie, media_output* _output)
status_t status_t
_SoundPlayNode::DisposeOutputCookie(int32 cookie) SoundPlayNode::DisposeOutputCookie(int32 cookie)
{ {
CALLED(); CALLED();
// do nothing because we don't use the cookie for anything special // do nothing because we don't use the cookie for anything special
@@ -249,19 +250,19 @@ _SoundPlayNode::DisposeOutputCookie(int32 cookie)
status_t status_t
_SoundPlayNode::SetBufferGroup(const media_source& forSource, SoundPlayNode::SetBufferGroup(const media_source& forSource,
BBufferGroup* newGroup) BBufferGroup* newGroup)
{ {
CALLED(); CALLED();
// is this our output? // is this our output?
if (forSource != mOutput.source) { if (forSource != fOutput.source) {
TRACE("_SoundPlayNode::SetBufferGroup returning B_MEDIA_BAD_SOURCE\n"); TRACE("SoundPlayNode::SetBufferGroup returning B_MEDIA_BAD_SOURCE\n");
return B_MEDIA_BAD_SOURCE; return B_MEDIA_BAD_SOURCE;
} }
// Are we being passed the buffer group we're already using? // Are we being passed the buffer group we're already using?
if (newGroup == mBufferGroup) if (newGroup == fBufferGroup)
return B_OK; return B_OK;
// Ahh, someone wants us to use a different buffer group. At this point we // Ahh, someone wants us to use a different buffer group. At this point we
@@ -270,19 +271,19 @@ _SoundPlayNode::SetBufferGroup(const media_source& forSource,
// use *that*. Note that if we're caching a BBuffer that we requested // use *that*. Note that if we're caching a BBuffer that we requested
// earlier, we have to Recycle() that buffer *before* deleting the buffer // earlier, we have to Recycle() that buffer *before* deleting the buffer
// group, otherwise we'll deadlock waiting for that buffer to be recycled! // group, otherwise we'll deadlock waiting for that buffer to be recycled!
delete mBufferGroup; delete fBufferGroup;
// waits for all buffers to recycle // waits for all buffers to recycle
if (newGroup != NULL) { if (newGroup != NULL) {
// we were given a valid group; just use that one from now on // we were given a valid group; just use that one from now on
mBufferGroup = newGroup; fBufferGroup = newGroup;
} else { } else {
// we were passed a NULL group pointer; that means we construct // we were passed a NULL group pointer; that means we construct
// our own buffer group to use from now on // our own buffer group to use from now on
size_t size = mOutput.format.u.raw_audio.buffer_size; size_t size = fOutput.format.u.raw_audio.buffer_size;
int32 count = int32(mLatency / BufferDuration() + 1 + 1); int32 count = int32(fLatency / BufferDuration() + 1 + 1);
if (count < 3) if (count < 3)
count = 3; count = 3;
mBufferGroup = new BBufferGroup(size, count); fBufferGroup = new BBufferGroup(size, count);
} }
return B_OK; return B_OK;
@@ -290,7 +291,7 @@ _SoundPlayNode::SetBufferGroup(const media_source& forSource,
status_t status_t
_SoundPlayNode::GetLatency(bigtime_t* _latency) SoundPlayNode::GetLatency(bigtime_t* _latency)
{ {
CALLED(); CALLED();
@@ -301,7 +302,7 @@ _SoundPlayNode::GetLatency(bigtime_t* _latency)
status_t status_t
_SoundPlayNode::PrepareToConnect(const media_source& what, SoundPlayNode::PrepareToConnect(const media_source& what,
const media_destination& where, media_format* format, const media_destination& where, media_format* format,
media_source* _source, char* _name) media_source* _source, char* _name)
{ {
@@ -314,14 +315,14 @@ _SoundPlayNode::PrepareToConnect(const media_source& what,
CALLED(); CALLED();
// is this our output? // is this our output?
if (what != mOutput.source) { if (what != fOutput.source) {
TRACE("_SoundPlayNode::PrepareToConnect returning " TRACE("SoundPlayNode::PrepareToConnect returning "
"B_MEDIA_BAD_SOURCE\n"); "B_MEDIA_BAD_SOURCE\n");
return B_MEDIA_BAD_SOURCE; return B_MEDIA_BAD_SOURCE;
} }
// are we already connected? // are we already connected?
if (mOutput.destination != media_destination::null) if (fOutput.destination != media_destination::null)
return B_MEDIA_ALREADY_CONNECTED; return B_MEDIA_ALREADY_CONNECTED;
// the format may not yet be fully specialized (the consumer might have // the format may not yet be fully specialized (the consumer might have
@@ -331,13 +332,13 @@ _SoundPlayNode::PrepareToConnect(const media_source& what,
#if DEBUG > 0 #if DEBUG > 0
char buf[100]; char buf[100];
string_for_format(*format, buf, sizeof(buf)); string_for_format(*format, buf, sizeof(buf));
TRACE("_SoundPlayNode::PrepareToConnect: input format %s\n", buf); TRACE("SoundPlayNode::PrepareToConnect: input format %s\n", buf);
#endif #endif
// if not raw audio, we can't support it // if not raw audio, we can't support it
if (format->type != B_MEDIA_UNKNOWN_TYPE if (format->type != B_MEDIA_UNKNOWN_TYPE
&& format->type != B_MEDIA_RAW_AUDIO) { && format->type != B_MEDIA_RAW_AUDIO) {
TRACE("_SoundPlayNode::PrepareToConnect: non raw format, returning " TRACE("SoundPlayNode::PrepareToConnect: non raw format, returning "
"B_MEDIA_BAD_FORMAT\n"); "B_MEDIA_BAD_FORMAT\n");
return B_MEDIA_BAD_FORMAT; return B_MEDIA_BAD_FORMAT;
} }
@@ -354,7 +355,7 @@ _SoundPlayNode::PrepareToConnect(const media_source& what,
&& *(uint32 *)&format->user_data[44] == FORMAT_USER_DATA_MAGIC_2) { && *(uint32 *)&format->user_data[44] == FORMAT_USER_DATA_MAGIC_2) {
channel_count = *(uint32 *)&format->user_data[4]; channel_count = *(uint32 *)&format->user_data[4];
frame_rate = *(float *)&format->user_data[20]; frame_rate = *(float *)&format->user_data[20];
TRACE("_SoundPlayNode::PrepareToConnect: found mixer info: " TRACE("SoundPlayNode::PrepareToConnect: found mixer info: "
"channel_count %ld, frame_rate %.1f\n", channel_count, frame_rate); "channel_count %ld, frame_rate %.1f\n", channel_count, frame_rate);
} }
@@ -377,28 +378,28 @@ _SoundPlayNode::PrepareToConnect(const media_source& what,
#if DEBUG > 0 #if DEBUG > 0
string_for_format(*format, buf, sizeof(buf)); string_for_format(*format, buf, sizeof(buf));
TRACE("_SoundPlayNode::PrepareToConnect: output format %s\n", buf); TRACE("SoundPlayNode::PrepareToConnect: output format %s\n", buf);
#endif #endif
// Now reserve the connection, and return information about it // Now reserve the connection, and return information about it
mOutput.destination = where; fOutput.destination = where;
mOutput.format = *format; fOutput.format = *format;
*_source = mOutput.source; *_source = fOutput.source;
strcpy(_name, Name()); strcpy(_name, Name());
return B_OK; return B_OK;
} }
void void
_SoundPlayNode::Connect(status_t error, const media_source& source, SoundPlayNode::Connect(status_t error, const media_source& source,
const media_destination& destination, const media_format& format, const media_destination& destination, const media_format& format,
char* name) char* name)
{ {
CALLED(); CALLED();
// is this our output? // is this our output?
if (source != mOutput.source) { if (source != fOutput.source) {
TRACE("_SoundPlayNode::Connect returning\n"); TRACE("SoundPlayNode::Connect returning\n");
return; return;
} }
@@ -406,85 +407,85 @@ _SoundPlayNode::Connect(status_t error, const media_source& source,
// a non-zero error code. When that happens we simply unreserve the // a non-zero error code. When that happens we simply unreserve the
// connection and do nothing else. // connection and do nothing else.
if (error) { if (error) {
mOutput.destination = media_destination::null; fOutput.destination = media_destination::null;
mOutput.format.type = B_MEDIA_RAW_AUDIO; fOutput.format.type = B_MEDIA_RAW_AUDIO;
mOutput.format.u.raw_audio = media_multi_audio_format::wildcard; fOutput.format.u.raw_audio = media_multi_audio_format::wildcard;
return; return;
} }
// Okay, the connection has been confirmed. Record the destination and // Okay, the connection has been confirmed. Record the destination and
// format that we agreed on, and report our connection name again. // format that we agreed on, and report our connection name again.
mOutput.destination = destination; fOutput.destination = destination;
mOutput.format = format; fOutput.format = format;
strcpy(name, Name()); strcpy(name, Name());
// Now that we're connected, we can determine our downstream latency. // Now that we're connected, we can determine our downstream latency.
// Do so, then make sure we get our events early enough. // Do so, then make sure we get our events early enough.
media_node_id id; media_node_id id;
FindLatencyFor(mOutput.destination, &mLatency, &id); FindLatencyFor(fOutput.destination, &fLatency, &id);
TRACE("_SoundPlayNode::Connect: downstream latency = %Ld\n", mLatency); TRACE("SoundPlayNode::Connect: downstream latency = %Ld\n", fLatency);
// reset our buffer duration, etc. to avoid later calculations // reset our buffer duration, etc. to avoid later calculations
bigtime_t duration = ((mOutput.format.u.raw_audio.buffer_size * 1000000LL) bigtime_t duration = ((fOutput.format.u.raw_audio.buffer_size * 1000000LL)
/ ((mOutput.format.u.raw_audio.format / ((fOutput.format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK) & media_raw_audio_format::B_AUDIO_SIZE_MASK)
* mOutput.format.u.raw_audio.channel_count)) * fOutput.format.u.raw_audio.channel_count))
/ (int32)mOutput.format.u.raw_audio.frame_rate; / (int32)fOutput.format.u.raw_audio.frame_rate;
SetBufferDuration(duration); SetBufferDuration(duration);
TRACE("_SoundPlayNode::Connect: buffer duration is %Ld\n", duration); TRACE("SoundPlayNode::Connect: buffer duration is %Ld\n", duration);
mInternalLatency = (3 * BufferDuration()) / 4; fInternalLatency = (3 * BufferDuration()) / 4;
TRACE("_SoundPlayNode::Connect: using %Ld as internal latency\n", TRACE("SoundPlayNode::Connect: using %Ld as internal latency\n",
mInternalLatency); fInternalLatency);
SetEventLatency(mLatency + mInternalLatency); SetEventLatency(fLatency + fInternalLatency);
// Set up the buffer group for our connection, as long as nobody handed us // Set up the buffer group for our connection, as long as nobody handed us
// a buffer group (via SetBufferGroup()) prior to this. // a buffer group (via SetBufferGroup()) prior to this.
// That can happen, for example, if the consumer calls SetOutputBuffersFor() // That can happen, for example, if the consumer calls SetOutputBuffersFor()
// on us from within its Connected() method. // on us from within its Connected() method.
if (!mBufferGroup) if (!fBufferGroup)
AllocateBuffers(); AllocateBuffers();
} }
void void
_SoundPlayNode::Disconnect(const media_source& what, SoundPlayNode::Disconnect(const media_source& what,
const media_destination& where) const media_destination& where)
{ {
CALLED(); CALLED();
// is this our output? // is this our output?
if (what != mOutput.source) { if (what != fOutput.source) {
TRACE("_SoundPlayNode::Disconnect returning\n"); TRACE("SoundPlayNode::Disconnect returning\n");
return; return;
} }
// Make sure that our connection is the one being disconnected // Make sure that our connection is the one being disconnected
if (where == mOutput.destination && what == mOutput.source) { if (where == fOutput.destination && what == fOutput.source) {
mOutput.destination = media_destination::null; fOutput.destination = media_destination::null;
mOutput.format.type = B_MEDIA_RAW_AUDIO; fOutput.format.type = B_MEDIA_RAW_AUDIO;
mOutput.format.u.raw_audio = media_multi_audio_format::wildcard; fOutput.format.u.raw_audio = media_multi_audio_format::wildcard;
delete mBufferGroup; delete fBufferGroup;
mBufferGroup = NULL; fBufferGroup = NULL;
} else { } else {
fprintf(stderr, "\tDisconnect() called with wrong source/destination (%ld/%ld), ours is (%ld/%ld)\n", fprintf(stderr, "\tDisconnect() called with wrong source/destination (%ld/%ld), ours is (%ld/%ld)\n",
what.id, where.id, mOutput.source.id, mOutput.destination.id); what.id, where.id, fOutput.source.id, fOutput.destination.id);
} }
} }
void void
_SoundPlayNode::LateNoticeReceived(const media_source& what, bigtime_t howMuch, SoundPlayNode::LateNoticeReceived(const media_source& what, bigtime_t howMuch,
bigtime_t performanceTime) bigtime_t performanceTime)
{ {
CALLED(); CALLED();
TRACE("_SoundPlayNode::LateNoticeReceived, %Ld too late at %Ld\n", howMuch, TRACE("SoundPlayNode::LateNoticeReceived, %Ld too late at %Ld\n", howMuch,
performanceTime); performanceTime);
// is this our output? // is this our output?
if (what != mOutput.source) { if (what != fOutput.source) {
TRACE("_SoundPlayNode::LateNoticeReceived returning\n"); TRACE("SoundPlayNode::LateNoticeReceived returning\n");
return; return;
} }
@@ -495,31 +496,31 @@ _SoundPlayNode::LateNoticeReceived(const media_source& what, bigtime_t howMuch,
// that at the moment, so we try to start producing buffers earlier to // that at the moment, so we try to start producing buffers earlier to
// compensate. // compensate.
mInternalLatency += howMuch; fInternalLatency += howMuch;
if (mInternalLatency > 30000) // avoid getting a too high latency if (fInternalLatency > 30000) // avoid getting a too high latency
mInternalLatency = 30000; fInternalLatency = 30000;
SetEventLatency(mLatency + mInternalLatency); SetEventLatency(fLatency + fInternalLatency);
TRACE("_SoundPlayNode::LateNoticeReceived: increasing latency to %Ld\n", mLatency + mInternalLatency); TRACE("SoundPlayNode::LateNoticeReceived: increasing latency to %Ld\n", fLatency + fInternalLatency);
} else { } else {
// The other run modes dictate various strategies for sacrificing data quality // The other run modes dictate various strategies for sacrificing data quality
// in the interests of timely data delivery. The way *we* do this is to skip // in the interests of timely data delivery. The way *we* do this is to skip
// a buffer, which catches us up in time by one buffer duration. // a buffer, which catches us up in time by one buffer duration.
size_t nFrames = mOutput.format.u.raw_audio.buffer_size size_t nFrames = fOutput.format.u.raw_audio.buffer_size
/ ((mOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) / ((fOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
* mOutput.format.u.raw_audio.channel_count); * fOutput.format.u.raw_audio.channel_count);
mFramesSent += nFrames; fFramesSent += nFrames;
TRACE("_SoundPlayNode::LateNoticeReceived: skipping a buffer to try to catch up\n"); TRACE("SoundPlayNode::LateNoticeReceived: skipping a buffer to try to catch up\n");
} }
} }
void void
_SoundPlayNode::EnableOutput(const media_source& what, bool enabled, SoundPlayNode::EnableOutput(const media_source& what, bool enabled,
int32* /* deprecated */) int32* /* deprecated */)
{ {
CALLED(); CALLED();
@@ -531,17 +532,17 @@ _SoundPlayNode::EnableOutput(const media_source& what, bool enabled,
// matches, then set the enable state accordingly. // matches, then set the enable state accordingly.
// is this our output? // is this our output?
if (what != mOutput.source) { if (what != fOutput.source) {
fprintf(stderr, "_SoundPlayNode::EnableOutput returning\n"); fprintf(stderr, "SoundPlayNode::EnableOutput returning\n");
return; return;
} }
mOutputEnabled = enabled; fOutputEnabled = enabled;
} }
void void
_SoundPlayNode::AdditionalBufferRequested(const media_source& source, SoundPlayNode::AdditionalBufferRequested(const media_source& source,
media_buffer_id previousBuffer, bigtime_t previousTime, media_buffer_id previousBuffer, bigtime_t previousTime,
const media_seek_tag* previousTag) const media_seek_tag* previousTag)
{ {
@@ -552,22 +553,22 @@ _SoundPlayNode::AdditionalBufferRequested(const media_source& source,
void void
_SoundPlayNode::LatencyChanged(const media_source& source, SoundPlayNode::LatencyChanged(const media_source& source,
const media_destination& destination, bigtime_t newLatency, uint32 flags) const media_destination& destination, bigtime_t newLatency, uint32 flags)
{ {
CALLED(); CALLED();
TRACE("_SoundPlayNode::LatencyChanged: new_latency %Ld\n", newLatency); TRACE("SoundPlayNode::LatencyChanged: new_latency %Ld\n", newLatency);
// something downstream changed latency, so we need to start producing // something downstream changed latency, so we need to start producing
// buffers earlier (or later) than we were previously. Make sure that the // buffers earlier (or later) than we were previously. Make sure that the
// connection that changed is ours, and adjust to the new downstream // connection that changed is ours, and adjust to the new downstream
// latency if so. // latency if so.
if (source == mOutput.source && destination == mOutput.destination) { if (source == fOutput.source && destination == fOutput.destination) {
mLatency = newLatency; fLatency = newLatency;
SetEventLatency(mLatency + mInternalLatency); SetEventLatency(fLatency + fInternalLatency);
} else { } else {
TRACE("_SoundPlayNode::LatencyChanged: ignored\n"); TRACE("SoundPlayNode::LatencyChanged: ignored\n");
} }
} }
@@ -576,7 +577,7 @@ _SoundPlayNode::LatencyChanged(const media_source& source,
void void
_SoundPlayNode::HandleEvent(const media_timed_event* event, bigtime_t lateness, SoundPlayNode::HandleEvent(const media_timed_event* event, bigtime_t lateness,
bool realTimeEvent) bool realTimeEvent)
{ {
CALLED(); CALLED();
@@ -619,7 +620,7 @@ _SoundPlayNode::HandleEvent(const media_timed_event* event, bigtime_t lateness,
// how should we handle late buffers? drop them? // how should we handle late buffers? drop them?
// notify the producer? // notify the producer?
status_t status_t
_SoundPlayNode::SendNewBuffer(const media_timed_event* event, SoundPlayNode::SendNewBuffer(const media_timed_event* event,
bigtime_t lateness, bool realTimeEvent) bigtime_t lateness, bool realTimeEvent)
{ {
CALLED(); CALLED();
@@ -627,7 +628,7 @@ _SoundPlayNode::SendNewBuffer(const media_timed_event* event,
// make sure we're both started *and* connected before delivering a buffer // make sure we're both started *and* connected before delivering a buffer
if (RunState() != BMediaEventLooper::B_STARTED if (RunState() != BMediaEventLooper::B_STARTED
|| mOutput.destination == media_destination::null) || fOutput.destination == media_destination::null)
return B_OK; return B_OK;
// The event->event_time is the time at which the buffer we are preparing // The event->event_time is the time at which the buffer we are preparing
@@ -637,12 +638,12 @@ _SoundPlayNode::SendNewBuffer(const media_timed_event* event,
// lateness is independent of EventLatency()! // lateness is independent of EventLatency()!
if (lateness > (BufferDuration() / 3) ) { if (lateness > (BufferDuration() / 3) ) {
printf("_SoundPlayNode::SendNewBuffer, event scheduled much too late, " printf("SoundPlayNode::SendNewBuffer, event scheduled much too late, "
"lateness is %Ld\n", lateness); "lateness is %Ld\n", lateness);
} }
// skip buffer creation if output not enabled // skip buffer creation if output not enabled
if (mOutputEnabled) { if (fOutputEnabled) {
// Get the next buffer of data // Get the next buffer of data
BBuffer* buffer = FillNextBuffer(event->event_time); BBuffer* buffer = FillNextBuffer(event->event_time);
@@ -651,26 +652,26 @@ _SoundPlayNode::SendNewBuffer(const media_timed_event* event,
// If we are ready way too early, decrase internal latency // If we are ready way too early, decrase internal latency
/* /*
bigtime_t how_early = event->event_time - TimeSource()->Now() - mLatency - mInternalLatency; bigtime_t how_early = event->event_time - TimeSource()->Now() - fLatency - fInternalLatency;
if (how_early > 5000) { if (how_early > 5000) {
printf("_SoundPlayNode::SendNewBuffer, event scheduled too early, how_early is %Ld\n", how_early); printf("SoundPlayNode::SendNewBuffer, event scheduled too early, how_early is %Ld\n", how_early);
if (mTooEarlyCount++ == 5) { if (fTooEarlyCount++ == 5) {
mInternalLatency -= how_early; fInternalLatency -= how_early;
if (mInternalLatency < 500) if (fInternalLatency < 500)
mInternalLatency = 500; fInternalLatency = 500;
printf("_SoundPlayNode::SendNewBuffer setting internal latency to %Ld\n", mInternalLatency); printf("SoundPlayNode::SendNewBuffer setting internal latency to %Ld\n", fInternalLatency);
SetEventLatency(mLatency + mInternalLatency); SetEventLatency(fLatency + fInternalLatency);
mTooEarlyCount = 0; fTooEarlyCount = 0;
} }
} }
*/ */
// send the buffer downstream if and only if output is enabled // send the buffer downstream if and only if output is enabled
if (B_OK != SendBuffer(buffer, mOutput.destination)) { if (B_OK != SendBuffer(buffer, fOutput.destination)) {
// we need to recycle the buffer // we need to recycle the buffer
// if the call to SendBuffer() fails // if the call to SendBuffer() fails
printf("_SoundPlayNode::SendNewBuffer: Buffer sending " printf("SoundPlayNode::SendNewBuffer: Buffer sending "
"failed\n"); "failed\n");
buffer->Recycle(); buffer->Recycle();
} }
@@ -678,17 +679,17 @@ _SoundPlayNode::SendNewBuffer(const media_timed_event* event,
} }
// track how much media we've delivered so far // track how much media we've delivered so far
size_t nFrames = mOutput.format.u.raw_audio.buffer_size size_t nFrames = fOutput.format.u.raw_audio.buffer_size
/ ((mOutput.format.u.raw_audio.format / ((fOutput.format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK) & media_raw_audio_format::B_AUDIO_SIZE_MASK)
* mOutput.format.u.raw_audio.channel_count); * fOutput.format.u.raw_audio.channel_count);
mFramesSent += nFrames; fFramesSent += nFrames;
// The buffer is on its way; now schedule the next one to go // The buffer is on its way; now schedule the next one to go
// nextEvent is the time at which the buffer should arrive at it's // nextEvent is the time at which the buffer should arrive at it's
// destination // destination
bigtime_t nextEvent = mStartTime + bigtime_t((1000000LL * mFramesSent) bigtime_t nextEvent = fStartTime + bigtime_t((1000000LL * fFramesSent)
/ (int32)mOutput.format.u.raw_audio.frame_rate); / (int32)fOutput.format.u.raw_audio.frame_rate);
media_timed_event nextBufferEvent(nextEvent, SEND_NEW_BUFFER_EVENT); media_timed_event nextBufferEvent(nextEvent, SEND_NEW_BUFFER_EVENT);
EventQueue()->AddEvent(nextBufferEvent); EventQueue()->AddEvent(nextBufferEvent);
@@ -697,10 +698,10 @@ _SoundPlayNode::SendNewBuffer(const media_timed_event* event,
status_t status_t
_SoundPlayNode::HandleDataStatus(const media_timed_event* event, SoundPlayNode::HandleDataStatus(const media_timed_event* event,
bigtime_t lateness, bool realTimeEvent) bigtime_t lateness, bool realTimeEvent)
{ {
TRACE("_SoundPlayNode::HandleDataStatus status: %li, lateness: %Li\n", TRACE("SoundPlayNode::HandleDataStatus status: %li, lateness: %Li\n",
event->data, lateness); event->data, lateness);
switch (event->data) { switch (event->data) {
@@ -718,7 +719,7 @@ _SoundPlayNode::HandleDataStatus(const media_timed_event* event,
status_t status_t
_SoundPlayNode::HandleStart(const media_timed_event* event, bigtime_t lateness, SoundPlayNode::HandleStart(const media_timed_event* event, bigtime_t lateness,
bool realTimeEvent) bool realTimeEvent)
{ {
CALLED(); CALLED();
@@ -727,8 +728,8 @@ _SoundPlayNode::HandleStart(const media_timed_event* event, bigtime_t lateness,
// We want to start sending buffers now, so we set up the buffer-sending // We want to start sending buffers now, so we set up the buffer-sending
// bookkeeping and fire off the first "produce a buffer" event. // bookkeeping and fire off the first "produce a buffer" event.
mFramesSent = 0; fFramesSent = 0;
mStartTime = event->event_time; fStartTime = event->event_time;
media_timed_event firstBufferEvent(event->event_time, media_timed_event firstBufferEvent(event->event_time,
SEND_NEW_BUFFER_EVENT); SEND_NEW_BUFFER_EVENT);
@@ -744,18 +745,18 @@ _SoundPlayNode::HandleStart(const media_timed_event* event, bigtime_t lateness,
status_t status_t
_SoundPlayNode::HandleSeek(const media_timed_event* event, bigtime_t lateness, SoundPlayNode::HandleSeek(const media_timed_event* event, bigtime_t lateness,
bool realTimeEvent) bool realTimeEvent)
{ {
CALLED(); CALLED();
TRACE("_SoundPlayNode::HandleSeek(t=%lld, d=%li, bd=%lld)\n", TRACE("SoundPlayNode::HandleSeek(t=%lld, d=%li, bd=%lld)\n",
event->event_time, event->data, event->bigdata); event->event_time, event->data, event->bigdata);
return B_OK; return B_OK;
} }
status_t status_t
_SoundPlayNode::HandleWarp(const media_timed_event* event, bigtime_t lateness, SoundPlayNode::HandleWarp(const media_timed_event* event, bigtime_t lateness,
bool realTimeEvent) bool realTimeEvent)
{ {
CALLED(); CALLED();
@@ -764,7 +765,7 @@ _SoundPlayNode::HandleWarp(const media_timed_event* event, bigtime_t lateness,
status_t status_t
_SoundPlayNode::HandleStop(const media_timed_event* event, bigtime_t lateness, SoundPlayNode::HandleStop(const media_timed_event* event, bigtime_t lateness,
bool realTimeEvent) bool realTimeEvent)
{ {
CALLED(); CALLED();
@@ -777,7 +778,7 @@ _SoundPlayNode::HandleStop(const media_timed_event* event, bigtime_t lateness,
status_t status_t
_SoundPlayNode::HandleParameter(const media_timed_event* event, SoundPlayNode::HandleParameter(const media_timed_event* event,
bigtime_t lateness, bool realTimeEvent) bigtime_t lateness, bool realTimeEvent)
{ {
CALLED(); CALLED();
@@ -786,60 +787,63 @@ _SoundPlayNode::HandleParameter(const media_timed_event* event,
void void
_SoundPlayNode::AllocateBuffers() SoundPlayNode::AllocateBuffers()
{ {
CALLED(); CALLED();
// allocate enough buffers to span our downstream latency, plus one // allocate enough buffers to span our downstream latency, plus one
size_t size = mOutput.format.u.raw_audio.buffer_size; size_t size = fOutput.format.u.raw_audio.buffer_size;
int32 count = int32(mLatency / BufferDuration() + 1 + 1); int32 count = int32(fLatency / BufferDuration() + 1 + 1);
TRACE("_SoundPlayNode::AllocateBuffers: latency = %Ld, buffer duration " TRACE("SoundPlayNode::AllocateBuffers: latency = %Ld, buffer duration "
"= %Ld, count %ld\n", mLatency, BufferDuration(), count); "= %Ld, count %ld\n", fLatency, BufferDuration(), count);
if (count < 3) if (count < 3)
count = 3; count = 3;
TRACE("_SoundPlayNode::AllocateBuffers: creating group of %ld buffers, " TRACE("SoundPlayNode::AllocateBuffers: creating group of %ld buffers, "
"size = %lu\n", count, size); "size = %lu\n", count, size);
mBufferGroup = new BBufferGroup(size, count); fBufferGroup = new BBufferGroup(size, count);
if (mBufferGroup->InitCheck() != B_OK) { if (fBufferGroup->InitCheck() != B_OK) {
ERROR("_SoundPlayNode::AllocateBuffers: BufferGroup::InitCheck() " ERROR("SoundPlayNode::AllocateBuffers: BufferGroup::InitCheck() "
"failed\n"); "failed\n");
} }
} }
BBuffer* BBuffer*
_SoundPlayNode::FillNextBuffer(bigtime_t event_time) SoundPlayNode::FillNextBuffer(bigtime_t eventTime)
{ {
CALLED(); CALLED();
// get a buffer from our buffer group // get a buffer from our buffer group
BBuffer* buf = mBufferGroup->RequestBuffer( BBuffer* buffer = fBufferGroup->RequestBuffer(
mOutput.format.u.raw_audio.buffer_size, BufferDuration() / 2); fOutput.format.u.raw_audio.buffer_size, BufferDuration() / 2);
// If we fail to get a buffer (for example, if the request times out), we // If we fail to get a buffer (for example, if the request times out), we
// skip this buffer and go on to the next, to avoid locking up the control // skip this buffer and go on to the next, to avoid locking up the control
// thread // thread
if (!buf) { if (buffer == NULL) {
ERROR("_SoundPlayNode::FillNextBuffer: RequestBuffer failed\n"); ERROR("SoundPlayNode::FillNextBuffer: RequestBuffer failed\n");
return NULL; return NULL;
} }
if (mPlayer->HasData()) { if (fPlayer->HasData()) {
mPlayer->_PlayBuffer(buf->Data(), fPlayer->_PlayBuffer(buffer->Data(),
mOutput.format.u.raw_audio.buffer_size, mOutput.format.u.raw_audio); fOutput.format.u.raw_audio.buffer_size, fOutput.format.u.raw_audio);
} else { } else
memset(buf->Data(), 0, mOutput.format.u.raw_audio.buffer_size); memset(buffer->Data(), 0, fOutput.format.u.raw_audio.buffer_size);
}
// fill in the buffer header // fill in the buffer header
media_header* hdr = buf->Header(); media_header* header = buffer->Header();
hdr->type = B_MEDIA_RAW_AUDIO; header->type = B_MEDIA_RAW_AUDIO;
hdr->size_used = mOutput.format.u.raw_audio.buffer_size; header->size_used = fOutput.format.u.raw_audio.buffer_size;
hdr->time_source = TimeSource()->ID(); header->time_source = TimeSource()->ID();
hdr->start_time = event_time; header->start_time = eventTime;
return buf;
return buffer;
} }
} // namespace BPrivate
+117 -142
View File
@@ -1,177 +1,152 @@
#ifndef _SOUND_PLAY_NODE_ /*
#define _SOUND_PLAY_NODE_ * Copyright 2002-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Marcus Overhagen
* Jérôme Duval
*/
#ifndef _SOUND_PLAY_NODE_H
#define _SOUND_PLAY_NODE_H
#include <BufferProducer.h>
#include <MediaEventLooper.h>
#include <Buffer.h> #include <Buffer.h>
#include <BufferGroup.h> #include <BufferGroup.h>
#include "SoundPlayer.h" #include <BufferProducer.h>
#include <MediaEventLooper.h>
#include <SoundPlayer.h>
/***********************************************************************
* AUTHOR: Marcus Overhagen, Jérôme Duval
* FILE: SoundPlayNode.h
* DESCR: This is the BBufferProducer, used internally by BSoundPlayer
* This belongs into a private namespace, but isn't for
* compatibility reasons.
***********************************************************************/
class _SoundPlayNode namespace BPrivate {
: public BBufferProducer, public BMediaEventLooper
{
class SoundPlayNode : public BBufferProducer, public BMediaEventLooper {
public: public:
_SoundPlayNode(const char *name, BSoundPlayer *player); SoundPlayNode(const char* name,
~_SoundPlayNode(); BSoundPlayer* player);
virtual ~SoundPlayNode();
bool IsPlaying(); bool IsPlaying();
bigtime_t CurrentTime(); bigtime_t CurrentTime();
/*************************/ // BMediaNode methods
/* begin from BMediaNode */
public: virtual BMediaAddOn* AddOn(int32* _internalID) const;
virtual BMediaAddOn* AddOn(
int32 * internal_id) const; /* Who instantiated you -- or NULL for app class */
protected: protected:
/* These don't return errors; instead, they use the global error condition reporter. */ virtual void Preroll();
/* A node is required to have a queue of at least one pending command (plus TimeWarp) */
/* and is recommended to allow for at least one pending command of each type. */
/* Allowing an arbitrary number of outstanding commands might be nice, but apps */
/* cannot depend on that happening. */
virtual void Preroll(void);
public: public:
virtual status_t HandleMessage( virtual status_t HandleMessage(int32 message, const void* data,
int32 message, size_t size);
const void * data,
size_t size);
protected: protected:
virtual void NodeRegistered(void); /* reserved 2 */ virtual void NodeRegistered();
virtual status_t RequestCompleted(const media_request_info &info); virtual status_t RequestCompleted(
virtual void SetTimeSource(BTimeSource *timeSource); const media_request_info& info);
virtual void SetRunMode(run_mode mode); virtual void SetTimeSource(BTimeSource* timeSource);
virtual void SetRunMode(run_mode mode);
/* end from BMediaNode */ // BBufferProducer methods
/***********************/
/******************************/ virtual status_t FormatSuggestionRequested(media_type type,
/* begin from BBufferProducer */ int32 quality, media_format* format);
virtual status_t FormatSuggestionRequested( media_type type, virtual status_t FormatProposal(const media_source& output,
int32 quality, media_format* format);
media_format* format);
virtual status_t FormatProposal( const media_source& output, virtual status_t FormatChangeRequested(
media_format* format); const media_source& source,
const media_destination& destination,
media_format* format, int32* _deprecated_);
virtual status_t GetNextOutput(int32* cookie,
media_output* _output);
virtual status_t DisposeOutputCookie(int32 cookie);
virtual status_t FormatChangeRequested( const media_source& source, virtual status_t SetBufferGroup(const media_source& forSource,
const media_destination& destination, BBufferGroup* group);
media_format* io_format, virtual status_t GetLatency(bigtime_t* _latency);
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, virtual status_t PrepareToConnect(const media_source& what,
BBufferGroup* group); const media_destination& where,
virtual status_t GetLatency( bigtime_t * out_latency); media_format* format, media_source* _source,
char* _name);
virtual status_t PrepareToConnect( const media_source& what, virtual void Connect(status_t error,
const media_destination& where, const media_source& source,
media_format* format, const media_destination& destination,
media_source* out_source, const media_format& format,
char* out_name); char* name);
virtual void Connect( status_t error, virtual void Disconnect(const media_source& what,
const media_source& source, const media_destination& where);
const media_destination& destination,
const media_format& format,
char* io_name);
virtual void Disconnect( const media_source& what, virtual void LateNoticeReceived(const media_source& what,
const media_destination& where); bigtime_t howMuch,
bigtime_t performanceTime);
virtual void LateNoticeReceived( const media_source& what, virtual void EnableOutput(const media_source& what,
bigtime_t how_much, bool enabled, int32* _deprecated_);
bigtime_t performance_time); virtual void AdditionalBufferRequested(
const media_source& source,
media_buffer_id previousBuffer,
bigtime_t previousTime,
const media_seek_tag* previousTag);
virtual void LatencyChanged(const media_source& source,
const media_destination& destination,
bigtime_t newLatency, uint32 flags);
virtual void EnableOutput( const media_source & what, // BMediaEventLooper methods
bool enabled,
int32* _deprecated_);
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);
/* end from BBufferProducer */
/****************************/
/********************************/
/* start from BMediaEventLooper */
protected:
/* you must override to handle your events! */
/* you should not call HandleEvent directly */
virtual void HandleEvent( const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
/* end from BMediaEventLooper */
/******************************/
protected:
virtual void HandleEvent(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
public: public:
media_multi_audio_format Format() const; media_multi_audio_format Format() const;
protected: protected:
virtual status_t HandleStart(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleSeek(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleWarp(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleStop(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t SendNewBuffer(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleDataStatus(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleParameter(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleStart( void AllocateBuffers();
const media_timed_event *event, BBuffer* FillNextBuffer(bigtime_t eventTime);
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleSeek(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleWarp(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleStop(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t SendNewBuffer(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleDataStatus(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleParameter(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
void AllocateBuffers();
BBuffer* FillNextBuffer(bigtime_t event_time);
private: private:
BSoundPlayer *mPlayer; BSoundPlayer* fPlayer;
status_t mInitCheckStatus; status_t fInitStatus;
bool mOutputEnabled; bool fOutputEnabled;
media_output mOutput; media_output fOutput;
BBufferGroup *mBufferGroup; BBufferGroup* fBufferGroup;
media_format mFormat; bigtime_t fLatency;
bigtime_t mLatency; bigtime_t fInternalLatency;
bigtime_t mInternalLatency; bigtime_t fStartTime;
bigtime_t mStartTime; uint64 fFramesSent;
uint64 mFramesSent; int32 fTooEarlyCount;
int32 mTooEarlyCount;
}; };
#endif
} // namespace BPrivate
#endif // _SOUND_PLAY_NODE_H
+11 -12
View File
@@ -23,7 +23,6 @@
#include "debug.h" #include "debug.h"
#define atomic_read(a) atomic_or(a, 0)
// Flags used internally in BSoundPlayer // Flags used internally in BSoundPlayer
enum { enum {
@@ -293,10 +292,10 @@ BSoundPlayer::Latency()
void void
BSoundPlayer::SetHasData(bool has_data) BSoundPlayer::SetHasData(bool hasData)
{ {
CALLED(); CALLED();
if (has_data) if (hasData)
atomic_or(&fFlags, F_HAS_DATA); atomic_or(&fFlags, F_HAS_DATA);
else else
atomic_and(&fFlags, ~F_HAS_DATA); atomic_and(&fFlags, ~F_HAS_DATA);
@@ -307,7 +306,7 @@ bool
BSoundPlayer::HasData() BSoundPlayer::HasData()
{ {
CALLED(); CALLED();
return (atomic_read(&fFlags) & F_HAS_DATA) != 0; return (atomic_get(&fFlags) & F_HAS_DATA) != 0;
} }
@@ -445,7 +444,7 @@ BSoundPlayer::StartPlaying(BSound* sound, bigtime_t atTime, float withVolume)
CALLED(); CALLED();
// TODO: support the at_time and with_volume parameters // TODO: support the at_time and with_volume parameters
_playing_sound *item = (_playing_sound *)malloc(sizeof(_playing_sound)); playing_sound* item = (playing_sound*)malloc(sizeof(playing_sound));
if (item == NULL) if (item == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -478,7 +477,7 @@ BSoundPlayer::SetSoundVolume(play_id id, float newVolume)
if (!fLocker.Lock()) if (!fLocker.Lock())
return B_ERROR; return B_ERROR;
_playing_sound *item = fPlayingSounds; playing_sound *item = fPlayingSounds;
while (item) { while (item) {
if (item->id == id) { if (item->id == id) {
item->volume = newVolume; item->volume = newVolume;
@@ -501,7 +500,7 @@ BSoundPlayer::IsPlaying(play_id id)
if (!fLocker.Lock()) if (!fLocker.Lock())
return B_ERROR; return B_ERROR;
_playing_sound *item = fPlayingSounds; playing_sound *item = fPlayingSounds;
while (item) { while (item) {
if (item->id == id) { if (item->id == id) {
fLocker.Unlock(); fLocker.Unlock();
@@ -523,8 +522,8 @@ BSoundPlayer::StopPlaying(play_id id)
if (!fLocker.Lock()) if (!fLocker.Lock())
return B_ERROR; return B_ERROR;
_playing_sound** link = &fPlayingSounds; playing_sound** link = &fPlayingSounds;
_playing_sound* item = fPlayingSounds; playing_sound* item = fPlayingSounds;
while (item != NULL) { while (item != NULL) {
if (item->id == id) { if (item->id == id) {
@@ -557,7 +556,7 @@ BSoundPlayer::WaitForSound(play_id id)
if (!fLocker.Lock()) if (!fLocker.Lock())
return B_ERROR; return B_ERROR;
_playing_sound* item = fPlayingSounds; playing_sound* item = fPlayingSounds;
while (item != NULL) { while (item != NULL) {
if (item->id == id) { if (item->id == id) {
sem_id waitSem = item->wait_sem; sem_id waitSem = item->wait_sem;
@@ -684,7 +683,7 @@ BSoundPlayer::_SoundPlayBufferFunc(void *cookie, void *buffer, size_t size,
return; return;
} }
_playing_sound *sound = player->fPlayingSounds; playing_sound *sound = player->fPlayingSounds;
if (sound == NULL) { if (sound == NULL) {
player->SetHasData(false); player->SetHasData(false);
player->fLocker.Unlock(); player->fLocker.Unlock();
@@ -774,7 +773,7 @@ BSoundPlayer::_Init(const media_node* node,
media_format tryFormat; media_format tryFormat;
// Create the player node and register it // Create the player node and register it
fPlayerNode = new _SoundPlayNode(name, this); fPlayerNode = new BPrivate::SoundPlayNode(name, this);
fInitStatus = roster->RegisterNode(fPlayerNode); fInitStatus = roster->RegisterNode(fPlayerNode);
if (fInitStatus != B_OK) { if (fInitStatus != B_OK) {
TRACE("BSoundPlayer::_Init: Couldn't RegisterNode: %s\n", TRACE("BSoundPlayer::_Init: Couldn't RegisterNode: %s\n",