152a38012Sejakowatz /*********************************************************************** 2*95531d1eSJérôme Duval * AUTHOR: Marcus Overhagen, Jérôme Duval 352a38012Sejakowatz * FILE: SoundPlayer.cpp 452a38012Sejakowatz * DESCR: 552a38012Sejakowatz ***********************************************************************/ 652a38012Sejakowatz #include <TimeSource.h> 7*95531d1eSJérôme Duval #include "SoundPlayer.h" 852a38012Sejakowatz #include <MediaRoster.h> 952a38012Sejakowatz #include <math.h> 1052a38012Sejakowatz 1152a38012Sejakowatz #include "debug.h" 1252a38012Sejakowatz #include "SoundPlayNode.h" 1352a38012Sejakowatz 1452a38012Sejakowatz /* this is the normal volume DB range of 16 bit integer */ 1552a38012Sejakowatz const float minDB = -96; 1652a38012Sejakowatz const float maxDB = 0; 1752a38012Sejakowatz 1852a38012Sejakowatz /************************************************************* 1952a38012Sejakowatz * public sound_error 2052a38012Sejakowatz *************************************************************/ 2152a38012Sejakowatz 2252a38012Sejakowatz //final 2352a38012Sejakowatz sound_error::sound_error(const char *str) 2452a38012Sejakowatz { 2552a38012Sejakowatz CALLED(); 2652a38012Sejakowatz m_str_const = str; 2752a38012Sejakowatz } 2852a38012Sejakowatz 2952a38012Sejakowatz //final 3052a38012Sejakowatz const char * 3152a38012Sejakowatz sound_error::what() const 3252a38012Sejakowatz { 3352a38012Sejakowatz CALLED(); 3452a38012Sejakowatz return m_str_const; 3552a38012Sejakowatz } 3652a38012Sejakowatz 3752a38012Sejakowatz /************************************************************* 3852a38012Sejakowatz * public BSoundPlayer 3952a38012Sejakowatz *************************************************************/ 4052a38012Sejakowatz 4152a38012Sejakowatz BSoundPlayer::BSoundPlayer(const char * name, 4252a38012Sejakowatz void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format), 4352a38012Sejakowatz void (*Notifier)(void *, sound_player_notification what, ...), 4452a38012Sejakowatz void * cookie) 4552a38012Sejakowatz { 4652a38012Sejakowatz CALLED(); 4752a38012Sejakowatz 4852a38012Sejakowatz Init(NULL,&media_multi_audio_format::wildcard,name,NULL,PlayBuffer,Notifier,cookie); 4952a38012Sejakowatz } 5052a38012Sejakowatz 5152a38012Sejakowatz BSoundPlayer::BSoundPlayer(const media_raw_audio_format * format, 5252a38012Sejakowatz const char * name, 5352a38012Sejakowatz void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format), 5452a38012Sejakowatz void (*Notifier)(void *, sound_player_notification what, ...), 5552a38012Sejakowatz void * cookie) 5652a38012Sejakowatz { 5752a38012Sejakowatz CALLED(); 5852a38012Sejakowatz media_multi_audio_format fmt = media_multi_audio_format::wildcard; 5952a38012Sejakowatz memcpy(&fmt,format,sizeof(*format)); 6052a38012Sejakowatz Init(NULL,&fmt,name,NULL,PlayBuffer,Notifier,cookie); 6152a38012Sejakowatz } 6252a38012Sejakowatz 6352a38012Sejakowatz BSoundPlayer::BSoundPlayer(const media_node & toNode, 6452a38012Sejakowatz const media_multi_audio_format * format, 6552a38012Sejakowatz const char * name, 6652a38012Sejakowatz const media_input * input, 6752a38012Sejakowatz void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format), 6852a38012Sejakowatz void (*Notifier)(void *, sound_player_notification what, ...), 6952a38012Sejakowatz void * cookie) 7052a38012Sejakowatz { 7152a38012Sejakowatz CALLED(); 7252a38012Sejakowatz if (toNode.kind & B_BUFFER_CONSUMER == 0) 7352a38012Sejakowatz debugger("BSoundPlayer: toNode must have B_BUFFER_CONSUMER kind!\n"); 7452a38012Sejakowatz Init(&toNode,format,name,input,PlayBuffer,Notifier,cookie); 7552a38012Sejakowatz } 7652a38012Sejakowatz 7752a38012Sejakowatz /* virtual */ 7852a38012Sejakowatz BSoundPlayer::~BSoundPlayer() 7952a38012Sejakowatz { 8052a38012Sejakowatz CALLED(); 81*95531d1eSJérôme Duval if (_m_node) { 82*95531d1eSJérôme Duval BMediaRoster *roster = BMediaRoster::Roster(); 83*95531d1eSJérôme Duval if (!roster) { 84*95531d1eSJérôme Duval TRACE("BSoundPlayer::~BSoundPlayer: Couldn't get BMediaRoster\n"); 85*95531d1eSJérôme Duval } else { 86*95531d1eSJérôme Duval status_t err; 87*95531d1eSJérôme Duval 88*95531d1eSJérôme Duval // Ordinarily we'd stop *all* of the nodes in the chain at this point. However, 89*95531d1eSJérôme Duval // one of the nodes is the System Mixer, and stopping the Mixer is a Bad Idea (tm). 90*95531d1eSJérôme Duval // So, we just disconnect from it, and release our references to the nodes that 91*95531d1eSJérôme Duval // we're using. We *are* supposed to do that even for global nodes like the Mixer. 92*95531d1eSJérôme Duval Stop(true, false); 93*95531d1eSJérôme Duval 94*95531d1eSJérôme Duval err = roster->Disconnect(m_input.node.node, m_input.source, 95*95531d1eSJérôme Duval m_output.node.node, m_output.destination); 96*95531d1eSJérôme Duval if (err) { 97*95531d1eSJérôme Duval fprintf(stderr, "* Error disconnecting nodes: %ld (%s)\n", err, strerror(err)); 98*95531d1eSJérôme Duval } 99*95531d1eSJérôme Duval 100*95531d1eSJérôme Duval err = roster->ReleaseNode(m_input.node); 101*95531d1eSJérôme Duval if (err) { 102*95531d1eSJérôme Duval fprintf(stderr, "* Error releasing input node: %ld (%s)\n", err, strerror(err)); 103*95531d1eSJérôme Duval } 104*95531d1eSJérôme Duval 105*95531d1eSJérôme Duval err = roster->ReleaseNode(m_output.node); 106*95531d1eSJérôme Duval if (err) { 107*95531d1eSJérôme Duval fprintf(stderr, "* Error releasing output node: %ld (%s)\n", err, strerror(err)); 108*95531d1eSJérôme Duval } 109*95531d1eSJérôme Duval _m_node = NULL; 110*95531d1eSJérôme Duval } 111*95531d1eSJérôme Duval } 11252a38012Sejakowatz delete [] _m_buf; 11352a38012Sejakowatz } 11452a38012Sejakowatz 11552a38012Sejakowatz 11652a38012Sejakowatz status_t 11752a38012Sejakowatz BSoundPlayer::InitCheck() 11852a38012Sejakowatz { 11952a38012Sejakowatz CALLED(); 12052a38012Sejakowatz return _m_init_err; 12152a38012Sejakowatz } 12252a38012Sejakowatz 12352a38012Sejakowatz 12452a38012Sejakowatz media_raw_audio_format 12552a38012Sejakowatz BSoundPlayer::Format() const 12652a38012Sejakowatz { 12752a38012Sejakowatz CALLED(); 12852a38012Sejakowatz 12952a38012Sejakowatz media_raw_audio_format temp = media_raw_audio_format::wildcard; 13052a38012Sejakowatz 13152a38012Sejakowatz if (_m_node) { 13252a38012Sejakowatz media_multi_audio_format fmt; 13352a38012Sejakowatz fmt = _m_node->Format(); 13452a38012Sejakowatz memcpy(&temp,&fmt,sizeof(temp)); 13552a38012Sejakowatz } 13652a38012Sejakowatz 13752a38012Sejakowatz return temp; 13852a38012Sejakowatz } 13952a38012Sejakowatz 14052a38012Sejakowatz 14152a38012Sejakowatz status_t 14252a38012Sejakowatz BSoundPlayer::Start() 14352a38012Sejakowatz { 14452a38012Sejakowatz CALLED(); 14552a38012Sejakowatz 14652a38012Sejakowatz if (!_m_node) 14752a38012Sejakowatz return B_ERROR; 14852a38012Sejakowatz 149*95531d1eSJérôme Duval BMediaRoster *roster = BMediaRoster::Roster(); 150*95531d1eSJérôme Duval if (!roster) { 151*95531d1eSJérôme Duval TRACE("BSoundPlayer::Start: Couldn't get BMediaRoster\n"); 152*95531d1eSJérôme Duval return B_ERROR; 153*95531d1eSJérôme Duval } 154*95531d1eSJérôme Duval 155*95531d1eSJérôme Duval BTimeSource *timeSource = roster->MakeTimeSourceFor(_m_node->Node()); 156*95531d1eSJérôme Duval 157*95531d1eSJérôme Duval // make sure we give the producer enough time to run buffers through 158*95531d1eSJérôme Duval // the node chain, otherwise it'll start up already late 159*95531d1eSJérôme Duval bigtime_t latency = 0; 160*95531d1eSJérôme Duval status_t err = roster->GetLatencyFor(_m_node->Node(), &latency); 161*95531d1eSJérôme Duval 162*95531d1eSJérôme Duval err = roster->StartNode(_m_node->Node(), timeSource->Now() + latency); 163*95531d1eSJérôme Duval 164*95531d1eSJérôme Duval timeSource->Release(); 165*95531d1eSJérôme Duval 166*95531d1eSJérôme Duval return err; 16752a38012Sejakowatz } 16852a38012Sejakowatz 16952a38012Sejakowatz 17052a38012Sejakowatz void 17152a38012Sejakowatz BSoundPlayer::Stop(bool block, 17252a38012Sejakowatz bool flush) 17352a38012Sejakowatz { 17452a38012Sejakowatz CALLED(); 17552a38012Sejakowatz 17652a38012Sejakowatz if (!_m_node) 17752a38012Sejakowatz return; 17852a38012Sejakowatz 179*95531d1eSJérôme Duval BMediaRoster *roster = BMediaRoster::Roster(); 180*95531d1eSJérôme Duval if (!roster) { 181*95531d1eSJérôme Duval TRACE("BSoundPlayer::Stop: Couldn't get BMediaRoster\n"); 182*95531d1eSJérôme Duval return; 183*95531d1eSJérôme Duval } 184*95531d1eSJérôme Duval 185*95531d1eSJérôme Duval roster->StopNode(_m_node->Node(), 0, true); 186*95531d1eSJérôme Duval 18752a38012Sejakowatz } 18852a38012Sejakowatz 18952a38012Sejakowatz BSoundPlayer::BufferPlayerFunc 19052a38012Sejakowatz BSoundPlayer::BufferPlayer() const 19152a38012Sejakowatz { 19252a38012Sejakowatz CALLED(); 19352a38012Sejakowatz return _PlayBuffer; 19452a38012Sejakowatz } 19552a38012Sejakowatz 19652a38012Sejakowatz void BSoundPlayer::SetBufferPlayer(void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format)) 19752a38012Sejakowatz { 19852a38012Sejakowatz CALLED(); 19952a38012Sejakowatz _m_lock.Lock(); 20052a38012Sejakowatz _PlayBuffer = PlayBuffer; 20152a38012Sejakowatz _m_lock.Unlock(); 20252a38012Sejakowatz } 20352a38012Sejakowatz 20452a38012Sejakowatz BSoundPlayer::EventNotifierFunc 20552a38012Sejakowatz BSoundPlayer::EventNotifier() const 20652a38012Sejakowatz { 20752a38012Sejakowatz CALLED(); 20852a38012Sejakowatz return _Notifier; 20952a38012Sejakowatz } 21052a38012Sejakowatz 21152a38012Sejakowatz void BSoundPlayer::SetNotifier(void (*Notifier)(void *, sound_player_notification what, ...)) 21252a38012Sejakowatz { 21352a38012Sejakowatz CALLED(); 21452a38012Sejakowatz _m_lock.Lock(); 21552a38012Sejakowatz _Notifier = Notifier; 21652a38012Sejakowatz _m_lock.Unlock(); 21752a38012Sejakowatz } 21852a38012Sejakowatz 21952a38012Sejakowatz void * 22052a38012Sejakowatz BSoundPlayer::Cookie() const 22152a38012Sejakowatz { 22252a38012Sejakowatz CALLED(); 22352a38012Sejakowatz return _m_cookie; 22452a38012Sejakowatz } 22552a38012Sejakowatz 22652a38012Sejakowatz void 22752a38012Sejakowatz BSoundPlayer::SetCookie(void *cookie) 22852a38012Sejakowatz { 22952a38012Sejakowatz CALLED(); 23052a38012Sejakowatz _m_lock.Lock(); 23152a38012Sejakowatz _m_cookie = cookie; 23252a38012Sejakowatz _m_lock.Unlock(); 23352a38012Sejakowatz } 23452a38012Sejakowatz 23552a38012Sejakowatz void BSoundPlayer::SetCallbacks(void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format), 23652a38012Sejakowatz void (*Notifier)(void *, sound_player_notification what, ...), 23752a38012Sejakowatz void * cookie) 23852a38012Sejakowatz { 23952a38012Sejakowatz CALLED(); 24052a38012Sejakowatz _m_lock.Lock(); 24152a38012Sejakowatz SetBufferPlayer(PlayBuffer); 24252a38012Sejakowatz SetNotifier(Notifier); 24352a38012Sejakowatz SetCookie(cookie); 24452a38012Sejakowatz _m_lock.Unlock(); 24552a38012Sejakowatz } 24652a38012Sejakowatz 24752a38012Sejakowatz 24852a38012Sejakowatz bigtime_t 24952a38012Sejakowatz BSoundPlayer::CurrentTime() 25052a38012Sejakowatz { 25152a38012Sejakowatz CALLED(); 25252a38012Sejakowatz if (!_m_node) 25352a38012Sejakowatz return system_time(); 254*95531d1eSJérôme Duval 255*95531d1eSJérôme Duval return _m_node->TimeSource()->Now(); 25652a38012Sejakowatz } 25752a38012Sejakowatz 25852a38012Sejakowatz 25952a38012Sejakowatz bigtime_t 26052a38012Sejakowatz BSoundPlayer::PerformanceTime() 26152a38012Sejakowatz { 26252a38012Sejakowatz CALLED(); 26352a38012Sejakowatz if (!_m_node) 26452a38012Sejakowatz return (bigtime_t) B_ERROR; 265*95531d1eSJérôme Duval 266*95531d1eSJérôme Duval return _m_node->TimeSource()->Now(); 26752a38012Sejakowatz } 26852a38012Sejakowatz 26952a38012Sejakowatz 27052a38012Sejakowatz status_t 27152a38012Sejakowatz BSoundPlayer::Preroll() 27252a38012Sejakowatz { 273*95531d1eSJérôme Duval CALLED(); 27452a38012Sejakowatz 275*95531d1eSJérôme Duval BMediaRoster *roster = BMediaRoster::Roster(); 276*95531d1eSJérôme Duval if (!roster) { 277*95531d1eSJérôme Duval TRACE("BSoundPlayer::Preroll: Couldn't get BMediaRoster\n"); 278*95531d1eSJérôme Duval return B_ERROR; 279*95531d1eSJérôme Duval } 280*95531d1eSJérôme Duval 281*95531d1eSJérôme Duval status_t err = roster->PrerollNode(m_output.node); 282*95531d1eSJérôme Duval 283*95531d1eSJérôme Duval if(err != B_OK) { 284*95531d1eSJérôme Duval fprintf(stderr, "Error while PrerollNode: %ld (%s)\n", err, strerror(err)); 285*95531d1eSJérôme Duval } 286*95531d1eSJérôme Duval 287*95531d1eSJérôme Duval return err; 28852a38012Sejakowatz } 28952a38012Sejakowatz 29052a38012Sejakowatz 29152a38012Sejakowatz BSoundPlayer::play_id 29252a38012Sejakowatz BSoundPlayer::StartPlaying(BSound *sound, 29352a38012Sejakowatz bigtime_t at_time) 29452a38012Sejakowatz { 29552a38012Sejakowatz UNIMPLEMENTED(); 29652a38012Sejakowatz return 1; 29752a38012Sejakowatz } 29852a38012Sejakowatz 29952a38012Sejakowatz 30052a38012Sejakowatz BSoundPlayer::play_id 30152a38012Sejakowatz BSoundPlayer::StartPlaying(BSound *sound, 30252a38012Sejakowatz bigtime_t at_time, 30352a38012Sejakowatz float with_volume) 30452a38012Sejakowatz { 30552a38012Sejakowatz UNIMPLEMENTED(); 30652a38012Sejakowatz return 1; 30752a38012Sejakowatz } 30852a38012Sejakowatz 30952a38012Sejakowatz 31052a38012Sejakowatz status_t 31152a38012Sejakowatz BSoundPlayer::SetSoundVolume(play_id sound, 31252a38012Sejakowatz float new_volume) 31352a38012Sejakowatz { 31452a38012Sejakowatz UNIMPLEMENTED(); 31552a38012Sejakowatz 31652a38012Sejakowatz return B_OK; 31752a38012Sejakowatz } 31852a38012Sejakowatz 31952a38012Sejakowatz 32052a38012Sejakowatz bool 32152a38012Sejakowatz BSoundPlayer::IsPlaying(play_id id) 32252a38012Sejakowatz { 32352a38012Sejakowatz UNIMPLEMENTED(); 32452a38012Sejakowatz 32552a38012Sejakowatz return true; 32652a38012Sejakowatz } 32752a38012Sejakowatz 32852a38012Sejakowatz 32952a38012Sejakowatz status_t 33052a38012Sejakowatz BSoundPlayer::StopPlaying(play_id id) 33152a38012Sejakowatz { 33252a38012Sejakowatz UNIMPLEMENTED(); 33352a38012Sejakowatz 33452a38012Sejakowatz return B_OK; 33552a38012Sejakowatz } 33652a38012Sejakowatz 33752a38012Sejakowatz 33852a38012Sejakowatz status_t 33952a38012Sejakowatz BSoundPlayer::WaitForSound(play_id id) 34052a38012Sejakowatz { 34152a38012Sejakowatz UNIMPLEMENTED(); 34252a38012Sejakowatz 34352a38012Sejakowatz return B_OK; 34452a38012Sejakowatz } 34552a38012Sejakowatz 34652a38012Sejakowatz 34752a38012Sejakowatz float 34852a38012Sejakowatz BSoundPlayer::Volume() 34952a38012Sejakowatz { 35052a38012Sejakowatz CALLED(); 35152a38012Sejakowatz return _m_volume; 35252a38012Sejakowatz } 35352a38012Sejakowatz 35452a38012Sejakowatz 35552a38012Sejakowatz void 35652a38012Sejakowatz BSoundPlayer::SetVolume(float new_volume) 35752a38012Sejakowatz { 35852a38012Sejakowatz CALLED(); 35952a38012Sejakowatz _m_lock.Lock(); 36052a38012Sejakowatz if (new_volume >= 0.0f) 36152a38012Sejakowatz _m_volume = new_volume; 36252a38012Sejakowatz _m_lock.Unlock(); 36352a38012Sejakowatz } 36452a38012Sejakowatz 36552a38012Sejakowatz 36652a38012Sejakowatz float 36752a38012Sejakowatz BSoundPlayer::VolumeDB(bool forcePoll) 36852a38012Sejakowatz { 36952a38012Sejakowatz CALLED(); 37052a38012Sejakowatz return 20.0f * log10(_m_volume); 37152a38012Sejakowatz } 37252a38012Sejakowatz 37352a38012Sejakowatz 37452a38012Sejakowatz void 37552a38012Sejakowatz BSoundPlayer::SetVolumeDB(float volume_dB) 37652a38012Sejakowatz { 37752a38012Sejakowatz CALLED(); 37852a38012Sejakowatz _m_lock.Lock(); 37952a38012Sejakowatz _m_volume = pow(10.0f,volume_dB / 20.0f); 38052a38012Sejakowatz _m_lock.Unlock(); 38152a38012Sejakowatz } 38252a38012Sejakowatz 38352a38012Sejakowatz 38452a38012Sejakowatz status_t 38552a38012Sejakowatz BSoundPlayer::GetVolumeInfo(media_node *out_node, 38652a38012Sejakowatz int32 *out_parameter, 38752a38012Sejakowatz float *out_min_dB, 38852a38012Sejakowatz float *out_max_dB) 38952a38012Sejakowatz { 39052a38012Sejakowatz BROKEN(); 39152a38012Sejakowatz 39252a38012Sejakowatz *out_node = m_output.node; 39352a38012Sejakowatz *out_parameter = -1; /* is the parameter ID for the volume control */ 39452a38012Sejakowatz *out_min_dB = minDB; 39552a38012Sejakowatz *out_max_dB = maxDB; 39652a38012Sejakowatz 39752a38012Sejakowatz return B_OK; 39852a38012Sejakowatz } 39952a38012Sejakowatz 40052a38012Sejakowatz 40152a38012Sejakowatz bigtime_t 40252a38012Sejakowatz BSoundPlayer::Latency() 40352a38012Sejakowatz { 404*95531d1eSJérôme Duval CALLED(); 405*95531d1eSJérôme Duval 406*95531d1eSJérôme Duval BMediaRoster *roster = BMediaRoster::Roster(); 407*95531d1eSJérôme Duval if (!roster) { 408*95531d1eSJérôme Duval TRACE("BSoundPlayer::Latency: Couldn't get BMediaRoster\n"); 409*95531d1eSJérôme Duval return 0; 410*95531d1eSJérôme Duval } 411*95531d1eSJérôme Duval 412*95531d1eSJérôme Duval bigtime_t latency = 0; 413*95531d1eSJérôme Duval status_t err = roster->GetLatencyFor(m_output.node, &latency); 414*95531d1eSJérôme Duval 415*95531d1eSJérôme Duval if(err != B_OK) { 416*95531d1eSJérôme Duval fprintf(stderr, "Error while GetLatencyFor: %ld (%s)\n", err, strerror(err)); 417*95531d1eSJérôme Duval } 418*95531d1eSJérôme Duval 419*95531d1eSJérôme Duval return latency; 42052a38012Sejakowatz } 42152a38012Sejakowatz 42252a38012Sejakowatz 42352a38012Sejakowatz /* virtual */ bool 42452a38012Sejakowatz BSoundPlayer::HasData() 42552a38012Sejakowatz { 42652a38012Sejakowatz CALLED(); 42752a38012Sejakowatz 42852a38012Sejakowatz return _m_has_data != 0; 42952a38012Sejakowatz } 43052a38012Sejakowatz 43152a38012Sejakowatz 43252a38012Sejakowatz void 43352a38012Sejakowatz BSoundPlayer::SetHasData(bool has_data) 43452a38012Sejakowatz { 43552a38012Sejakowatz CALLED(); 43652a38012Sejakowatz _m_lock.Lock(); 43752a38012Sejakowatz _m_has_data = has_data ? 1 : 0; 43852a38012Sejakowatz _m_lock.Unlock(); 43952a38012Sejakowatz } 44052a38012Sejakowatz 44152a38012Sejakowatz 44252a38012Sejakowatz /************************************************************* 44352a38012Sejakowatz * protected BSoundPlayer 44452a38012Sejakowatz *************************************************************/ 44552a38012Sejakowatz 44652a38012Sejakowatz //final 44752a38012Sejakowatz void 44852a38012Sejakowatz BSoundPlayer::SetInitError(status_t in_error) 44952a38012Sejakowatz { 45052a38012Sejakowatz CALLED(); 45152a38012Sejakowatz _m_init_err = in_error; 45252a38012Sejakowatz } 45352a38012Sejakowatz 45452a38012Sejakowatz 45552a38012Sejakowatz /************************************************************* 45652a38012Sejakowatz * private BSoundPlayer 45752a38012Sejakowatz *************************************************************/ 45852a38012Sejakowatz 45952a38012Sejakowatz status_t BSoundPlayer::_Reserved_SoundPlayer_0(void *, ...) { return B_ERROR; } 46052a38012Sejakowatz status_t BSoundPlayer::_Reserved_SoundPlayer_1(void *, ...) { return B_ERROR; } 46152a38012Sejakowatz status_t BSoundPlayer::_Reserved_SoundPlayer_2(void *, ...) { return B_ERROR; } 46252a38012Sejakowatz status_t BSoundPlayer::_Reserved_SoundPlayer_3(void *, ...) { return B_ERROR; } 46352a38012Sejakowatz status_t BSoundPlayer::_Reserved_SoundPlayer_4(void *, ...) { return B_ERROR; } 46452a38012Sejakowatz status_t BSoundPlayer::_Reserved_SoundPlayer_5(void *, ...) { return B_ERROR; } 46552a38012Sejakowatz status_t BSoundPlayer::_Reserved_SoundPlayer_6(void *, ...) { return B_ERROR; } 46652a38012Sejakowatz status_t BSoundPlayer::_Reserved_SoundPlayer_7(void *, ...) { return B_ERROR; } 46752a38012Sejakowatz 46852a38012Sejakowatz 46952a38012Sejakowatz void 47052a38012Sejakowatz BSoundPlayer::NotifySoundDone(play_id sound, 47152a38012Sejakowatz bool got_to_play) 47252a38012Sejakowatz { 47352a38012Sejakowatz UNIMPLEMENTED(); 47452a38012Sejakowatz } 47552a38012Sejakowatz 47652a38012Sejakowatz 47752a38012Sejakowatz void 47852a38012Sejakowatz BSoundPlayer::get_volume_slider() 47952a38012Sejakowatz { 48052a38012Sejakowatz UNIMPLEMENTED(); 48152a38012Sejakowatz } 48252a38012Sejakowatz 48352a38012Sejakowatz void 48452a38012Sejakowatz BSoundPlayer::Init( 48552a38012Sejakowatz const media_node * node, 48652a38012Sejakowatz const media_multi_audio_format * format, 48752a38012Sejakowatz const char * name, 48852a38012Sejakowatz const media_input * input, 48952a38012Sejakowatz void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format), 49052a38012Sejakowatz void (*Notifier)(void *, sound_player_notification what, ...), 49152a38012Sejakowatz void * cookie) 49252a38012Sejakowatz { 49352a38012Sejakowatz BROKEN(); 49452a38012Sejakowatz _m_node = NULL; 49552a38012Sejakowatz _m_sounds = NULL; 49652a38012Sejakowatz _m_waiting = NULL; 49752a38012Sejakowatz _PlayBuffer = PlayBuffer; 49852a38012Sejakowatz _Notifier = Notifier; 49952a38012Sejakowatz _m_volume = 0.0f; 50052a38012Sejakowatz _m_mix_buffer = 0; 50152a38012Sejakowatz _m_mix_buffer_size = 0; 50252a38012Sejakowatz _m_cookie = cookie; 50352a38012Sejakowatz _m_buf = NULL; 50452a38012Sejakowatz _m_bufsize = 0; 50552a38012Sejakowatz _m_has_data = 0; 50652a38012Sejakowatz _m_init_err = B_ERROR; 50752a38012Sejakowatz _m_perfTime = 0; 50852a38012Sejakowatz _m_volumeSlider = NULL; 50952a38012Sejakowatz _m_gotVolume = 0; 51052a38012Sejakowatz 51152a38012Sejakowatz _m_node = 0; 51252a38012Sejakowatz 513*95531d1eSJérôme Duval status_t err; 514*95531d1eSJérôme Duval media_node outputNode; 515*95531d1eSJérôme Duval media_output _output; 516*95531d1eSJérôme Duval media_input _input; 517*95531d1eSJérôme Duval int32 inputCount, outputCount; 518*95531d1eSJérôme Duval media_format tryFormat; 519*95531d1eSJérôme Duval media_multi_audio_format fmt; 520*95531d1eSJérôme Duval media_node timeSource; 521*95531d1eSJérôme Duval 522*95531d1eSJérôme Duval BMediaRoster *roster = BMediaRoster::Roster(); 52352a38012Sejakowatz if (!roster) { 52452a38012Sejakowatz TRACE("BSoundPlayer::Init: Couldn't get BMediaRoster\n"); 52552a38012Sejakowatz return; 52652a38012Sejakowatz } 52752a38012Sejakowatz 52852a38012Sejakowatz //connect our producer node either to the 52952a38012Sejakowatz //system mixer or to the supplied out node 53052a38012Sejakowatz if (!node) { 531*95531d1eSJérôme Duval err = roster->GetAudioMixer(&outputNode); 532*95531d1eSJérôme Duval if (err != B_OK) { 53352a38012Sejakowatz TRACE("BSoundPlayer::Init: Couldn't GetAudioMixer\n"); 534*95531d1eSJérôme Duval goto the_end; 53552a38012Sejakowatz } 536*95531d1eSJérôme Duval node = &outputNode; 53752a38012Sejakowatz } 53852a38012Sejakowatz 53952a38012Sejakowatz memcpy(&fmt,format,sizeof(fmt)); 54052a38012Sejakowatz 54152a38012Sejakowatz if (fmt.frame_rate == media_multi_audio_format::wildcard.frame_rate) 54252a38012Sejakowatz fmt.frame_rate = 44100.0f; 54352a38012Sejakowatz if (fmt.channel_count == media_multi_audio_format::wildcard.channel_count) 54452a38012Sejakowatz fmt.channel_count = 2; 54552a38012Sejakowatz if (fmt.format == media_multi_audio_format::wildcard.format) 54652a38012Sejakowatz fmt.format = media_raw_audio_format::B_AUDIO_FLOAT; 54752a38012Sejakowatz if (fmt.byte_order == media_multi_audio_format::wildcard.byte_order) 54852a38012Sejakowatz fmt.byte_order = B_MEDIA_HOST_ENDIAN; 54952a38012Sejakowatz if (fmt.buffer_size == media_multi_audio_format::wildcard.buffer_size) 55052a38012Sejakowatz fmt.buffer_size = 4096; 55152a38012Sejakowatz 55252a38012Sejakowatz if (fmt.channel_count != 1 && fmt.channel_count != 2) 55352a38012Sejakowatz debugger("BSoundPlayer: not a 1 or 2 channel audio format\n"); 55452a38012Sejakowatz if (fmt.frame_rate <= 0.0f) 55552a38012Sejakowatz debugger("BSoundPlayer: framerate must be > 0\n"); 55652a38012Sejakowatz 55752a38012Sejakowatz _m_bufsize = fmt.buffer_size; 55852a38012Sejakowatz _m_buf = new char[_m_bufsize]; 55952a38012Sejakowatz _m_node = new _SoundPlayNode(name,&fmt,this); 56052a38012Sejakowatz 561*95531d1eSJérôme Duval err = roster->RegisterNode(_m_node); 562*95531d1eSJérôme Duval if(err != B_OK) { 563*95531d1eSJérôme Duval TRACE("BSoundPlayer::Init: Couldn't RegisterNode\n"); 564*95531d1eSJérôme Duval goto the_end; 565*95531d1eSJérôme Duval } 56652a38012Sejakowatz 567*95531d1eSJérôme Duval // set the producer's time source to be the "default" time source, which 568*95531d1eSJérôme Duval // the Mixer uses too. 56952a38012Sejakowatz 570*95531d1eSJérôme Duval roster->GetTimeSource(&timeSource); 571*95531d1eSJérôme Duval roster->SetTimeSourceFor(_m_node->Node().node, timeSource.node); 57252a38012Sejakowatz 573*95531d1eSJérôme Duval if(!input) { 574*95531d1eSJérôme Duval err = roster->GetFreeInputsFor(*node, &_input, 1, 575*95531d1eSJérôme Duval &inputCount, B_MEDIA_RAW_AUDIO); 576*95531d1eSJérôme Duval if(err != B_OK) { 577*95531d1eSJérôme Duval TRACE("BSoundPlayer::Init: Couldn't GetFreeInputsFor\n"); 578*95531d1eSJérôme Duval goto the_end; 579*95531d1eSJérôme Duval } 580*95531d1eSJérôme Duval } else { 581*95531d1eSJérôme Duval _input = *input; 582*95531d1eSJérôme Duval } 583*95531d1eSJérôme Duval err = roster->GetFreeOutputsFor(_m_node->Node(), &_output, 1, &outputCount, B_MEDIA_RAW_AUDIO); 584*95531d1eSJérôme Duval if(err != B_OK) { 585*95531d1eSJérôme Duval TRACE("BSoundPlayer::Init: Couldn't GetFreeOutputsFor\n"); 586*95531d1eSJérôme Duval goto the_end; 587*95531d1eSJérôme Duval } 58852a38012Sejakowatz 589*95531d1eSJérôme Duval //tryFormat.type = B_MEDIA_RAW_AUDIO; 590*95531d1eSJérôme Duval //tryformat.fileAudioOutput.format; 591*95531d1eSJérôme Duval tryFormat = _output.format; 592*95531d1eSJérôme Duval err = roster->Connect(_output.source, _input.destination, &tryFormat, &m_output, &m_input); 593*95531d1eSJérôme Duval if(err != B_OK) { 594*95531d1eSJérôme Duval TRACE("BSoundPlayer::Init: Couldn't Connect\n"); 595*95531d1eSJérôme Duval goto the_end; 596*95531d1eSJérôme Duval } 59752a38012Sejakowatz 598*95531d1eSJérôme Duval // Set an appropriate run mode for the producer 599*95531d1eSJérôme Duval err = roster->SetRunModeNode(_m_node->Node(), BMediaNode::B_INCREASE_LATENCY); 600*95531d1eSJérôme Duval if(err != B_OK) { 601*95531d1eSJérôme Duval TRACE("BSoundPlayer::Init: Couldn't SetRunModeNode\n"); 602*95531d1eSJérôme Duval goto the_end; 603*95531d1eSJérôme Duval } 60452a38012Sejakowatz 605*95531d1eSJérôme Duval the_end: 606*95531d1eSJérôme Duval TRACE("BSoundPlayer::Init: %s\n", strerror(err)); 607*95531d1eSJérôme Duval SetInitError(err); 60852a38012Sejakowatz } 60952a38012Sejakowatz 61052a38012Sejakowatz /* virtual */ void 61152a38012Sejakowatz BSoundPlayer::Notify(sound_player_notification what, 61252a38012Sejakowatz ...) 61352a38012Sejakowatz { 61452a38012Sejakowatz CALLED(); 61552a38012Sejakowatz _m_lock.Lock(); 61652a38012Sejakowatz if (_Notifier) 61752a38012Sejakowatz (*_Notifier)(_m_cookie,what); 61852a38012Sejakowatz else { 61952a38012Sejakowatz } 62052a38012Sejakowatz _m_lock.Unlock(); 62152a38012Sejakowatz } 62252a38012Sejakowatz 62352a38012Sejakowatz 62452a38012Sejakowatz /* virtual */ void 62552a38012Sejakowatz BSoundPlayer::PlayBuffer(void *buffer, 62652a38012Sejakowatz size_t size, 62752a38012Sejakowatz const media_raw_audio_format &format) 62852a38012Sejakowatz { 62952a38012Sejakowatz // CALLED(); 63052a38012Sejakowatz _m_lock.Lock(); 63152a38012Sejakowatz if (_PlayBuffer) 63252a38012Sejakowatz (*_PlayBuffer)(_m_cookie,buffer,size,format); 63352a38012Sejakowatz else { 63452a38012Sejakowatz } 63552a38012Sejakowatz _m_lock.Unlock(); 63652a38012Sejakowatz } 63752a38012Sejakowatz 63852a38012Sejakowatz 639