1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2008 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
18 #include "audio-alsa.h"
19 #include "audio-pulse.h"
24 #include "mediaplayer.h"
27 * AudioSource::AudioFrame
30 AudioSource::AudioFrame::AudioFrame (MediaFrame
*frame
)
37 AudioSource::AudioFrame::~AudioFrame ()
46 AudioSource::AudioSource (AudioPlayer
*player
, MediaPlayer
*mplayer
, AudioStream
*stream
)
47 : EventObject (Type::AUDIOSOURCE
)
49 pthread_mutexattr_t attribs
;
51 this->mplayer
= mplayer
;
52 this->mplayer
->ref ();
53 this->stream
= stream
;
55 this->player
= player
;
57 stream
->AddSafeHandler (IMediaStream::FirstFrameEnqueuedEvent
, FirstFrameEnqueuedCallback
, this, false);
62 flags
= (AudioFlags
) 0;
68 last_write_pts
= G_MAXUINT64
;
69 last_current_pts
= G_MAXUINT64
;
71 channels
= stream
->GetOutputChannels ();
72 sample_rate
= stream
->GetOutputSampleRate ();
73 input_bytes_per_sample
= stream
->GetOutputBitsPerSample () / 8;
74 output_bytes_per_sample
= input_bytes_per_sample
;
76 pthread_mutexattr_init (&attribs
);
77 pthread_mutexattr_settype (&attribs
, PTHREAD_MUTEX_RECURSIVE
);
78 pthread_mutex_init (&mutex
, &attribs
);
79 pthread_mutexattr_destroy (&attribs
);
83 char *fname
= g_strdup_printf ("/tmp/AudioSource-%iHz-%iChannels-%iBit.raw", sample_rate
, channels
, input_bytes_per_sample
* 8);
84 dump_fd
= fopen (fname
, "w+");
85 printf ("AudioSource: Dumping pcm data to: %s, command line to play:\n", fname
);
86 printf ("play -s -t raw -%i -c %i --rate %i %s\n", input_bytes_per_sample
, channels
, sample_rate
, fname
);
91 AudioSource::~AudioSource ()
93 pthread_mutex_destroy (&mutex
);
101 AudioSource::Dispose ()
104 stream
->RemoveAllHandlers (this);
115 delete current_frame
;
116 current_frame
= NULL
;
119 EventObject::Dispose ();
125 pthread_mutex_lock (&mutex
);
129 AudioSource::Unlock ()
131 pthread_mutex_unlock (&mutex
);
135 AudioSource::GetAudioStream ()
145 AudioSource::SetAudioStream (AudioStream
*value
)
157 AudioSource::GetInputBytesPerFrame ()
159 /* No locking required, this can only be set during initialization */
160 return channels
* input_bytes_per_sample
;
164 AudioSource::GetInputBytesPerSample ()
166 /* No locking required, this can only be set during initialization */
167 return input_bytes_per_sample
;
171 AudioSource::GetOutputBytesPerFrame ()
173 /* No locking required, this can only be set during initialization */
174 return channels
* output_bytes_per_sample
;
178 AudioSource::GetOutputBytesPerSample ()
180 /* No locking required, this can only be set during initialization */
181 return output_bytes_per_sample
;
185 AudioSource::SetOutputBytesPerSample (guint32 value
)
187 /* No locking required, this can only be set during initialization */
188 output_bytes_per_sample
= value
;
192 AudioSource::GetStreamReffed ()
204 AudioSource::SetFlag (AudioFlags flag
, bool value
)
208 flags
= (AudioFlags
) (flag
| flags
);
210 flags
= (AudioFlags
) (~flag
& flags
);
212 LOG_AUDIO_EX ("AudioSource::SetFlag (%i = %s, %i), resulting flags: %i = %s\n", flag
, GetFlagNames (flag
), value
, flags
, GetFlagNames (flags
));
217 AudioSource::GetFlag (AudioFlags flag
)
224 AudioSource::GetFlagNames (AudioFlags flags
)
228 v
[0] = v
[1] = v
[2] = v
[3] = v
[4] = NULL
;
230 if (flags
& AudioInitialized
)
231 v
[i
++] = "Initialized";
233 if (flags
& AudioEOF
)
236 if (flags
& AudioWaiting
)
239 if (flags
& AudioEnded
)
242 return (char *) g_strjoinv (",", (gchar
**) v
);
248 AudioSource::GetStateName (AudioState state
)
251 case AudioNone
: return "None";
252 case AudioPlaying
: return "Playing";
253 case AudioPaused
: return "Paused";
254 case AudioError
: return "Error";
255 case AudioStopped
: return "Stopped";
256 default: return "Unknown";
261 AudioSource::GetState ()
271 AudioSource::SetState (AudioState value
)
273 AudioState old_state
;
274 bool changed
= false;
277 if (state
!= value
) {
278 if (state
== AudioError
) {
279 LOG_AUDIO ("AudioSource::SetState (%s): Current state is Error, can't change that state\n", GetStateName (value
));
284 if (value
== AudioError
)
285 mplayer
->AudioFailed (this);
290 LOG_AUDIO_EX ("AudioSource::SetState (%s), old state: %s, changed: %i\n", GetStateName (value
), GetStateName (old_state
), changed
);
293 StateChanged (old_state
);
297 AudioSource::GetBalance ()
307 AudioSource::SetBalance (double value
)
315 AudioSource::GetVolume ()
325 AudioSource::SetVolume (double value
)
333 AudioSource::GetMuted ()
343 AudioSource::SetMuted (bool value
)
351 AudioSource::GetChannels ()
353 // This can only be set during initialization, so there's no need to lock here.
358 AudioSource::GetSampleRate ()
360 // This can only be set during initialization, so there's no need to lock here.
365 AudioSource::IsQueueEmpty ()
370 LOG_AUDIO_EX ("AudioSource::IsQueueEmpty ().\n");
372 stream
= GetStreamReffed ();
374 g_return_val_if_fail (stream
!= NULL
, false);
376 result
= stream
->IsQueueEmpty ();
384 AudioSource::FirstFrameEnqueuedHandler (EventObject
*sender
, EventArgs
*args
)
386 LOG_AUDIO_EX ("AudioSource::FirstFrameEnqueuedHandler ().\n");
388 if (GetFlag (AudioWaiting
)) {
389 SetFlag (AudioWaiting
, false);
390 if (GetState () == AudioPlaying
)
396 AudioSource::GetDelay ()
398 return GetDelayInternal ();
402 AudioSource::GetCurrentPts ()
405 guint64 current_pts
= 0;
408 if (GetState () != AudioPlaying
) {
409 result
= last_current_pts
;
412 current_pts
= last_write_pts
;
417 if (current_pts
== G_MAXUINT64
) {
418 result
= current_pts
;
419 } else if (delay
== G_MAXUINT64
|| GetState () != AudioPlaying
) {
420 result
= last_current_pts
;
421 } else if (delay
> current_pts
) {
424 result
= current_pts
- delay
;
428 last_current_pts
= result
;
430 LOG_AUDIO_EX ("AudioSource::GetCurrentPts (): %" G_GUINT64_FORMAT
" ms, delay: %" G_GUINT64_FORMAT
", last_write_pts: %llu\n",
431 MilliSeconds_FromPts (result
), MilliSeconds_FromPts (delay
), MilliSeconds_FromPts (last_write_pts
));
439 LOG_AUDIO ("AudioSource::Stop ()\n");
442 SetState (AudioStopped
);
443 last_current_pts
= G_MAXUINT64
;
444 last_write_pts
= G_MAXUINT64
;
445 delete current_frame
;
446 current_frame
= NULL
;
454 LOG_AUDIO ("AudioSource::Play ()\n");
456 SetState (AudioPlaying
);
457 SetFlag ((AudioFlags
) (AudioEnded
| AudioEOF
| AudioWaiting
), false);
462 AudioSource::Pause ()
464 LOG_AUDIO ("AudioSource::Pause ()\n");
466 SetState (AudioPaused
);
471 AudioSource::Underflowed ()
473 LOG_AUDIO ("AudioSource::Underflowed (), state: %s, flags: %s\n", GetStateName (GetState ()), GetFlagNames (flags
));
475 SetCurrentDeployment (false);
477 if (GetState () == AudioPlaying
) {
478 if (GetFlag (AudioEOF
)) {
480 SetFlag (AudioEnded
, true);
481 mplayer
->AudioFinished ();
482 } else if (IsQueueEmpty ()) {
483 SetFlag (AudioWaiting
, true);
484 mplayer
->SetBufferUnderflow ();
490 AudioSource::Initialize ()
494 result
= InitializeInternal ();
497 SetFlag (AudioInitialized
, true);
499 SetFlag (AudioInitialized
, false);
500 SetState (AudioError
);
507 AudioSource::Close ()
513 AudioSource::Write (void *dest
, guint32 samples
)
515 AudioData
**data
= (AudioData
**) g_alloca (sizeof (AudioData
*) * (channels
+ 1));
518 for (unsigned int i
= 0; i
< channels
; i
++)
519 data
[i
] = (AudioData
*) g_malloc (sizeof (AudioData
));
521 data
[0]->dest
= dest
;
522 data
[0]->distance
= GetOutputBytesPerFrame ();
523 // Interleaved multi-channel audio data
524 for (unsigned int i
= 1; i
< channels
; i
++) {
525 data
[i
]->dest
= ((char *) dest
) + output_bytes_per_sample
* i
;
526 data
[i
]->distance
= data
[0]->distance
;
528 data
[channels
] = NULL
;
529 result
= WriteFull (data
, samples
);
531 for (int i
= 0; data
[i
] != NULL
; i
++) {
539 AudioSource::WriteFull (AudioData
**channel_data
, guint32 samples
)
541 guint32 channels
= GetChannels ();
542 gint32
*volumes
= (gint32
*) g_alloca (sizeof (gint32
) * channels
);
546 gint16
**write_ptr
= (gint16
**) g_alloca (sizeof (gint16
*) * channels
);
548 guint32 bytes_per_frame
= input_bytes_per_sample
* channels
;
549 guint32 frames_to_write
;
550 guint32 bytes_available
;
551 guint32 bytes_written
;
553 guint64 last_frame_pts
= 0; // The pts of the last frame which was used to write samples
554 guint64 last_frame_samples
= 0; // Samples written from the last frame
556 SetCurrentDeployment (false);
559 if (channel_data
== NULL
) {
560 SetState (AudioError
);
563 for (guint32 i
= 0; i
< channels
; i
++) {
564 if (channel_data
[i
] == NULL
) {
565 LOG_AUDIO ("AudioSource::WriteFull (%p, %u): channel data #%i is NULL\n", channel_data
, samples
, i
);
566 SetState (AudioError
);
570 if (channel_data
[channels
] != NULL
) {
571 SetState (AudioError
);
577 volume
= this->volume
* 8192;
578 balance
= this->balance
;
579 muted
= false; //this->muted;
581 // Set the per-channel volume
583 // TODO: how does the balance work here?
584 // We probably need a channel map to figure out left and right
585 for (unsigned int i
= 0; i
< channels
; i
++) {
586 volumes
[i
] = muted
? 0.0 : volume
;
588 } else if (channels
== 2) {
590 volumes
[0] = volumes
[1] = 0;
591 } else if (balance
< 0.0) {
592 volumes
[0] = volume
;
593 volumes
[1] = (1.0 + balance
) * volume
;
594 } else if (balance
> 0.0) {
595 volumes
[0] = (1.0 - balance
) * volume
;
596 volumes
[1] = volume
;
598 volumes
[0] = volumes
[1] = volume
;
600 } else if (channels
== 1) {
604 volumes
[0] = volume
;
607 SetState (AudioError
);
611 for (guint32 i
= 0; i
< channels
; i
++)
612 write_ptr
[i
] = (gint16
*) channel_data
[i
]->dest
;
614 while (GetState () == AudioPlaying
) {
615 if (current_frame
== NULL
) {
616 MediaFrame
*frame
= stream
->PopFrame ();
618 current_frame
= new AudioFrame (frame
);
623 if (current_frame
== NULL
) {
624 if (stream
->GetOutputEnded ()) {
625 LOG_AUDIO ("AudioSource::WriteFull (): No more data and reached the end.\n");
626 SetFlag (AudioWaiting
, false);
627 SetFlag ((AudioFlags
) (AudioEOF
| AudioEnded
), true);
629 LOG_AUDIO ("AudioSource::WriteFull (): No more data, starting to wait...\n");
630 if (!GetFlag (AudioEOF
) && !GetFlag (AudioEnded
)) {
631 SetFlag (AudioWaiting
, true);
632 SetFlag ((AudioFlags
) (AudioEOF
| AudioEnded
), false);
638 bytes_available
= current_frame
->frame
->buflen
- current_frame
->bytes_used
;
640 if (bytes_available
< bytes_per_frame
) {
641 LOG_AUDIO ("AudioSource::WriteFull (): incomplete packet, bytes_available: %u, buflen: %u, bytes_used: %u\n", bytes_available
, current_frame
->frame
->buflen
, current_frame
->bytes_used
);
642 delete current_frame
;
643 current_frame
= NULL
;
647 frames_to_write
= MIN (bytes_available
/ bytes_per_frame
, samples
- result
);
648 bytes_written
= frames_to_write
* bytes_per_frame
;
651 fwrite ((((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
), 1, bytes_written
, dump_fd
);
654 switch (this->input_bytes_per_sample
) {
656 switch (this->output_bytes_per_sample
) {
658 // 16bit audio -> 16bit audio
659 gint16
*read_ptr
= (gint16
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
661 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
662 for (guint32 channel
= 0; channel
< channels
; channel
++) {
663 value
= ((*read_ptr
) * volumes
[channel
]) >> 13;
664 *(write_ptr
[channel
]) = (gint16
) CLAMP (value
, -32768, 32767);
665 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
671 default: // implement others as needed
672 LOG_AUDIO ("AudioSource::Write (): Invalid output_bytes_per_sample, expected 2, got: %i\n", this->output_bytes_per_sample
);
678 switch (this->output_bytes_per_sample
) {
680 // 24bit audio -> 16bit audio
681 gint16
*read_ptr
= (gint16
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
683 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
684 for (guint32 channel
= 0; channel
< channels
; channel
++) {
685 read_ptr
= (gint16
*) (((gint8
*) read_ptr
) + 1); // +1 byte
687 value
= (gint16
) CLAMP (((value
* volumes
[channel
]) >> 13), -32768, 32767);
688 *write_ptr
[channel
] = value
;
689 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
690 read_ptr
+= 1; // +2 bytes
695 // case 3: // 24bit audio -> 24bit audio, this is painful to both read and write.
697 // 24bit audio -> 32bit audio
698 gint32
*read_ptr
= (gint32
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
700 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
701 for (guint32 channel
= 0; channel
< channels
; channel
++) {
702 if (false && i
> 0) {
703 // can overread before, mask out the upper bits.
704 value
= * (gint32
*) (((gint8
*) read_ptr
) - 1);
707 // can't overread before, use byte pointers
709 ((guint8
*) &value
) [1] = (((guint8
*) read_ptr
) [0]);
710 ((guint8
*) &value
) [2] = (((guint8
*) read_ptr
) [1]);
711 ((guint8
*) &value
) [3] = (((guint8
*) read_ptr
) [2]);
713 // not sure how to calculate volume here, this shifts down 13 bits
714 // and then multiply with volume. This loses the lowest 5 bits of information
715 // from the 24 bit sample. Not quite sure how to do this with 32bit math without
716 // losing information though.
717 value
= (value
>> 13) * (volumes
[channel
]);
718 *((gint32
*) write_ptr
[channel
]) = value
;
719 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
720 read_ptr
= (gint32
*) (((gint8
*) read_ptr
) + 3); // += input_bytes_per_sample;
725 default: // implement others as needed
726 LOG_AUDIO ("AudioSource::Write (): Invalid output_bytes_per_sample, expected 2 or 4, got: %i\n", this->output_bytes_per_sample
);
732 LOG_AUDIO ("AudioSource::Write (): Invalid input_bytes_per_sample, can only be 2 or 3, but got: %i\n", this->input_bytes_per_sample
);
733 SetState (AudioError
);
737 result
+= frames_to_write
;
738 current_frame
->bytes_used
+= bytes_written
;
740 last_frame_samples
= current_frame
->bytes_used
/ GetInputBytesPerFrame ();
741 last_frame_pts
= current_frame
->frame
->pts
;
743 if (current_frame
->bytes_used
== current_frame
->frame
->buflen
) {
744 // We used the entire packet
745 delete current_frame
;
746 current_frame
= NULL
;
748 // There is still audio data left in the packet, just leave it.
751 if (result
== samples
) {
752 // We've written all we were requested to write
755 //printf ("AudioSource::WriteFull (): Written %u samples of %u requested samples, getting new packet (%i packets left)\n", result, samples, frames.Length ());
760 LOG_AUDIO_EX ("AudioSource::WriteFull (%p, %u): Wrote %u samples, current pts: %" G_GUINT64_FORMAT
", volume: %.2f\n", channel_data
, samples
, result
, MilliSeconds_FromPts (GetCurrentPts ()), this->volume
);
763 last_write_pts
= last_frame_pts
+ MilliSeconds_ToPts (last_frame_samples
* 1000 / GetSampleRate ());
775 AudioListNode::AudioListNode (AudioSource
*source
)
777 this->source
= source
;
778 this->source
->ref ();
782 AudioListNode::~AudioListNode ()
784 this->source
->unref ();
791 AudioSources::AudioSources ()
793 pthread_mutex_init (&mutex
, NULL
);
794 current_generation
= 0;
797 AudioSources::~AudioSources ()
799 pthread_mutex_destroy (&mutex
);
803 AudioSources::Lock ()
805 pthread_mutex_lock (&mutex
);
809 AudioSources::Unlock ()
811 pthread_mutex_unlock (&mutex
);
815 AudioSources::Add (AudioSource
*source
)
818 list
.Append (new AudioListNode (source
));
823 AudioSources::Remove (AudioSource
*source
)
829 node
= (AudioListNode
*) list
.First ();
830 while (node
!= NULL
) {
831 if (node
->source
== source
) {
833 if (last_node
== node
)
834 last_node
= (AudioListNode
*) node
->prev
;
839 node
= (AudioListNode
*) node
->next
;
848 AudioSources::StartEnumeration ()
851 current_generation
++;
857 AudioSources::GetNext (bool only_playing
)
859 AudioListNode
*node
= NULL
;
860 AudioSource
*result
= NULL
;
864 // Check the last node returned from GetNext
865 if (last_node
!= NULL
&& last_node
->next
!= NULL
) {
866 node
= (AudioListNode
*) last_node
->next
;
867 if (node
->generation
!= current_generation
&& (!only_playing
|| node
->source
->IsPlaying ()))
871 // Loop through all the nodes looking for a node not in the
872 // current generation.
873 node
= (AudioListNode
*) list
.First ();
874 while (node
!= NULL
&& (node
->generation
== current_generation
|| (only_playing
&& !node
->source
->IsPlaying ()))) {
875 node
= (AudioListNode
*) node
->next
;
878 // Its possible that the loop has started but nothing is playing, which without this guard would
879 // return list.First () in an infinite loop while we're downloading / buffering.
880 // (due to the while loop above not clearing out the first value (list.First ()) if the condition is false and there's no other
881 // node which satifies the condition)
882 if (only_playing
&& node
!= NULL
&& !node
->source
->IsPlaying ())
887 node
->generation
= current_generation
;
889 result
= node
->source
;
890 result
->SetCurrentDeployment (false);
893 Deployment::SetCurrent (NULL
, false);
902 AudioSources::GetHead ()
904 AudioSource
*result
= NULL
;
909 node
= (AudioListNode
*) list
.First ();
911 result
= node
->source
;
912 result
->SetCurrentDeployment (false);
923 AudioSources::Length ()
928 result
= list
.Length ();
939 AudioPlayer
* AudioPlayer::instance
= NULL
;
940 pthread_mutex_t
AudioPlayer::instance_mutex
= PTHREAD_MUTEX_INITIALIZER
;
943 AudioPlayer::Add (MediaPlayer
*mplayer
, AudioStream
*stream
)
945 AudioSource
*result
= NULL
;
947 LOG_AUDIO ("AudioPlayer::Add (%p)\n", mplayer
);
949 if (moonlight_flags
& RUNTIME_INIT_DISABLE_AUDIO
) {
950 LOG_AUDIO ("AudioPlayer: audio is disabled.\n");
954 pthread_mutex_lock (&instance_mutex
);
955 if (instance
== NULL
)
956 instance
= CreatePlayer ();
957 if (instance
!= NULL
)
958 result
= instance
->AddImpl (mplayer
, stream
);
959 pthread_mutex_unlock (&instance_mutex
);
965 AudioPlayer::Remove (AudioSource
*source
)
967 LOG_AUDIO ("AudioPlayer::Remove (%p)\n", source
);
969 pthread_mutex_lock (&instance_mutex
);
970 if (instance
!= NULL
)
971 instance
->RemoveImpl (source
);
973 pthread_mutex_unlock (&instance_mutex
);
977 AudioPlayer::Shutdown ()
980 LOG_AUDIO ("AudioPlayer::Shutdown ()\n");
982 pthread_mutex_lock (&instance_mutex
);
983 if (instance
!= NULL
) {
986 player
->ShutdownImpl ();
989 pthread_mutex_unlock (&instance_mutex
);
993 AudioPlayer::CreatePlayer ()
996 AudioPlayer
*result
= NULL
;
998 // If any of the flags are specified, we disable all players
999 // and re-enable according to the flag.
1001 overridden
= moonlight_flags
& (RUNTIME_INIT_AUDIO_PULSE
| RUNTIME_INIT_AUDIO_ALSA
| RUNTIME_INIT_AUDIO_ALSA_MMAP
| RUNTIME_INIT_AUDIO_ALSA_RW
);
1003 #if INCLUDE_PULSEAUDIO
1004 if (result
!= NULL
) {
1005 LOG_AUDIO ("AudioPlayer: Not checking for PulseAudio support, we already found support for another configuration.\n");
1006 } else if (overridden
&& !(moonlight_flags
& RUNTIME_INIT_AUDIO_PULSE
)) {
1007 LOG_AUDIO ("AudioPlayer: PulseAudio disabled with environment variable (MOONLIGHT_OVERRIDES)\n");
1008 } else if (!PulsePlayer::IsInstalled ()) {
1009 LOG_AUDIO ("AudioPlayer: PulseAudio is not installed or configured correctly.\n");
1011 printf ("AudioPlayer: Using PulseAudio.\n");
1012 result
= new PulsePlayer ();
1015 if (result
!= NULL
) {
1016 if (!result
->Initialize ()) {
1017 LOG_AUDIO ("AudioPlayer: Failed initialization.\n");
1018 result
->ShutdownImpl ();
1026 LOG_AUDIO ("AudioPlayer: Built without support for pulseaudio.\n");
1030 if (result
!= NULL
) {
1031 LOG_AUDIO ("AudioPlayer: Not checking for Alsa support, we already found support for another configuration.\n");
1032 } else if (overridden
&& !(moonlight_flags
& (RUNTIME_INIT_AUDIO_ALSA
| RUNTIME_INIT_AUDIO_ALSA_MMAP
| RUNTIME_INIT_AUDIO_ALSA_RW
))) {
1033 LOG_AUDIO ("AudioPlayer: Alsa disabled with environment variable (MOONLIGHT_OVERRIDES)\n");
1034 } else if (!AlsaPlayer::IsInstalled ()) {
1035 LOG_AUDIO ("AudioPlayer: Alsa is not installed or configured correctly.\n");
1037 printf ("AudioPlayer: Using Alsa.\n");
1038 result
= new AlsaPlayer ();
1041 if (result
!= NULL
) {
1042 if (!result
->Initialize ()) {
1043 LOG_AUDIO ("AudioPlayer: Failed initialization.\n");
1044 result
->ShutdownImpl ();
1052 LOG_AUDIO ("AudioPlayer: Built without support for alsa.\n");
1059 AudioPlayer::AddImpl (MediaPlayer
*mplayer
, AudioStream
*stream
)
1061 AudioSource
*result
= CreateNode (mplayer
, stream
);
1063 if (result
->Initialize ()) {
1064 sources
.Add (result
);
1065 AddInternal (result
);
1075 AudioPlayer::RemoveImpl (AudioSource
*node
)
1078 if (sources
.Remove (node
)) {
1079 RemoveInternal (node
);
1086 AudioPlayer::ShutdownImpl ()
1088 AudioSource
*source
;
1090 PrepareShutdownInternal ();
1092 // Remove all the sources.
1093 while ((source
= sources
.GetHead ()) != NULL
) {
1094 RemoveImpl (source
);
1098 FinishShutdownInternal ();