Massive BSoundPlayer rewrite. Format negotiation and node registering/unregistering fixed.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9470 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d3f88ee1ed
commit
df42a7b539
@ -152,22 +152,17 @@ virtual status_t _Reserved_SoundPlayer_7(void *, ...);
|
||||
void (*fPlayBufferFunc)(void * cookie, void * buffer, size_t size, const media_raw_audio_format & format);
|
||||
void (*fNotifierFunc)(void * cookie, sound_player_notification what, ...);
|
||||
BLocker fLocker;
|
||||
float fVolume;
|
||||
media_input fMediaInput;
|
||||
media_output fMediaOutput;
|
||||
float * _m_mix_buffer;
|
||||
size_t _m_mix_buffer_size;
|
||||
float fVolumeDB;
|
||||
media_input fMediaInput; // the system mixer
|
||||
media_output fMediaOutput; // the player node
|
||||
void * fCookie;
|
||||
void * _m_buf;
|
||||
size_t _m_bufsize;
|
||||
int32 fFlags;
|
||||
|
||||
status_t fInitStatus; // new in R4.1
|
||||
bigtime_t _m_perfTime;
|
||||
BContinuousParameter * fVolumeSlider;
|
||||
bigtime_t fLastVolumeUpdate;
|
||||
BParameterWeb *fParameterWeb;
|
||||
uint32 _m_reserved[9];
|
||||
uint32 _m_reserved[15];
|
||||
|
||||
void NotifySoundDone(
|
||||
play_id sound,
|
||||
|
@ -7,6 +7,7 @@
|
||||
***********************************************************************/
|
||||
|
||||
#include <TimeSource.h>
|
||||
#include <MediaRoster.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -25,7 +26,7 @@
|
||||
|
||||
#define SEND_NEW_BUFFER_EVENT (BTimedEventQueue::B_USER_EVENT + 1)
|
||||
|
||||
_SoundPlayNode::_SoundPlayNode(const char *name, const media_multi_audio_format *format, BSoundPlayer *player) :
|
||||
_SoundPlayNode::_SoundPlayNode(const char *name, BSoundPlayer *player) :
|
||||
BMediaNode(name),
|
||||
BBufferProducer(B_MEDIA_RAW_AUDIO),
|
||||
BMediaEventLooper(),
|
||||
@ -37,28 +38,8 @@ _SoundPlayNode::_SoundPlayNode(const char *name, const media_multi_audio_format
|
||||
mTooEarlyCount(0)
|
||||
{
|
||||
CALLED();
|
||||
mFormat.type = B_MEDIA_RAW_AUDIO;
|
||||
mFormat.u.raw_audio = *format;
|
||||
|
||||
DPRINTF("Format Info:\n");
|
||||
DPRINTF(" frame_rate: %.1f (%ld)\n", mFormat.u.raw_audio.frame_rate, (int32)mFormat.u.raw_audio.frame_rate);
|
||||
DPRINTF(" channel_count: %ld\n",mFormat.u.raw_audio.channel_count);
|
||||
DPRINTF(" byte_order: %ld (",mFormat.u.raw_audio.byte_order);
|
||||
switch (mFormat.u.raw_audio.byte_order) {
|
||||
case B_MEDIA_BIG_ENDIAN: DPRINTF("B_MEDIA_BIG_ENDIAN)\n"); break;
|
||||
case B_MEDIA_LITTLE_ENDIAN: DPRINTF("B_MEDIA_LITTLE_ENDIAN)\n"); break;
|
||||
default: DPRINTF("unknown)\n"); break;
|
||||
}
|
||||
DPRINTF(" buffer_size: %ld\n",mFormat.u.raw_audio.buffer_size);
|
||||
DPRINTF(" format: %ld (",mFormat.u.raw_audio.format);
|
||||
switch (mFormat.u.raw_audio.format) {
|
||||
case media_raw_audio_format::B_AUDIO_FLOAT: DPRINTF("B_AUDIO_FLOAT)\n"); break;
|
||||
case media_raw_audio_format::B_AUDIO_SHORT: DPRINTF("B_AUDIO_SHORT)\n"); break;
|
||||
case media_raw_audio_format::B_AUDIO_INT: DPRINTF("B_AUDIO_INT)\n"); break;
|
||||
case media_raw_audio_format::B_AUDIO_CHAR: DPRINTF("B_AUDIO_CHAR)\n"); break;
|
||||
case media_raw_audio_format::B_AUDIO_UCHAR: DPRINTF("B_AUDIO_UCHAR)\n"); break;
|
||||
default: DPRINTF("unknown)\n"); break;
|
||||
}
|
||||
mOutput.format.type = B_MEDIA_RAW_AUDIO;
|
||||
mOutput.format.u.raw_audio = media_multi_audio_format::wildcard;
|
||||
}
|
||||
|
||||
|
||||
@ -75,16 +56,16 @@ _SoundPlayNode::IsPlaying()
|
||||
}
|
||||
|
||||
bigtime_t
|
||||
_SoundPlayNode::Latency()
|
||||
_SoundPlayNode::CurrentTime()
|
||||
{
|
||||
return EventLatency();
|
||||
int frame_rate = (int)mOutput.format.u.raw_audio.frame_rate;
|
||||
return frame_rate == 0 ? 0 : bigtime_t((1000000LL * mFramesSent) / frame_rate);
|
||||
}
|
||||
|
||||
|
||||
media_multi_audio_format
|
||||
_SoundPlayNode::Format() const
|
||||
{
|
||||
return mFormat.u.raw_audio;
|
||||
return mOutput.format.u.raw_audio;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------- //
|
||||
@ -122,7 +103,8 @@ void _SoundPlayNode::NodeRegistered(void)
|
||||
|
||||
SetPriority(B_URGENT_PRIORITY);
|
||||
|
||||
mOutput.format = mFormat;
|
||||
mOutput.format.type = B_MEDIA_RAW_AUDIO;
|
||||
mOutput.format.u.raw_audio = media_multi_audio_format::wildcard;
|
||||
mOutput.destination = media_destination::null;
|
||||
mOutput.source.port = ControlPort();
|
||||
mOutput.source.id = 0;
|
||||
@ -168,7 +150,8 @@ _SoundPlayNode::FormatSuggestionRequested(media_type type, int32 /*quality*/, me
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
|
||||
// this is the format we'll be returning (our preferred format)
|
||||
*format = mFormat;
|
||||
format->type = B_MEDIA_RAW_AUDIO;
|
||||
format->u.raw_audio = media_multi_audio_format::wildcard;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -186,16 +169,21 @@ _SoundPlayNode::FormatProposal(const media_source& output, media_format* format)
|
||||
return B_MEDIA_BAD_SOURCE;
|
||||
}
|
||||
|
||||
// we only support floating-point raw audio, so we always return that, but we
|
||||
// supply an error code depending on whether we found the proposal acceptable.
|
||||
media_type requestedType = format->type;
|
||||
*format = mFormat;
|
||||
if ((requestedType != B_MEDIA_UNKNOWN_TYPE) && (requestedType != B_MEDIA_RAW_AUDIO)) {
|
||||
// if wildcard, change it to raw audio
|
||||
if (format->type == B_MEDIA_UNKNOWN_TYPE)
|
||||
format->type = B_MEDIA_RAW_AUDIO;
|
||||
|
||||
// if not raw audio, we can't support it
|
||||
if (format->type != B_MEDIA_RAW_AUDIO) {
|
||||
TRACE("_SoundPlayNode::FormatProposal returning B_MEDIA_BAD_FORMAT\n");
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
}
|
||||
else
|
||||
return B_OK; // raw audio or wildcard type, either is okay by us
|
||||
|
||||
char buf[100];
|
||||
string_for_format(*format, buf, sizeof(buf));
|
||||
printf("_SoundPlayNode::FormatProposal: format %s\n", buf);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
@ -284,15 +272,14 @@ status_t
|
||||
_SoundPlayNode::PrepareToConnect(const media_source& what, const media_destination& where, media_format* format, media_source* out_source, char* out_name)
|
||||
{
|
||||
// PrepareToConnect() is the second stage of format negotiations that happens
|
||||
// inside BMediaRoster::Connect(). At this point, the consumer's AcceptFormat()
|
||||
// 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()
|
||||
// format. It may also have left wildcards in the format. PrepareToConnect()
|
||||
// *must* fully specialize the format before returning!
|
||||
CALLED();
|
||||
|
||||
// is this our output?
|
||||
if (what != mOutput.source)
|
||||
{
|
||||
if (what != mOutput.source) {
|
||||
TRACE("_SoundPlayNode::PrepareToConnect returning B_MEDIA_BAD_SOURCE\n");
|
||||
return B_MEDIA_BAD_SOURCE;
|
||||
}
|
||||
@ -302,26 +289,55 @@ _SoundPlayNode::PrepareToConnect(const media_source& what, const media_destinati
|
||||
return B_MEDIA_ALREADY_CONNECTED;
|
||||
|
||||
// the format may not yet be fully specialized (the consumer might have
|
||||
// passed back some wildcards). Finish specializing it now, and return an
|
||||
// passed back some wildcards). Finish specializing it now, and return an
|
||||
// error if we don't support the requested format.
|
||||
if (format->type != B_MEDIA_RAW_AUDIO)
|
||||
{
|
||||
TRACE("\tnon-raw-audio format?!\n");
|
||||
|
||||
char buf[100];
|
||||
string_for_format(*format, buf, sizeof(buf));
|
||||
printf("_SoundPlayNode::PrepareToConnect: input format %s\n", buf);
|
||||
|
||||
// if not raw audio, we can't support it
|
||||
if (format->type != B_MEDIA_UNKNOWN_TYPE && format->type != B_MEDIA_RAW_AUDIO) {
|
||||
TRACE("_SoundPlayNode::PrepareToConnect: non raw format, returning B_MEDIA_BAD_FORMAT\n");
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
}
|
||||
// !!! validate all other fields except for buffer_size here, because the consumer might have
|
||||
// supplied different values from AcceptFormat()?
|
||||
|
||||
// check the buffer size, which may still be wildcarded
|
||||
if (format->u.raw_audio.buffer_size == media_raw_audio_format::wildcard.buffer_size)
|
||||
{
|
||||
format->u.raw_audio.buffer_size = 2048; // pick something comfortable to suggest
|
||||
TRACE("\tno buffer size provided, suggesting %lu\n", format->u.raw_audio.buffer_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("\tconsumer suggested buffer_size %lu\n", format->u.raw_audio.buffer_size);
|
||||
// the haiku mixer might have a hint
|
||||
// for us, so check for it
|
||||
#define FORMAT_USER_DATA_TYPE 0x7294a8f3
|
||||
#define FORMAT_USER_DATA_MAGIC_1 0xc84173bd
|
||||
#define FORMAT_USER_DATA_MAGIC_2 0x4af62b7d
|
||||
uint32 channel_count = 0;
|
||||
float frame_rate = 0;
|
||||
if (format->user_data_type == FORMAT_USER_DATA_TYPE
|
||||
&& *(uint32 *)&format->user_data[0] == FORMAT_USER_DATA_MAGIC_1
|
||||
&& *(uint32 *)&format->user_data[44] == FORMAT_USER_DATA_MAGIC_2) {
|
||||
channel_count = *(uint32 *)&format->user_data[4];
|
||||
frame_rate = *(float *)&format->user_data[20];
|
||||
printf("_SoundPlayNode::PrepareToConnect: found mixer info: channel_count %ld, frame_rate %.1f\n", channel_count, frame_rate);
|
||||
}
|
||||
if (channel_count <= 0)
|
||||
channel_count = 2;
|
||||
if (frame_rate <= 0)
|
||||
frame_rate = 44100;
|
||||
|
||||
media_format default_format;
|
||||
default_format.type = B_MEDIA_RAW_AUDIO;
|
||||
default_format.u.raw_audio.frame_rate = frame_rate > 0 ? frame_rate : 44100;
|
||||
default_format.u.raw_audio.channel_count = channel_count > 0 ? channel_count : 2;
|
||||
default_format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
default_format.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
default_format.u.raw_audio.buffer_size = 0;
|
||||
format->SpecializeTo(&default_format);
|
||||
|
||||
if (format->u.raw_audio.buffer_size == 0)
|
||||
format->u.raw_audio.buffer_size = BMediaRoster::Roster()->AudioBufferSizeFor(
|
||||
format->u.raw_audio.channel_count,
|
||||
format->u.raw_audio.format,
|
||||
format->u.raw_audio.frame_rate);
|
||||
|
||||
string_for_format(*format, buf, sizeof(buf));
|
||||
printf("_SoundPlayNode::PrepareToConnect: output format %s\n", buf);
|
||||
|
||||
// Now reserve the connection, and return information about it
|
||||
mOutput.destination = where;
|
||||
@ -337,8 +353,7 @@ _SoundPlayNode::Connect(status_t error, const media_source& source, const media_
|
||||
CALLED();
|
||||
|
||||
// is this our output?
|
||||
if (source != mOutput.source)
|
||||
{
|
||||
if (source != mOutput.source) {
|
||||
TRACE("_SoundPlayNode::Connect returning\n");
|
||||
return;
|
||||
}
|
||||
@ -346,10 +361,10 @@ _SoundPlayNode::Connect(status_t error, const media_source& source, const media_
|
||||
// If something earlier failed, Connect() might still be called, but with a non-zero
|
||||
// error code. When that happens we simply unreserve the connection and do
|
||||
// nothing else.
|
||||
if (error)
|
||||
{
|
||||
if (error) {
|
||||
mOutput.destination = media_destination::null;
|
||||
mOutput.format = mFormat;
|
||||
mOutput.format.type = B_MEDIA_RAW_AUDIO;
|
||||
mOutput.format.u.raw_audio = media_multi_audio_format::wildcard;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -400,7 +415,8 @@ _SoundPlayNode::Disconnect(const media_source& what, const media_destination& wh
|
||||
if ((where == mOutput.destination) && (what == mOutput.source))
|
||||
{
|
||||
mOutput.destination = media_destination::null;
|
||||
mOutput.format = mFormat;
|
||||
mOutput.format.type = B_MEDIA_RAW_AUDIO;
|
||||
mOutput.format.u.raw_audio = media_multi_audio_format::wildcard;
|
||||
delete mBufferGroup;
|
||||
mBufferGroup = NULL;
|
||||
}
|
||||
|
@ -19,11 +19,11 @@ class _SoundPlayNode
|
||||
: public BBufferProducer, public BMediaEventLooper
|
||||
{
|
||||
public:
|
||||
_SoundPlayNode(const char *name, const media_multi_audio_format *format, BSoundPlayer *player);
|
||||
_SoundPlayNode(const char *name, BSoundPlayer *player);
|
||||
~_SoundPlayNode();
|
||||
|
||||
bool IsPlaying();
|
||||
bigtime_t Latency();
|
||||
bigtime_t CurrentTime();
|
||||
|
||||
/*************************/
|
||||
/* begin from BMediaNode */
|
||||
|
@ -13,50 +13,47 @@
|
||||
#include "SoundPlayNode.h"
|
||||
#include "SoundPlayer.h"
|
||||
|
||||
#define TRACE_SOUND_PLAYER
|
||||
#ifdef TRACE_SOUND_PLAYER
|
||||
#undef TRACE
|
||||
#define TRACE printf
|
||||
#endif
|
||||
|
||||
#define atomic_read(a) atomic_or(a, 0)
|
||||
|
||||
// Flags used internally in BSoundPlayer
|
||||
enum {
|
||||
F_HAS_DATA (1 << 0),
|
||||
F_NODES_CONNECTED (1 << 1),
|
||||
F_NODES_CONNECTED = (1 << 0),
|
||||
F_HAS_DATA = (1 << 1),
|
||||
F_IS_STARTED = (1 << 2),
|
||||
F_MUST_RELEASE_MIXER = (1 << 3),
|
||||
};
|
||||
|
||||
/*************************************************************
|
||||
* public sound_error
|
||||
*************************************************************/
|
||||
|
||||
//final
|
||||
sound_error::sound_error(const char *str)
|
||||
{
|
||||
CALLED();
|
||||
m_str_const = str;
|
||||
}
|
||||
|
||||
//final
|
||||
const char *
|
||||
sound_error::what() const
|
||||
{
|
||||
CALLED();
|
||||
return m_str_const;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* public BSoundPlayer
|
||||
*************************************************************/
|
||||
|
||||
|
||||
BSoundPlayer::BSoundPlayer(const char * name,
|
||||
void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format),
|
||||
void (*Notifier)(void *, sound_player_notification what, ...),
|
||||
void * cookie)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
TRACE("BSoundPlayer::BSoundPlayer: default constructor used");
|
||||
|
||||
media_multi_audio_format fmt = media_multi_audio_format::wildcard;
|
||||
fmt.frame_rate = 44100.0f;
|
||||
// fmt.frame_rate = 44100.0f;
|
||||
// fmt.channel_count = 2;
|
||||
fmt.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
fmt.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
//fmt.buffer_size = 4096;
|
||||
// fmt.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
// fmt.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
// fmt.buffer_size = 4096;
|
||||
Init(NULL, &fmt, name, NULL, PlayBuffer, Notifier, cookie);
|
||||
}
|
||||
|
||||
|
||||
BSoundPlayer::BSoundPlayer(const media_raw_audio_format * format,
|
||||
const char * name,
|
||||
void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format),
|
||||
@ -64,11 +61,15 @@ BSoundPlayer::BSoundPlayer(const media_raw_audio_format * format,
|
||||
void * cookie)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
TRACE("BSoundPlayer::BSoundPlayer: raw audio format constructor used");
|
||||
|
||||
media_multi_audio_format fmt = media_multi_audio_format::wildcard;
|
||||
fmt = *format;
|
||||
*(media_raw_audio_format *)&fmt = *format;
|
||||
Init(NULL, &fmt, name, NULL, PlayBuffer, Notifier, cookie);
|
||||
}
|
||||
|
||||
|
||||
BSoundPlayer::BSoundPlayer(const media_node & toNode,
|
||||
const media_multi_audio_format * format,
|
||||
const char * name,
|
||||
@ -78,55 +79,199 @@ BSoundPlayer::BSoundPlayer(const media_node & toNode,
|
||||
void * cookie)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
TRACE("BSoundPlayer::BSoundPlayer: multi audio format constructor used");
|
||||
|
||||
if (toNode.kind & B_BUFFER_CONSUMER == 0)
|
||||
debugger("BSoundPlayer: toNode must have B_BUFFER_CONSUMER kind!\n");
|
||||
|
||||
Init(&toNode, format, name, input, PlayBuffer, Notifier, cookie);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* private BSoundPlayer
|
||||
*************************************************************/
|
||||
|
||||
|
||||
void
|
||||
BSoundPlayer::Init( const media_node * node,
|
||||
const media_multi_audio_format * format,
|
||||
const char * name,
|
||||
const media_input * input,
|
||||
void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format),
|
||||
void (*Notifier)(void *, sound_player_notification what, ...),
|
||||
void * cookie)
|
||||
{
|
||||
CALLED();
|
||||
_m_sounds = NULL; // unused
|
||||
_m_waiting = NULL; // unused
|
||||
|
||||
fPlayerNode = NULL;
|
||||
fPlayBufferFunc = PlayBuffer;
|
||||
fNotifierFunc = Notifier;
|
||||
fVolumeDB = 0.0f;
|
||||
fCookie = cookie;
|
||||
fFlags = 0;
|
||||
fInitStatus = B_ERROR;
|
||||
fParameterWeb = NULL;
|
||||
fVolumeSlider = NULL;
|
||||
fLastVolumeUpdate = 0;
|
||||
|
||||
status_t err;
|
||||
media_node timeSource;
|
||||
media_node inputNode;
|
||||
media_output _output;
|
||||
media_input _input;
|
||||
int32 inputCount;
|
||||
int32 outputCount;
|
||||
media_format tryFormat;
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't get BMediaRoster\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// The inputNode that our player node will be
|
||||
// connected with is either supplied by the user
|
||||
// or the system audio mixer
|
||||
if (node) {
|
||||
inputNode = *node;
|
||||
} else {
|
||||
err = roster->GetAudioMixer(&inputNode);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetAudioMixer\n");
|
||||
goto the_end;
|
||||
}
|
||||
fFlags |= F_MUST_RELEASE_MIXER;
|
||||
}
|
||||
|
||||
// Create the player node and register it
|
||||
fPlayerNode = new _SoundPlayNode(name, this);
|
||||
err = roster->RegisterNode(fPlayerNode);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't RegisterNode\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
// set the producer's time source to be the "default" time source,
|
||||
// which the system audio mixer uses too.
|
||||
err = roster->GetTimeSource(&timeSource);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetTimeSource\n");
|
||||
goto the_end;
|
||||
}
|
||||
err = roster->SetTimeSourceFor(fPlayerNode->Node().node, timeSource.node);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't SetTimeSourceFor\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
if (!input) {
|
||||
err = roster->GetFreeInputsFor(inputNode, &_input, 1, &inputCount, B_MEDIA_RAW_AUDIO);
|
||||
if (err != B_OK || inputCount < 1) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetFreeInputsFor\n");
|
||||
goto the_end;
|
||||
}
|
||||
} else {
|
||||
_input = *input;
|
||||
}
|
||||
err = roster->GetFreeOutputsFor(fPlayerNode->Node(), &_output, 1, &outputCount, B_MEDIA_RAW_AUDIO);
|
||||
if (err != B_OK || outputCount < 1) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetFreeOutputsFor\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
// Set an appropriate run mode for the producer
|
||||
err = roster->SetRunModeNode(fPlayerNode->Node(), BMediaNode::B_INCREASE_LATENCY);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't SetRunModeNode\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
// setup our requested format (can still have many wildcards)
|
||||
tryFormat.type = B_MEDIA_RAW_AUDIO;
|
||||
tryFormat.u.raw_audio = *format;
|
||||
|
||||
char buf[100];
|
||||
string_for_format(tryFormat, buf, sizeof(buf));
|
||||
TRACE("BSoundPlayer::Init: trying to connect with format %s\n", buf);
|
||||
|
||||
// and connect the nodes
|
||||
err = roster->Connect(_output.source, _input.destination, &tryFormat, &fMediaOutput, &fMediaInput);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't Connect\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
fFlags |= F_NODES_CONNECTED;
|
||||
|
||||
get_volume_slider();
|
||||
|
||||
printf("BSoundPlayer node %ld has timesource %ld\n", fPlayerNode->Node().node, fPlayerNode->TimeSource()->Node().node);
|
||||
|
||||
the_end:
|
||||
TRACE("BSoundPlayer::Init: %s\n", strerror(err));
|
||||
SetInitError(err);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* public BSoundPlayer
|
||||
*************************************************************/
|
||||
|
||||
|
||||
/* virtual */
|
||||
BSoundPlayer::~BSoundPlayer()
|
||||
{
|
||||
CALLED();
|
||||
|
||||
F_NODES_CONNECTED
|
||||
|
||||
|
||||
|
||||
if (fPlayerNode) {
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::~BSoundPlayer: Couldn't get BMediaRoster\n");
|
||||
} else {
|
||||
status_t err;
|
||||
|
||||
// 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.
|
||||
Stop(true, false);
|
||||
|
||||
err = roster->Disconnect(fMediaInput.node.node, fMediaInput.source,
|
||||
fMediaOutput.node.node, fMediaOutput.destination);
|
||||
if (err) {
|
||||
fprintf(stderr, "* Error disconnecting nodes: %ld (%s)\n", err, strerror(err));
|
||||
}
|
||||
fVolumeSlider = NULL;
|
||||
|
||||
err = roster->ReleaseNode(fMediaInput.node);
|
||||
if (err) {
|
||||
fprintf(stderr, "* Error releasing input node: %ld (%s)\n", err, strerror(err));
|
||||
}
|
||||
|
||||
err = roster->ReleaseNode(fMediaOutput.node);
|
||||
if (err) {
|
||||
fprintf(stderr, "* Error releasing output node: %ld (%s)\n", err, strerror(err));
|
||||
}
|
||||
fPlayerNode = NULL;
|
||||
if (fFlags & F_IS_STARTED) {
|
||||
Stop(true, false); // block, but don't flush
|
||||
}
|
||||
|
||||
status_t err;
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::~BSoundPlayer: Couldn't get BMediaRoster\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (fFlags & F_NODES_CONNECTED) {
|
||||
// Ordinarily we'd stop *all* of the nodes in the chain before disconnecting. However,
|
||||
// our node is already stopped, and we can't stop the System Mixer.
|
||||
// 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.
|
||||
err = roster->Disconnect(fMediaInput.node.node, fMediaInput.source,
|
||||
fMediaOutput.node.node, fMediaOutput.destination);
|
||||
if (err) {
|
||||
TRACE("BSoundPlayer::~BSoundPlayer: Error disconnecting nodes: %ld (%s)\n", err, strerror(err));
|
||||
}
|
||||
}
|
||||
delete [] _m_buf;
|
||||
|
||||
if (fFlags & F_MUST_RELEASE_MIXER) {
|
||||
// Release the mixer as it was acquired
|
||||
// through BMediaRoster::GetAudioMixer()
|
||||
err = roster->ReleaseNode(fMediaInput.node);
|
||||
if (err) {
|
||||
TRACE("BSoundPlayer::~BSoundPlayer: Error releasing input node: %ld (%s)\n", err, strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
// Dispose of the player node
|
||||
if (fPlayerNode) {
|
||||
// We do not call BMediaRoster::ReleaseNode(), since
|
||||
// the player was created by using "new". We could
|
||||
// call BMediaRoster::UnregisterNode(), but this is
|
||||
// supposed to be done by BMediaNode destructor automatically
|
||||
delete fPlayerNode;
|
||||
}
|
||||
|
||||
delete fParameterWeb;
|
||||
// do not delete fVolumeSlider, it belonged to the parameter web
|
||||
}
|
||||
|
||||
|
||||
@ -143,6 +288,12 @@ BSoundPlayer::Format() const
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if ((fFlags & F_NODES_CONNECTED) == 0)
|
||||
return media_raw_audio_format::wildcard;
|
||||
|
||||
return fPlayerNode->Format();
|
||||
|
||||
#if 0
|
||||
media_raw_audio_format temp = media_raw_audio_format::wildcard;
|
||||
|
||||
if (fPlayerNode) {
|
||||
@ -152,6 +303,7 @@ BSoundPlayer::Format() const
|
||||
}
|
||||
|
||||
return temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -159,24 +311,33 @@ status_t
|
||||
BSoundPlayer::Start()
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if ((fFlags & F_NODES_CONNECTED) == 0)
|
||||
return B_NO_INIT;
|
||||
|
||||
if (!fPlayerNode)
|
||||
return B_ERROR;
|
||||
if (fFlags & F_IS_STARTED)
|
||||
return B_OK;
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::Start: Couldn't get BMediaRoster\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// make sure we give the producer enough time to run buffers through
|
||||
// the node chain, otherwise it'll start up already late
|
||||
bigtime_t latency = 0;
|
||||
status_t err = roster->GetLatencyFor(fPlayerNode->Node(), &latency);
|
||||
|
||||
err = roster->StartNode(fPlayerNode->Node(), fPlayerNode->TimeSource()->Now() + latency + 5000);
|
||||
// Add latency and a few ms to the nodes current time to
|
||||
// make sure that we give the producer enough time to run
|
||||
// buffers through the node chain, otherwise it'll start
|
||||
// up already late
|
||||
|
||||
return err;
|
||||
status_t err = roster->StartNode(fPlayerNode->Node(), fPlayerNode->TimeSource()->Now() + Latency() + 5000);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Start: StartNode failed, %ld", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
atomic_or(&fFlags, F_IS_STARTED);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -186,21 +347,26 @@ BSoundPlayer::Stop(bool block,
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if (!fPlayerNode)
|
||||
return;
|
||||
|
||||
// XXX flush is ignored
|
||||
|
||||
TRACE("BSoundPlayer::Stop: block %d, flush %d\n", (int)block, (int)flush);
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::Stop: Couldn't get BMediaRoster\n");
|
||||
|
||||
if ((fFlags & F_NODES_CONNECTED) == 0)
|
||||
return;
|
||||
|
||||
// XXX flush is ignored
|
||||
|
||||
if (fFlags & F_IS_STARTED) {
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::Stop: Couldn't get BMediaRoster\n");
|
||||
return;
|
||||
}
|
||||
|
||||
roster->StopNode(fPlayerNode->Node(), 0, true);
|
||||
|
||||
atomic_and(&fFlags, ~F_IS_STARTED);
|
||||
}
|
||||
|
||||
roster->StopNode(fPlayerNode->Node(), 0, true);
|
||||
|
||||
if (block) {
|
||||
// wait until the node is stopped
|
||||
int maxtrys;
|
||||
@ -210,10 +376,56 @@ BSoundPlayer::Stop(bool block,
|
||||
DEBUG_ONLY(if (maxtrys == 0) printf("BSoundPlayer::Stop: waiting for node stop failed\n"));
|
||||
|
||||
// wait until all buffers on the way to the physical output have been played
|
||||
snooze(fPlayerNode->Latency() + 2000);
|
||||
snooze(Latency() + 2000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bigtime_t
|
||||
BSoundPlayer::Latency()
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if ((fFlags & F_NODES_CONNECTED) == 0)
|
||||
return 0;
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::Latency: Couldn't get BMediaRoster\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bigtime_t latency;
|
||||
status_t err = roster->GetLatencyFor(fMediaOutput.node, &latency);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Latency: GetLatencyFor failed %ld (%s)\n", err, strerror(err));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return latency;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BSoundPlayer::SetHasData(bool has_data)
|
||||
{
|
||||
CALLED();
|
||||
if (has_data)
|
||||
atomic_or(&fFlags, F_HAS_DATA);
|
||||
else
|
||||
atomic_and(&fFlags, ~F_HAS_DATA);
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ bool
|
||||
BSoundPlayer::HasData()
|
||||
{
|
||||
CALLED();
|
||||
return (atomic_read(&fFlags) & F_HAS_DATA) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BSoundPlayer::BufferPlayerFunc
|
||||
BSoundPlayer::BufferPlayer() const
|
||||
{
|
||||
@ -221,7 +433,9 @@ BSoundPlayer::BufferPlayer() const
|
||||
return fPlayBufferFunc;
|
||||
}
|
||||
|
||||
void BSoundPlayer::SetBufferPlayer(void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format))
|
||||
|
||||
void
|
||||
BSoundPlayer::SetBufferPlayer(void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format))
|
||||
{
|
||||
CALLED();
|
||||
fLocker.Lock();
|
||||
@ -229,6 +443,7 @@ void BSoundPlayer::SetBufferPlayer(void (*PlayBuffer)(void *, void * buffer, siz
|
||||
fLocker.Unlock();
|
||||
}
|
||||
|
||||
|
||||
BSoundPlayer::EventNotifierFunc
|
||||
BSoundPlayer::EventNotifier() const
|
||||
{
|
||||
@ -236,6 +451,7 @@ BSoundPlayer::EventNotifier() const
|
||||
return fNotifierFunc;
|
||||
}
|
||||
|
||||
|
||||
void BSoundPlayer::SetNotifier(void (*Notifier)(void *, sound_player_notification what, ...))
|
||||
{
|
||||
CALLED();
|
||||
@ -244,6 +460,7 @@ void BSoundPlayer::SetNotifier(void (*Notifier)(void *, sound_player_notificatio
|
||||
fLocker.Unlock();
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
BSoundPlayer::Cookie() const
|
||||
{
|
||||
@ -251,6 +468,7 @@ BSoundPlayer::Cookie() const
|
||||
return fCookie;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BSoundPlayer::SetCookie(void *cookie)
|
||||
{
|
||||
@ -260,9 +478,11 @@ BSoundPlayer::SetCookie(void *cookie)
|
||||
fLocker.Unlock();
|
||||
}
|
||||
|
||||
void BSoundPlayer::SetCallbacks(void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format),
|
||||
void (*Notifier)(void *, sound_player_notification what, ...),
|
||||
void * cookie)
|
||||
|
||||
void
|
||||
BSoundPlayer::SetCallbacks(void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format),
|
||||
void (*Notifier)(void *, sound_player_notification what, ...),
|
||||
void * cookie)
|
||||
{
|
||||
CALLED();
|
||||
fLocker.Lock();
|
||||
@ -273,22 +493,29 @@ void BSoundPlayer::SetCallbacks(void (*PlayBuffer)(void *, void * buffer, size_t
|
||||
}
|
||||
|
||||
|
||||
/* The BeBook is inaccurate about the meaning of this function.
|
||||
* The probably best interpretation is to return the time that
|
||||
* has elapsed since playing was started, whichs seems to match
|
||||
* " CurrentTime() returns the current media time "
|
||||
*/
|
||||
bigtime_t
|
||||
BSoundPlayer::CurrentTime()
|
||||
{
|
||||
CALLED();
|
||||
if (!fPlayerNode)
|
||||
return system_time(); // XXX wrong
|
||||
if ((fFlags & F_NODES_CONNECTED) == 0)
|
||||
return 0;
|
||||
|
||||
return fPlayerNode->TimeSource()->Now(); // XXX wrong
|
||||
return fPlayerNode->CurrentTime();
|
||||
}
|
||||
|
||||
|
||||
/* Returns the current performance time of the sound player node
|
||||
* being used by the BSoundPlayer. Will return B_ERROR if the
|
||||
* BSoundPlayer object hasn't been properly initialized.
|
||||
*/
|
||||
bigtime_t
|
||||
BSoundPlayer::PerformanceTime()
|
||||
{
|
||||
CALLED();
|
||||
if (!fPlayerNode)
|
||||
if ((fFlags & F_NODES_CONNECTED) == 0)
|
||||
return (bigtime_t) B_ERROR;
|
||||
|
||||
return fPlayerNode->TimeSource()->Now();
|
||||
@ -300,6 +527,9 @@ BSoundPlayer::Preroll()
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if ((fFlags & F_NODES_CONNECTED) == 0)
|
||||
return B_NO_INIT;
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::Preroll: Couldn't get BMediaRoster\n");
|
||||
@ -307,12 +537,12 @@ BSoundPlayer::Preroll()
|
||||
}
|
||||
|
||||
status_t err = roster->PrerollNode(fMediaOutput.node);
|
||||
|
||||
if (err != B_OK) {
|
||||
fprintf(stderr, "Error while PrerollNode: %ld (%s)\n", err, strerror(err));
|
||||
TRACE("BSoundPlayer::Preroll: Error while PrerollNode: %ld (%s)\n", err, strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -394,17 +624,17 @@ BSoundPlayer::VolumeDB(bool forcePoll)
|
||||
{
|
||||
CALLED();
|
||||
if (!fVolumeSlider)
|
||||
return 0.0f;
|
||||
return -94.0f; // silence
|
||||
|
||||
if (!forcePoll && (system_time() - fLastVolumeUpdate < 500000))
|
||||
return fVolume;
|
||||
return fVolumeDB;
|
||||
|
||||
int32 count = fVolumeSlider->CountChannels();
|
||||
float values[count];
|
||||
size_t size = count * sizeof(float);
|
||||
fVolumeSlider->GetValue(&values, &size, NULL);
|
||||
fLastVolumeUpdate = system_time();
|
||||
fVolume = values[0];
|
||||
fVolumeDB = values[0];
|
||||
|
||||
return values[0];
|
||||
}
|
||||
@ -430,7 +660,7 @@ BSoundPlayer::SetVolumeDB(float volume_dB)
|
||||
values[i] = volume_dB;
|
||||
fVolumeSlider->SetValue(values, sizeof(float) * count, 0);
|
||||
|
||||
fVolume = volume_dB;
|
||||
fVolumeDB = volume_dB;
|
||||
fLastVolumeUpdate = system_time();
|
||||
}
|
||||
|
||||
@ -457,54 +687,12 @@ BSoundPlayer::GetVolumeInfo(media_node *out_node,
|
||||
}
|
||||
|
||||
|
||||
bigtime_t
|
||||
BSoundPlayer::Latency()
|
||||
{
|
||||
CALLED();
|
||||
if (fInitStatus != B_OK)
|
||||
return B_NO_INIT;
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::Latency: Couldn't get BMediaRoster\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bigtime_t latency;
|
||||
status_t err = roster->GetLatencyFor(fMediaOutput.node, &latency);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Latency: GetLatencyFor failed %ld (%s)\n", err, strerror(err));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return latency;
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ bool
|
||||
BSoundPlayer::HasData()
|
||||
{
|
||||
CALLED();
|
||||
return (atomic_read(&fFlags) & F_HAS_DATA) != 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BSoundPlayer::SetHasData(bool has_data)
|
||||
{
|
||||
CALLED();
|
||||
if (has_data)
|
||||
atomic_or(&fFlags, F_HAS_DATA);
|
||||
else
|
||||
atomic_and(&fFlags, ~F_HAS_DATA);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* protected BSoundPlayer
|
||||
*************************************************************/
|
||||
|
||||
//final
|
||||
|
||||
void
|
||||
BSoundPlayer::SetInitError(status_t in_error)
|
||||
{
|
||||
@ -551,10 +739,10 @@ BSoundPlayer::get_volume_slider()
|
||||
|
||||
int count = fParameterWeb->CountParameters();
|
||||
for (int i = 0; i < count; i++) {
|
||||
BParameter *parameter = web->ParameterAt(i);
|
||||
BParameter *parameter = fParameterWeb->ParameterAt(i);
|
||||
if (parameter->Type() != BParameter::B_CONTINUOUS_PARAMETER)
|
||||
continue;
|
||||
if (parameter->ID() >> 16) != fMediaInput.destination.id)
|
||||
if ((parameter->ID() >> 16) != fMediaInput.destination.id)
|
||||
continue;
|
||||
if (strcmp(parameter->Kind(), B_GAIN) != 0)
|
||||
continue;
|
||||
@ -563,151 +751,9 @@ BSoundPlayer::get_volume_slider()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BSoundPlayer::Init(
|
||||
const media_node * node,
|
||||
const media_multi_audio_format * format,
|
||||
const char * name,
|
||||
const media_input * input,
|
||||
void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format),
|
||||
void (*Notifier)(void *, sound_player_notification what, ...),
|
||||
void * cookie)
|
||||
{
|
||||
CALLED();
|
||||
fPlayerNode = NULL;
|
||||
_m_sounds = NULL;
|
||||
_m_waiting = NULL;
|
||||
fPlayBufferFunc = PlayBuffer;
|
||||
fNotifierFunc = Notifier;
|
||||
fVolume = 0.0f;
|
||||
_m_mix_buffer = 0;
|
||||
_m_mix_buffer_size = 0;
|
||||
fCookie = cookie;
|
||||
_m_buf = NULL;
|
||||
_m_bufsize = 0;
|
||||
fFlags = 0;
|
||||
fInitStatus = B_ERROR;
|
||||
_m_perfTime = 0;
|
||||
fVolumeSlider = NULL;
|
||||
fParameterWeb = NULL;
|
||||
fLastVolumeUpdate = 0;
|
||||
|
||||
fPlayerNode = 0;
|
||||
|
||||
status_t err;
|
||||
media_node mixerNode;
|
||||
media_output _output;
|
||||
media_input _input;
|
||||
int32 inputCount, outputCount;
|
||||
media_format tryFormat;
|
||||
media_multi_audio_format fmt;
|
||||
media_node timeSource;
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
if (!roster) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't get BMediaRoster\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//connect our producer node either to the
|
||||
//system mixer or to the supplied out node
|
||||
if (!node) {
|
||||
err = roster->GetAudioMixer(&mixerNode);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetAudioMixer\n");
|
||||
goto the_end;
|
||||
}
|
||||
node = &mixerNode;
|
||||
}
|
||||
|
||||
memcpy(&fmt,format,sizeof(fmt));
|
||||
|
||||
if (fmt.frame_rate == media_multi_audio_format::wildcard.frame_rate)
|
||||
fmt.frame_rate = 44100.0f;
|
||||
if (fmt.channel_count == media_multi_audio_format::wildcard.channel_count)
|
||||
fmt.channel_count = 2;
|
||||
if (fmt.format == media_multi_audio_format::wildcard.format)
|
||||
fmt.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
if (fmt.byte_order == media_multi_audio_format::wildcard.byte_order)
|
||||
fmt.byte_order = B_MEDIA_HOST_ENDIAN;
|
||||
if (fmt.buffer_size == media_multi_audio_format::wildcard.buffer_size)
|
||||
fmt.buffer_size = 4096;
|
||||
|
||||
if (fmt.channel_count != 1 && fmt.channel_count != 2)
|
||||
ERROR("BSoundPlayer: not a 1 or 2 channel audio format\n");
|
||||
if (fmt.frame_rate <= 0.0f)
|
||||
ERROR("BSoundPlayer: framerate must be > 0\n");
|
||||
|
||||
_m_bufsize = fmt.buffer_size;
|
||||
_m_buf = new char[_m_bufsize];
|
||||
fPlayerNode = new _SoundPlayNode(name,&fmt,this);
|
||||
|
||||
err = roster->RegisterNode(fPlayerNode);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't RegisterNode\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
// set the producer's time source to be the "default" time source, which
|
||||
// the Mixer uses too.
|
||||
|
||||
err = roster->GetTimeSource(&timeSource);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetTimeSource\n");
|
||||
goto the_end;
|
||||
}
|
||||
err = roster->SetTimeSourceFor(fPlayerNode->Node().node, timeSource.node);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't SetTimeSourceFor\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
if (!input) {
|
||||
err = roster->GetFreeInputsFor(*node, &_input, 1,
|
||||
&inputCount, B_MEDIA_RAW_AUDIO);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetFreeInputsFor\n");
|
||||
goto the_end;
|
||||
}
|
||||
} else {
|
||||
_input = *input;
|
||||
}
|
||||
err = roster->GetFreeOutputsFor(fPlayerNode->Node(), &_output, 1, &outputCount, B_MEDIA_RAW_AUDIO);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetFreeOutputsFor\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
// Set an appropriate run mode for the producer
|
||||
err = roster->SetRunModeNode(fPlayerNode->Node(), BMediaNode::B_INCREASE_LATENCY);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't SetRunModeNode\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
//tryFormat.type = B_MEDIA_RAW_AUDIO;
|
||||
//tryformat.fileAudioOutput.format;
|
||||
tryFormat = _output.format;
|
||||
err = roster->Connect(_output.source, _input.destination, &tryFormat, &fMediaOutput, &fMediaInput);
|
||||
if (err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't Connect\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
get_volume_slider();
|
||||
|
||||
|
||||
printf("BSoundPlayer node %ld has timesource %ld\n", fPlayerNode->Node().node, fPlayerNode->TimeSource()->Node().node);
|
||||
|
||||
the_end:
|
||||
TRACE("BSoundPlayer::Init: %s\n", strerror(err));
|
||||
SetInitError(err);
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
BSoundPlayer::Notify(sound_player_notification what,
|
||||
...)
|
||||
BSoundPlayer::Notify(sound_player_notification what, ...)
|
||||
{
|
||||
CALLED();
|
||||
if (fLocker.Lock()) {
|
||||
@ -719,9 +765,7 @@ BSoundPlayer::Notify(sound_player_notification what,
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
BSoundPlayer::PlayBuffer(void *buffer,
|
||||
size_t size,
|
||||
const media_raw_audio_format &format)
|
||||
BSoundPlayer::PlayBuffer(void *buffer, size_t size, const media_raw_audio_format &format)
|
||||
{
|
||||
if (fLocker.Lock()) {
|
||||
if (fPlayBufferFunc)
|
||||
@ -729,3 +773,24 @@ BSoundPlayer::PlayBuffer(void *buffer,
|
||||
fLocker.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* public sound_error
|
||||
*************************************************************/
|
||||
|
||||
|
||||
sound_error::sound_error(const char *str)
|
||||
{
|
||||
CALLED();
|
||||
m_str_const = str;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
sound_error::what() const
|
||||
{
|
||||
CALLED();
|
||||
return m_str_const;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user