tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / media / SoundPlayer.cpp
blob42db720bca21e7ce145571e3a82d189245359740
1 /*
2 * Copyright 2002-2009, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marcus Overhagen
7 * Jérôme Duval
8 */
11 #include <SoundPlayer.h>
13 #include <math.h>
14 #include <string.h>
16 #include <Autolock.h>
17 #include <MediaRoster.h>
18 #include <ParameterWeb.h>
19 #include <Sound.h>
20 #include <TimeSource.h>
22 #include "SoundPlayNode.h"
24 #include "debug.h"
27 // Flags used internally in BSoundPlayer
28 enum {
29 F_NODES_CONNECTED = (1 << 0),
30 F_HAS_DATA = (1 << 1),
31 F_IS_STARTED = (1 << 2),
32 F_MUST_RELEASE_MIXER = (1 << 3),
36 static BSoundPlayer::play_id sCurrentPlayID = 1;
39 BSoundPlayer::BSoundPlayer(const char* name, BufferPlayerFunc playerFunction,
40 EventNotifierFunc eventNotifierFunction, void* cookie)
42 CALLED();
44 TRACE("BSoundPlayer::BSoundPlayer: default constructor used\n");
46 media_multi_audio_format format = media_multi_audio_format::wildcard;
48 _Init(NULL, &format, name, NULL, playerFunction, eventNotifierFunction,
49 cookie);
53 BSoundPlayer::BSoundPlayer(const media_raw_audio_format* _format,
54 const char* name, BufferPlayerFunc playerFunction,
55 EventNotifierFunc eventNotifierFunction, void* cookie)
57 CALLED();
59 TRACE("BSoundPlayer::BSoundPlayer: raw audio format constructor used\n");
61 media_multi_audio_format format = media_multi_audio_format::wildcard;
62 *(media_raw_audio_format*)&format = *_format;
64 #if DEBUG > 0
65 char buf[100];
66 media_format tmp; tmp.type = B_MEDIA_RAW_AUDIO; tmp.u.raw_audio = format;
67 string_for_format(tmp, buf, sizeof(buf));
68 TRACE("BSoundPlayer::BSoundPlayer: format %s\n", buf);
69 #endif
71 _Init(NULL, &format, name, NULL, playerFunction, eventNotifierFunction,
72 cookie);
76 BSoundPlayer::BSoundPlayer(const media_node& toNode,
77 const media_multi_audio_format* format, const char* name,
78 const media_input* input, BufferPlayerFunc playerFunction,
79 EventNotifierFunc eventNotifierFunction, void* cookie)
81 CALLED();
83 TRACE("BSoundPlayer::BSoundPlayer: multi audio format constructor used\n");
85 if ((toNode.kind & B_BUFFER_CONSUMER) == 0)
86 debugger("BSoundPlayer: toNode must have B_BUFFER_CONSUMER kind!\n");
88 #if DEBUG > 0
89 char buf[100];
90 media_format tmp; tmp.type = B_MEDIA_RAW_AUDIO; tmp.u.raw_audio = *format;
91 string_for_format(tmp, buf, sizeof(buf));
92 TRACE("BSoundPlayer::BSoundPlayer: format %s\n", buf);
93 #endif
95 _Init(&toNode, format, name, input, playerFunction, eventNotifierFunction,
96 cookie);
100 BSoundPlayer::~BSoundPlayer()
102 CALLED();
104 if ((fFlags & F_IS_STARTED) != 0) {
105 // block, but don't flush
106 Stop(true, false);
109 status_t err;
110 BMediaRoster* roster = BMediaRoster::Roster();
111 if (roster == NULL) {
112 TRACE("BSoundPlayer::~BSoundPlayer: Couldn't get BMediaRoster\n");
113 goto cleanup;
116 if ((fFlags & F_NODES_CONNECTED) != 0) {
117 // Ordinarily we'd stop *all* of the nodes in the chain before
118 // disconnecting. However, our node is already stopped, and we can't
119 // stop the System Mixer.
120 // So, we just disconnect from it, and release our references to the
121 // nodes that we're using. We *are* supposed to do that even for global
122 // nodes like the Mixer.
123 err = roster->Disconnect(fMediaOutput, fMediaInput);
124 if (err != B_OK) {
125 TRACE("BSoundPlayer::~BSoundPlayer: Error disconnecting nodes: "
126 "%ld (%s)\n", err, strerror(err));
130 if ((fFlags & F_MUST_RELEASE_MIXER) != 0) {
131 // Release the mixer as it was acquired
132 // through BMediaRoster::GetAudioMixer()
133 err = roster->ReleaseNode(fMediaInput.node);
134 if (err != B_OK) {
135 TRACE("BSoundPlayer::~BSoundPlayer: Error releasing input node: "
136 "%ld (%s)\n", err, strerror(err));
140 cleanup:
141 // Dispose of the player node
143 // We do not call BMediaRoster::ReleaseNode(), since
144 // the player was created by using "new". We could
145 // call BMediaRoster::UnregisterNode(), but this is
146 // supposed to be done by BMediaNode destructor automatically
147 delete fPlayerNode;
149 // do not delete fVolumeSlider, it belongs to the parameter web
150 delete fParameterWeb;
154 status_t
155 BSoundPlayer::InitCheck()
157 CALLED();
158 return fInitStatus;
162 media_raw_audio_format
163 BSoundPlayer::Format() const
165 CALLED();
167 if ((fFlags & F_NODES_CONNECTED) == 0)
168 return media_raw_audio_format::wildcard;
170 return fPlayerNode->Format();
174 status_t
175 BSoundPlayer::Start()
177 CALLED();
179 if ((fFlags & F_NODES_CONNECTED) == 0)
180 return B_NO_INIT;
182 if ((fFlags & F_IS_STARTED) != 0)
183 return B_OK;
185 BMediaRoster* roster = BMediaRoster::Roster();
186 if (!roster) {
187 TRACE("BSoundPlayer::Start: Couldn't get BMediaRoster\n");
188 return B_ERROR;
191 if (!fPlayerNode->TimeSource()->IsRunning()) {
192 roster->StartTimeSource(fPlayerNode->TimeSource()->Node(),
193 fPlayerNode->TimeSource()->RealTime());
196 // Add latency and a few ms to the nodes current time to
197 // make sure that we give the producer enough time to run
198 // buffers through the node chain, otherwise it'll start
199 // up already late
201 status_t err = roster->StartNode(fPlayerNode->Node(),
202 fPlayerNode->TimeSource()->Now() + Latency() + 5000);
203 if (err != B_OK) {
204 TRACE("BSoundPlayer::Start: StartNode failed, %ld", err);
205 return err;
208 if (fNotifierFunc != NULL)
209 fNotifierFunc(fCookie, B_STARTED, this);
211 SetHasData(true);
212 atomic_or(&fFlags, F_IS_STARTED);
214 return B_OK;
218 void
219 BSoundPlayer::Stop(bool block, bool flush)
221 CALLED();
223 TRACE("BSoundPlayer::Stop: block %d, flush %d\n", (int)block, (int)flush);
225 if ((fFlags & F_NODES_CONNECTED) == 0)
226 return;
228 // TODO: flush is ignored
230 if ((fFlags & F_IS_STARTED) != 0) {
231 BMediaRoster* roster = BMediaRoster::Roster();
232 if (roster == NULL) {
233 TRACE("BSoundPlayer::Stop: Couldn't get BMediaRoster\n");
234 return;
237 roster->StopNode(fPlayerNode->Node(), 0, true);
239 atomic_and(&fFlags, ~F_IS_STARTED);
242 if (block) {
243 // wait until the node is stopped
244 int tries;
245 for (tries = 250; fPlayerNode->IsPlaying() && tries != 0; tries--)
246 snooze(2000);
248 DEBUG_ONLY(if (tries == 0)
249 TRACE("BSoundPlayer::Stop: waiting for node stop failed\n"));
251 // Wait until all buffers on the way to the physical output have been
252 // played
253 snooze(Latency() + 2000);
256 if (fNotifierFunc)
257 fNotifierFunc(fCookie, B_STOPPED, this);
262 bigtime_t
263 BSoundPlayer::Latency()
265 CALLED();
267 if ((fFlags & F_NODES_CONNECTED) == 0)
268 return 0;
270 BMediaRoster *roster = BMediaRoster::Roster();
271 if (!roster) {
272 TRACE("BSoundPlayer::Latency: Couldn't get BMediaRoster\n");
273 return 0;
276 bigtime_t latency;
277 status_t err = roster->GetLatencyFor(fMediaOutput.node, &latency);
278 if (err != B_OK) {
279 TRACE("BSoundPlayer::Latency: GetLatencyFor failed %ld (%s)\n", err,
280 strerror(err));
281 return 0;
284 TRACE("BSoundPlayer::Latency: latency is %Ld\n", latency);
286 return latency;
290 void
291 BSoundPlayer::SetHasData(bool hasData)
293 CALLED();
294 if (hasData)
295 atomic_or(&fFlags, F_HAS_DATA);
296 else
297 atomic_and(&fFlags, ~F_HAS_DATA);
301 bool
302 BSoundPlayer::HasData()
304 CALLED();
305 return (atomic_get(&fFlags) & F_HAS_DATA) != 0;
309 BSoundPlayer::BufferPlayerFunc
310 BSoundPlayer::BufferPlayer() const
312 CALLED();
313 return fPlayBufferFunc;
317 void
318 BSoundPlayer::SetBufferPlayer(BufferPlayerFunc playerFunction)
320 CALLED();
321 BAutolock _(fLocker);
323 fPlayBufferFunc = playerFunction;
327 BSoundPlayer::EventNotifierFunc
328 BSoundPlayer::EventNotifier() const
330 CALLED();
331 return fNotifierFunc;
335 void
336 BSoundPlayer::SetNotifier(EventNotifierFunc eventNotifierFunction)
338 CALLED();
339 BAutolock _(fLocker);
341 fNotifierFunc = eventNotifierFunction;
345 void*
346 BSoundPlayer::Cookie() const
348 CALLED();
349 return fCookie;
353 void
354 BSoundPlayer::SetCookie(void *cookie)
356 CALLED();
357 BAutolock _(fLocker);
359 fCookie = cookie;
363 void
364 BSoundPlayer::SetCallbacks(BufferPlayerFunc playerFunction,
365 EventNotifierFunc eventNotifierFunction, void* cookie)
367 CALLED();
368 BAutolock _(fLocker);
370 SetBufferPlayer(playerFunction);
371 SetNotifier(eventNotifierFunction);
372 SetCookie(cookie);
376 /*! The BeBook is inaccurate about the meaning of this function.
377 The probably best interpretation is to return the time that
378 has elapsed since playing was started, whichs seems to match
379 "CurrentTime() returns the current media time"
381 bigtime_t
382 BSoundPlayer::CurrentTime()
384 if ((fFlags & F_NODES_CONNECTED) == 0)
385 return 0;
387 return fPlayerNode->CurrentTime();
391 /*! Returns the current performance time of the sound player node
392 being used by the BSoundPlayer. Will return B_ERROR if the
393 BSoundPlayer object hasn't been properly initialized.
395 bigtime_t
396 BSoundPlayer::PerformanceTime()
398 if ((fFlags & F_NODES_CONNECTED) == 0)
399 return (bigtime_t) B_ERROR;
401 return fPlayerNode->TimeSource()->Now();
405 status_t
406 BSoundPlayer::Preroll()
408 CALLED();
410 if ((fFlags & F_NODES_CONNECTED) == 0)
411 return B_NO_INIT;
413 BMediaRoster* roster = BMediaRoster::Roster();
414 if (roster == NULL) {
415 TRACE("BSoundPlayer::Preroll: Couldn't get BMediaRoster\n");
416 return B_ERROR;
419 status_t err = roster->PrerollNode(fMediaOutput.node);
420 if (err != B_OK) {
421 TRACE("BSoundPlayer::Preroll: Error while PrerollNode: %ld (%s)\n",
422 err, strerror(err));
423 return err;
426 return B_OK;
430 BSoundPlayer::play_id
431 BSoundPlayer::StartPlaying(BSound* sound, bigtime_t atTime)
433 return StartPlaying(sound, atTime, 1.0);
437 BSoundPlayer::play_id
438 BSoundPlayer::StartPlaying(BSound* sound, bigtime_t atTime, float withVolume)
440 CALLED();
442 // TODO: support the at_time and with_volume parameters
443 playing_sound* item = (playing_sound*)malloc(sizeof(playing_sound));
444 if (item == NULL)
445 return B_NO_MEMORY;
447 item->current_offset = 0;
448 item->sound = sound;
449 item->id = atomic_add(&sCurrentPlayID, 1);
450 item->delta = 0;
451 item->rate = 0;
452 item->volume = withVolume;
454 if (!fLocker.Lock()) {
455 free(item);
456 return B_ERROR;
459 sound->AcquireRef();
460 item->next = fPlayingSounds;
461 fPlayingSounds = item;
462 fLocker.Unlock();
464 SetHasData(true);
465 return item->id;
469 status_t
470 BSoundPlayer::SetSoundVolume(play_id id, float newVolume)
472 CALLED();
473 if (!fLocker.Lock())
474 return B_ERROR;
476 playing_sound *item = fPlayingSounds;
477 while (item) {
478 if (item->id == id) {
479 item->volume = newVolume;
480 fLocker.Unlock();
481 return B_OK;
484 item = item->next;
487 fLocker.Unlock();
488 return B_ENTRY_NOT_FOUND;
492 bool
493 BSoundPlayer::IsPlaying(play_id id)
495 CALLED();
496 if (!fLocker.Lock())
497 return B_ERROR;
499 playing_sound *item = fPlayingSounds;
500 while (item) {
501 if (item->id == id) {
502 fLocker.Unlock();
503 return true;
506 item = item->next;
509 fLocker.Unlock();
510 return false;
514 status_t
515 BSoundPlayer::StopPlaying(play_id id)
517 CALLED();
518 if (!fLocker.Lock())
519 return B_ERROR;
521 playing_sound** link = &fPlayingSounds;
522 playing_sound* item = fPlayingSounds;
524 while (item != NULL) {
525 if (item->id == id) {
526 *link = item->next;
527 sem_id waitSem = item->wait_sem;
528 item->sound->ReleaseRef();
529 free(item);
530 fLocker.Unlock();
532 _NotifySoundDone(id, true);
533 if (waitSem >= 0)
534 release_sem(waitSem);
536 return B_OK;
539 link = &item->next;
540 item = item->next;
543 fLocker.Unlock();
544 return B_ENTRY_NOT_FOUND;
548 status_t
549 BSoundPlayer::WaitForSound(play_id id)
551 CALLED();
552 if (!fLocker.Lock())
553 return B_ERROR;
555 playing_sound* item = fPlayingSounds;
556 while (item != NULL) {
557 if (item->id == id) {
558 sem_id waitSem = item->wait_sem;
559 if (waitSem < 0)
560 waitSem = item->wait_sem = create_sem(0, "wait for sound");
562 fLocker.Unlock();
563 return acquire_sem(waitSem);
566 item = item->next;
569 fLocker.Unlock();
570 return B_ENTRY_NOT_FOUND;
574 float
575 BSoundPlayer::Volume()
577 CALLED();
578 return pow(10.0, VolumeDB(true) / 20.0);
582 void
583 BSoundPlayer::SetVolume(float newVolume)
585 CALLED();
586 SetVolumeDB(20.0 * log10(newVolume));
590 float
591 BSoundPlayer::VolumeDB(bool forcePoll)
593 CALLED();
594 if (!fVolumeSlider)
595 return -94.0f; // silence
597 if (!forcePoll && system_time() - fLastVolumeUpdate < 500000)
598 return fVolumeDB;
600 int32 count = fVolumeSlider->CountChannels();
601 float values[count];
602 size_t size = count * sizeof(float);
603 fVolumeSlider->GetValue(&values, &size, NULL);
604 fLastVolumeUpdate = system_time();
605 fVolumeDB = values[0];
607 return values[0];
611 void
612 BSoundPlayer::SetVolumeDB(float volumeDB)
614 CALLED();
615 if (!fVolumeSlider)
616 return;
618 float minDB = fVolumeSlider->MinValue();
619 float maxDB = fVolumeSlider->MaxValue();
620 if (volumeDB < minDB)
621 volumeDB = minDB;
622 if (volumeDB > maxDB)
623 volumeDB = maxDB;
625 int count = fVolumeSlider->CountChannels();
626 float values[count];
627 for (int i = 0; i < count; i++)
628 values[i] = volumeDB;
629 fVolumeSlider->SetValue(values, sizeof(float) * count, 0);
631 fVolumeDB = volumeDB;
632 fLastVolumeUpdate = system_time();
636 status_t
637 BSoundPlayer::GetVolumeInfo(media_node* _node, int32* _parameterID,
638 float* _minDB, float* _maxDB)
640 CALLED();
641 if (fVolumeSlider == NULL)
642 return B_NO_INIT;
644 if (_node != NULL)
645 *_node = fMediaInput.node;
646 if (_parameterID != NULL)
647 *_parameterID = fVolumeSlider->ID();
648 if (_minDB != NULL)
649 *_minDB = fVolumeSlider->MinValue();
650 if (_maxDB != NULL)
651 *_maxDB = fVolumeSlider->MaxValue();
653 return B_OK;
657 // #pragma mark - protected BSoundPlayer
660 void
661 BSoundPlayer::SetInitError(status_t error)
663 CALLED();
664 fInitStatus = error;
668 // #pragma mark - private BSoundPlayer
671 void
672 BSoundPlayer::_SoundPlayBufferFunc(void *cookie, void *buffer, size_t size,
673 const media_raw_audio_format &format)
675 // TODO: support more than one sound and make use of the format parameter
676 BSoundPlayer *player = (BSoundPlayer *)cookie;
677 if (!player->fLocker.Lock()) {
678 memset(buffer, 0, size);
679 return;
682 playing_sound *sound = player->fPlayingSounds;
683 if (sound == NULL) {
684 player->SetHasData(false);
685 player->fLocker.Unlock();
686 memset(buffer, 0, size);
687 return;
690 size_t used = 0;
691 if (!sound->sound->GetDataAt(sound->current_offset, buffer, size, &used)) {
692 // will take care of removing the item and notifying others
693 player->StopPlaying(sound->id);
694 player->fLocker.Unlock();
695 memset(buffer, 0, size);
696 return;
699 sound->current_offset += used;
700 player->fLocker.Unlock();
702 if (used < size)
703 memset((uint8 *)buffer + used, 0, size - used);
707 status_t BSoundPlayer::_Reserved_SoundPlayer_0(void*, ...) { return B_ERROR; }
708 status_t BSoundPlayer::_Reserved_SoundPlayer_1(void*, ...) { return B_ERROR; }
709 status_t BSoundPlayer::_Reserved_SoundPlayer_2(void*, ...) { return B_ERROR; }
710 status_t BSoundPlayer::_Reserved_SoundPlayer_3(void*, ...) { return B_ERROR; }
711 status_t BSoundPlayer::_Reserved_SoundPlayer_4(void*, ...) { return B_ERROR; }
712 status_t BSoundPlayer::_Reserved_SoundPlayer_5(void*, ...) { return B_ERROR; }
713 status_t BSoundPlayer::_Reserved_SoundPlayer_6(void*, ...) { return B_ERROR; }
714 status_t BSoundPlayer::_Reserved_SoundPlayer_7(void*, ...) { return B_ERROR; }
717 void
718 BSoundPlayer::_Init(const media_node* node,
719 const media_multi_audio_format* format, const char* name,
720 const media_input* input, BufferPlayerFunc playerFunction,
721 EventNotifierFunc eventNotifierFunction, void* cookie)
723 CALLED();
724 fPlayingSounds = NULL;
725 fWaitingSounds = NULL;
727 fPlayerNode = NULL;
728 if (playerFunction == NULL) {
729 fPlayBufferFunc = _SoundPlayBufferFunc;
730 fCookie = this;
731 } else {
732 fPlayBufferFunc = playerFunction;
733 fCookie = cookie;
736 fNotifierFunc = eventNotifierFunction;
737 fVolumeDB = 0.0f;
738 fFlags = 0;
739 fInitStatus = B_ERROR;
740 fParameterWeb = NULL;
741 fVolumeSlider = NULL;
742 fLastVolumeUpdate = 0;
744 BMediaRoster* roster = BMediaRoster::Roster();
745 if (roster == NULL) {
746 TRACE("BSoundPlayer::_Init: Couldn't get BMediaRoster\n");
747 return;
750 // The inputNode that our player node will be
751 // connected with is either supplied by the user
752 // or the system audio mixer
753 media_node inputNode;
754 if (node) {
755 inputNode = *node;
756 } else {
757 fInitStatus = roster->GetAudioMixer(&inputNode);
758 if (fInitStatus != B_OK) {
759 TRACE("BSoundPlayer::_Init: Couldn't GetAudioMixer\n");
760 return;
762 fFlags |= F_MUST_RELEASE_MIXER;
765 media_output _output;
766 media_input _input;
767 int32 inputCount;
768 int32 outputCount;
769 media_format tryFormat;
771 // Create the player node and register it
772 fPlayerNode = new BPrivate::SoundPlayNode(name, this);
773 fInitStatus = roster->RegisterNode(fPlayerNode);
774 if (fInitStatus != B_OK) {
775 TRACE("BSoundPlayer::_Init: Couldn't RegisterNode: %s\n",
776 strerror(fInitStatus));
777 return;
780 // set the producer's time source to be the "default" time source,
781 // which the system audio mixer uses too.
782 media_node timeSource;
783 fInitStatus = roster->GetTimeSource(&timeSource);
784 if (fInitStatus != B_OK) {
785 TRACE("BSoundPlayer::_Init: Couldn't GetTimeSource: %s\n",
786 strerror(fInitStatus));
787 return;
789 fInitStatus = roster->SetTimeSourceFor(fPlayerNode->Node().node,
790 timeSource.node);
791 if (fInitStatus != B_OK) {
792 TRACE("BSoundPlayer::_Init: Couldn't SetTimeSourceFor: %s\n",
793 strerror(fInitStatus));
794 return;
797 // find a free media_input
798 if (!input) {
799 fInitStatus = roster->GetFreeInputsFor(inputNode, &_input, 1,
800 &inputCount, B_MEDIA_RAW_AUDIO);
801 if (fInitStatus != B_OK) {
802 TRACE("BSoundPlayer::_Init: Couldn't GetFreeInputsFor: %s\n",
803 strerror(fInitStatus));
804 return;
806 if (inputCount < 1) {
807 TRACE("BSoundPlayer::_Init: Couldn't find a free input\n");
808 fInitStatus = B_ERROR;
809 return;
811 } else {
812 _input = *input;
815 // find a free media_output
816 fInitStatus = roster->GetFreeOutputsFor(fPlayerNode->Node(), &_output, 1,
817 &outputCount, B_MEDIA_RAW_AUDIO);
818 if (fInitStatus != B_OK) {
819 TRACE("BSoundPlayer::_Init: Couldn't GetFreeOutputsFor: %s\n",
820 strerror(fInitStatus));
821 return;
823 if (outputCount < 1) {
824 TRACE("BSoundPlayer::_Init: Couldn't find a free output\n");
825 fInitStatus = B_ERROR;
826 return;
829 // Set an appropriate run mode for the producer
830 fInitStatus = roster->SetRunModeNode(fPlayerNode->Node(),
831 BMediaNode::B_INCREASE_LATENCY);
832 if (fInitStatus != B_OK) {
833 TRACE("BSoundPlayer::_Init: Couldn't SetRunModeNode: %s\n",
834 strerror(fInitStatus));
835 return;
838 // setup our requested format (can still have many wildcards)
839 tryFormat.type = B_MEDIA_RAW_AUDIO;
840 tryFormat.u.raw_audio = *format;
842 #if DEBUG > 0
843 char buf[100];
844 string_for_format(tryFormat, buf, sizeof(buf));
845 TRACE("BSoundPlayer::_Init: trying to connect with format %s\n", buf);
846 #endif
848 // and connect the nodes
849 fInitStatus = roster->Connect(_output.source, _input.destination,
850 &tryFormat, &fMediaOutput, &fMediaInput);
851 if (fInitStatus != B_OK) {
852 TRACE("BSoundPlayer::_Init: Couldn't Connect: %s\n",
853 strerror(fInitStatus));
854 return;
857 fFlags |= F_NODES_CONNECTED;
859 _GetVolumeSlider();
861 TRACE("BSoundPlayer node %ld has timesource %ld\n",
862 fPlayerNode->Node().node, fPlayerNode->TimeSource()->Node().node);
866 void
867 BSoundPlayer::_NotifySoundDone(play_id id, bool gotToPlay)
869 CALLED();
870 Notify(B_SOUND_DONE, id, gotToPlay);
874 void
875 BSoundPlayer::_GetVolumeSlider()
877 CALLED();
879 ASSERT(fVolumeSlider == NULL);
881 BMediaRoster *roster = BMediaRoster::CurrentRoster();
882 if (!roster) {
883 TRACE("BSoundPlayer::_GetVolumeSlider failed to get BMediaRoster");
884 return;
887 if (!fParameterWeb && roster->GetParameterWebFor(fMediaInput.node, &fParameterWeb) < B_OK) {
888 TRACE("BSoundPlayer::_GetVolumeSlider couldn't get parameter web");
889 return;
892 int count = fParameterWeb->CountParameters();
893 for (int i = 0; i < count; i++) {
894 BParameter *parameter = fParameterWeb->ParameterAt(i);
895 if (parameter->Type() != BParameter::B_CONTINUOUS_PARAMETER)
896 continue;
897 if ((parameter->ID() >> 16) != fMediaInput.destination.id)
898 continue;
899 if (strcmp(parameter->Kind(), B_GAIN) != 0)
900 continue;
901 fVolumeSlider = (BContinuousParameter *)parameter;
902 break;
905 #if DEBUG >0
906 if (!fVolumeSlider) {
907 TRACE("BSoundPlayer::_GetVolumeSlider couldn't find volume control");
909 #endif
913 void
914 BSoundPlayer::Notify(sound_player_notification what, ...)
916 CALLED();
917 if (fLocker.Lock()) {
918 if (fNotifierFunc)
919 (*fNotifierFunc)(fCookie, what);
920 fLocker.Unlock();
925 void
926 BSoundPlayer::PlayBuffer(void* buffer, size_t size,
927 const media_raw_audio_format& format)
929 if (fLocker.Lock()) {
930 if (fPlayBufferFunc)
931 (*fPlayBufferFunc)(fCookie, buffer, size, format);
932 fLocker.Unlock();
937 // #pragma mark - public sound_error
940 sound_error::sound_error(const char* string)
942 m_str_const = string;
946 const char*
947 sound_error::what() const throw()
949 return m_str_const;