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"
25 #include "deployment.h"
28 * AudioSource::AudioFrame
31 AudioSource::AudioFrame::AudioFrame (MediaFrame
*frame
)
38 AudioSource::AudioFrame::~AudioFrame ()
47 AudioSource::AudioSource (AudioPlayer
*player
, MediaPlayer
*mplayer
, AudioStream
*stream
)
48 : EventObject (Type::AUDIOSOURCE
, true)
50 pthread_mutexattr_t attribs
;
52 this->mplayer
= mplayer
;
53 this->mplayer
->ref ();
54 this->stream
= stream
;
56 this->player
= player
;
58 stream
->AddSafeHandler (IMediaStream::FirstFrameEnqueuedEvent
, FirstFrameEnqueuedCallback
, this, false);
63 flags
= (AudioFlags
) 0;
69 last_write_pts
= G_MAXUINT64
;
70 last_current_pts
= G_MAXUINT64
;
72 channels
= stream
->GetOutputChannels ();
73 sample_rate
= stream
->GetOutputSampleRate ();
74 input_bytes_per_sample
= stream
->GetOutputBitsPerSample () / 8;
75 output_bytes_per_sample
= input_bytes_per_sample
;
77 pthread_mutexattr_init (&attribs
);
78 pthread_mutexattr_settype (&attribs
, PTHREAD_MUTEX_RECURSIVE
);
79 pthread_mutex_init (&mutex
, &attribs
);
80 pthread_mutexattr_destroy (&attribs
);
84 char *fname
= g_strdup_printf ("/tmp/AudioSource-%iHz-%iChannels-%iBit.raw", sample_rate
, channels
, input_bytes_per_sample
* 8);
85 dump_fd
= fopen (fname
, "w+");
86 printf ("AudioSource: Dumping pcm data to: %s, command line to play:\n", fname
);
87 printf ("play -s -t raw -%i -c %i --rate %i %s\n", input_bytes_per_sample
, channels
, sample_rate
, fname
);
92 AudioSource::~AudioSource ()
94 pthread_mutex_destroy (&mutex
);
102 AudioSource::Dispose ()
104 IMediaStream
*stream
;
105 MediaPlayer
*mplayer
;
106 AudioFrame
*current_frame
;
111 stream
= this->stream
;
113 mplayer
= this->mplayer
;
114 this->mplayer
= NULL
;
115 current_frame
= this->current_frame
;
116 this->current_frame
= NULL
;
120 stream
->RemoveAllHandlers (this);
131 delete current_frame
;
132 current_frame
= NULL
;
135 EventObject::Dispose ();
139 AudioSource::GetMediaPlayerReffed ()
141 MediaPlayer
*result
= NULL
;
143 if (mplayer
!= NULL
) {
154 pthread_mutex_lock (&mutex
);
158 AudioSource::Unlock ()
160 pthread_mutex_unlock (&mutex
);
164 AudioSource::GetAudioStream ()
174 AudioSource::SetAudioStream (AudioStream
*value
)
186 AudioSource::GetInputBytesPerFrame ()
188 /* No locking required, this can only be set during initialization */
189 return channels
* input_bytes_per_sample
;
193 AudioSource::GetInputBytesPerSample ()
195 /* No locking required, this can only be set during initialization */
196 return input_bytes_per_sample
;
200 AudioSource::GetOutputBytesPerFrame ()
202 /* No locking required, this can only be set during initialization */
203 return channels
* output_bytes_per_sample
;
207 AudioSource::GetOutputBytesPerSample ()
209 /* No locking required, this can only be set during initialization */
210 return output_bytes_per_sample
;
214 AudioSource::SetOutputBytesPerSample (guint32 value
)
216 /* No locking required, this can only be set during initialization */
217 output_bytes_per_sample
= value
;
221 AudioSource::GetStreamReffed ()
233 AudioSource::SetFlag (AudioFlags flag
, bool value
)
237 flags
= (AudioFlags
) (flag
| flags
);
239 flags
= (AudioFlags
) (~flag
& flags
);
241 LOG_AUDIO_EX ("AudioSource::SetFlag (%i = %s, %i), resulting flags: %i = %s\n", flag
, GetFlagNames (flag
), value
, flags
, GetFlagNames (flags
));
246 AudioSource::GetFlag (AudioFlags flag
)
253 AudioSource::GetFlagNames (AudioFlags flags
)
257 v
[0] = v
[1] = v
[2] = v
[3] = v
[4] = NULL
;
259 if (flags
& AudioInitialized
)
260 v
[i
++] = "Initialized";
262 if (flags
& AudioEOF
)
265 if (flags
& AudioWaiting
)
268 if (flags
& AudioEnded
)
271 return (char *) g_strjoinv (",", (gchar
**) v
);
277 AudioSource::GetStateName (AudioState state
)
280 case AudioNone
: return "None";
281 case AudioPlaying
: return "Playing";
282 case AudioPaused
: return "Paused";
283 case AudioError
: return "Error";
284 case AudioStopped
: return "Stopped";
285 default: return "Unknown";
290 AudioSource::GetState ()
300 AudioSource::SetState (AudioState value
)
302 AudioState old_state
;
303 bool changed
= false;
304 bool audio_failed
= false;
307 if (state
!= value
) {
308 if (state
== AudioError
) {
309 LOG_AUDIO ("AudioSource::SetState (%s): Current state is Error, can't change that state\n", GetStateName (value
));
314 if (value
== AudioError
)
321 MediaPlayer
*mplayer
= GetMediaPlayerReffed ();
322 if (mplayer
!= NULL
) {
323 mplayer
->AudioFailed (this);
328 LOG_AUDIO_EX ("AudioSource::SetState (%s), old state: %s, changed: %i\n", GetStateName (value
), GetStateName (old_state
), changed
);
331 StateChanged (old_state
);
335 AudioSource::GetBalance ()
345 AudioSource::SetBalance (double value
)
353 AudioSource::GetVolume ()
363 AudioSource::SetVolume (double value
)
371 AudioSource::GetMuted ()
381 AudioSource::SetMuted (bool value
)
389 AudioSource::GetChannels ()
391 // This can only be set during initialization, so there's no need to lock here.
396 AudioSource::GetSampleRate ()
398 // This can only be set during initialization, so there's no need to lock here.
403 AudioSource::IsQueueEmpty ()
408 LOG_AUDIO_EX ("AudioSource::IsQueueEmpty ().\n");
410 stream
= GetStreamReffed ();
412 if (stream
== NULL
) {
415 result
= stream
->IsQueueEmpty ();
423 AudioSource::FirstFrameEnqueuedHandler (EventObject
*sender
, EventArgs
*args
)
425 LOG_AUDIO_EX ("AudioSource::FirstFrameEnqueuedHandler ().\n");
427 if (GetFlag (AudioWaiting
)) {
428 SetFlag (AudioWaiting
, false);
429 if (GetState () == AudioPlaying
)
435 AudioSource::GetDelay ()
437 return GetDelayInternal ();
441 AudioSource::GetCurrentPts ()
444 guint64 current_pts
= 0;
447 if (GetState () != AudioPlaying
) {
448 result
= last_current_pts
;
451 current_pts
= last_write_pts
;
456 if (current_pts
== G_MAXUINT64
) {
457 result
= current_pts
;
458 } else if (delay
== G_MAXUINT64
|| GetState () != AudioPlaying
) {
459 result
= last_current_pts
;
460 } else if (delay
> current_pts
) {
463 result
= current_pts
- delay
;
467 last_current_pts
= result
;
469 LOG_AUDIO_EX ("AudioSource::GetCurrentPts (): %" G_GUINT64_FORMAT
" ms, delay: %" G_GUINT64_FORMAT
", last_write_pts: %" G_GUINT64_FORMAT
"\n",
470 MilliSeconds_FromPts (result
), MilliSeconds_FromPts (delay
), MilliSeconds_FromPts (last_write_pts
));
478 LOG_AUDIO ("AudioSource::Stop ()\n");
481 SetState (AudioStopped
);
482 last_current_pts
= G_MAXUINT64
;
483 last_write_pts
= G_MAXUINT64
;
484 delete current_frame
;
485 current_frame
= NULL
;
493 LOG_AUDIO ("AudioSource::Play ()\n");
495 SetState (AudioPlaying
);
496 SetFlag ((AudioFlags
) (AudioEnded
| AudioEOF
| AudioWaiting
), false);
501 AudioSource::Pause ()
503 LOG_AUDIO ("AudioSource::Pause ()\n");
505 SetState (AudioPaused
);
510 AudioSource::Underflowed ()
512 MediaPlayer
*mplayer
;
513 LOG_AUDIO ("AudioSource::Underflowed (), state: %s, flags: %s\n", GetStateName (GetState ()), GetFlagNames (flags
));
518 SetCurrentDeployment (false);
520 mplayer
= GetMediaPlayerReffed ();
522 if (GetState () == AudioPlaying
) {
523 if (GetFlag (AudioEOF
)) {
525 SetFlag (AudioEnded
, true);
527 mplayer
->AudioFinished ();
528 } else if (IsQueueEmpty ()) {
529 SetFlag (AudioWaiting
, true);
531 mplayer
->SetBufferUnderflow ();
540 AudioSource::Initialize ()
544 result
= InitializeInternal ();
547 SetFlag (AudioInitialized
, true);
549 SetFlag (AudioInitialized
, false);
550 SetState (AudioError
);
557 AudioSource::Close ()
563 AudioSource::Write (void *dest
, guint32 samples
)
565 AudioData
**data
= (AudioData
**) g_alloca (sizeof (AudioData
*) * (channels
+ 1));
568 for (unsigned int i
= 0; i
< channels
; i
++)
569 data
[i
] = (AudioData
*) g_malloc (sizeof (AudioData
));
571 data
[0]->dest
= dest
;
572 data
[0]->distance
= GetOutputBytesPerFrame ();
573 // Interleaved multi-channel audio data
574 for (unsigned int i
= 1; i
< channels
; i
++) {
575 data
[i
]->dest
= ((char *) dest
) + output_bytes_per_sample
* i
;
576 data
[i
]->distance
= data
[0]->distance
;
578 data
[channels
] = NULL
;
579 result
= WriteFull (data
, samples
);
581 for (int i
= 0; data
[i
] != NULL
; i
++) {
589 AudioSource::WriteFull (AudioData
**channel_data
, guint32 samples
)
591 guint32 channels
= GetChannels ();
592 gint32
*volumes
= (gint32
*) g_alloca (sizeof (gint32
) * channels
);
596 gint16
**write_ptr
= (gint16
**) g_alloca (sizeof (gint16
*) * channels
);
598 guint32 bytes_per_frame
= input_bytes_per_sample
* channels
;
599 guint32 frames_to_write
;
600 guint32 bytes_available
;
601 guint32 bytes_written
;
603 guint64 last_frame_pts
= 0; // The pts of the last frame which was used to write samples
604 guint64 last_frame_samples
= 0; // Samples written from the last frame
605 IMediaStream
*stream
;
607 SetCurrentDeployment (false);
610 if (channel_data
== NULL
) {
611 SetState (AudioError
);
614 for (guint32 i
= 0; i
< channels
; i
++) {
615 if (channel_data
[i
] == NULL
) {
616 LOG_AUDIO ("AudioSource::WriteFull (%p, %u): channel data #%i is NULL\n", channel_data
, samples
, i
);
617 SetState (AudioError
);
621 if (channel_data
[channels
] != NULL
) {
622 SetState (AudioError
);
626 stream
= GetStreamReffed ();
627 if (stream
== NULL
) {
628 LOG_AUDIO ("AudioSource::WriteFull (): no stream.\n");
634 volume
= this->volume
* 8192;
635 balance
= this->balance
;
636 muted
= false; //this->muted;
638 // Set the per-channel volume
640 // TODO: how does the balance work here?
641 // We probably need a channel map to figure out left and right
642 for (unsigned int i
= 0; i
< channels
; i
++) {
643 volumes
[i
] = muted
? 0.0 : volume
;
645 } else if (channels
== 2) {
647 volumes
[0] = volumes
[1] = 0;
648 } else if (balance
< 0.0) {
649 volumes
[0] = volume
;
650 volumes
[1] = (1.0 + balance
) * volume
;
651 } else if (balance
> 0.0) {
652 volumes
[0] = (1.0 - balance
) * volume
;
653 volumes
[1] = volume
;
655 volumes
[0] = volumes
[1] = volume
;
657 } else if (channels
== 1) {
661 volumes
[0] = volume
;
664 SetState (AudioError
);
668 for (guint32 i
= 0; i
< channels
; i
++)
669 write_ptr
[i
] = (gint16
*) channel_data
[i
]->dest
;
671 while (GetState () == AudioPlaying
) {
672 if (current_frame
== NULL
) {
673 MediaFrame
*frame
= stream
->PopFrame ();
675 current_frame
= new AudioFrame (frame
);
680 if (current_frame
== NULL
) {
681 if (stream
->GetOutputEnded ()) {
682 LOG_AUDIO ("AudioSource::WriteFull (): No more data and reached the end.\n");
683 SetFlag (AudioWaiting
, false);
684 SetFlag ((AudioFlags
) (AudioEOF
| AudioEnded
), true);
686 LOG_AUDIO ("AudioSource::WriteFull (): No more data, starting to wait...\n");
687 if (!GetFlag (AudioEOF
) && !GetFlag (AudioEnded
)) {
688 SetFlag (AudioWaiting
, true);
689 SetFlag ((AudioFlags
) (AudioEOF
| AudioEnded
), false);
695 bytes_available
= current_frame
->frame
->buflen
- current_frame
->bytes_used
;
697 if (bytes_available
< bytes_per_frame
) {
698 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
);
699 delete current_frame
;
700 current_frame
= NULL
;
704 frames_to_write
= MIN (bytes_available
/ bytes_per_frame
, samples
- result
);
705 bytes_written
= frames_to_write
* bytes_per_frame
;
708 fwrite ((((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
), 1, bytes_written
, dump_fd
);
711 switch (this->input_bytes_per_sample
) {
713 switch (this->output_bytes_per_sample
) {
715 // 16bit audio -> 16bit audio
716 gint16
*read_ptr
= (gint16
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
718 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
719 for (guint32 channel
= 0; channel
< channels
; channel
++) {
720 value
= ((*read_ptr
) * volumes
[channel
]) >> 13;
721 *(write_ptr
[channel
]) = (gint16
) CLAMP (value
, -32768, 32767);
722 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
728 default: // implement others as needed
729 LOG_AUDIO ("AudioSource::Write (): Invalid output_bytes_per_sample, expected 2, got: %i\n", this->output_bytes_per_sample
);
735 switch (this->output_bytes_per_sample
) {
737 // 24bit audio -> 16bit audio
738 gint16
*read_ptr
= (gint16
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
740 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
741 for (guint32 channel
= 0; channel
< channels
; channel
++) {
742 read_ptr
= (gint16
*) (((gint8
*) read_ptr
) + 1); // +1 byte
744 value
= (gint16
) CLAMP (((value
* volumes
[channel
]) >> 13), -32768, 32767);
745 *write_ptr
[channel
] = value
;
746 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
747 read_ptr
+= 1; // +2 bytes
752 // case 3: // 24bit audio -> 24bit audio, this is painful to both read and write.
754 // 24bit audio -> 32bit audio
755 gint32
*read_ptr
= (gint32
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
757 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
758 for (guint32 channel
= 0; channel
< channels
; channel
++) {
759 if (false && i
> 0) {
760 // can overread before, mask out the upper bits.
761 value
= * (gint32
*) (((gint8
*) read_ptr
) - 1);
764 // can't overread before, use byte pointers
766 ((guint8
*) &value
) [1] = (((guint8
*) read_ptr
) [0]);
767 ((guint8
*) &value
) [2] = (((guint8
*) read_ptr
) [1]);
768 ((guint8
*) &value
) [3] = (((guint8
*) read_ptr
) [2]);
770 // not sure how to calculate volume here, this shifts down 13 bits
771 // and then multiply with volume. This loses the lowest 5 bits of information
772 // from the 24 bit sample. Not quite sure how to do this with 32bit math without
773 // losing information though.
774 value
= (value
>> 13) * (volumes
[channel
]);
775 *((gint32
*) write_ptr
[channel
]) = value
;
776 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
777 read_ptr
= (gint32
*) (((gint8
*) read_ptr
) + 3); // += input_bytes_per_sample;
782 default: // implement others as needed
783 LOG_AUDIO ("AudioSource::Write (): Invalid output_bytes_per_sample, expected 2 or 4, got: %i\n", this->output_bytes_per_sample
);
789 LOG_AUDIO ("AudioSource::Write (): Invalid input_bytes_per_sample, can only be 2 or 3, but got: %i\n", this->input_bytes_per_sample
);
790 SetState (AudioError
);
794 result
+= frames_to_write
;
795 current_frame
->bytes_used
+= bytes_written
;
797 last_frame_samples
= current_frame
->bytes_used
/ GetInputBytesPerFrame ();
798 last_frame_pts
= current_frame
->frame
->pts
;
800 if (current_frame
->bytes_used
== current_frame
->frame
->buflen
) {
801 // We used the entire packet
802 delete current_frame
;
803 current_frame
= NULL
;
805 // There is still audio data left in the packet, just leave it.
808 if (result
== samples
) {
809 // We've written all we were requested to write
812 //printf ("AudioSource::WriteFull (): Written %u samples of %u requested samples, getting new packet (%i packets left)\n", result, samples, frames.Length ());
817 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
);
820 last_write_pts
= last_frame_pts
+ MilliSeconds_ToPts (last_frame_samples
* 1000 / GetSampleRate ());
835 AudioListNode::AudioListNode (AudioSource
*source
)
837 this->source
= source
;
838 this->source
->ref ();
842 AudioListNode::~AudioListNode ()
844 this->source
->unref ();
851 AudioSources::AudioSources ()
853 pthread_mutex_init (&mutex
, NULL
);
854 current_generation
= 0;
857 AudioSources::~AudioSources ()
859 pthread_mutex_destroy (&mutex
);
863 AudioSources::Lock ()
865 pthread_mutex_lock (&mutex
);
869 AudioSources::Unlock ()
871 pthread_mutex_unlock (&mutex
);
875 AudioSources::Add (AudioSource
*source
)
878 list
.Append (new AudioListNode (source
));
883 AudioSources::Remove (AudioSource
*source
)
889 node
= (AudioListNode
*) list
.First ();
890 while (node
!= NULL
) {
891 if (node
->source
== source
) {
893 if (last_node
== node
)
894 last_node
= (AudioListNode
*) node
->prev
;
899 node
= (AudioListNode
*) node
->next
;
908 AudioSources::StartEnumeration ()
911 current_generation
++;
917 AudioSources::GetNext (bool only_playing
)
919 AudioListNode
*node
= NULL
;
920 AudioSource
*result
= NULL
;
924 // Check the last node returned from GetNext
925 if (last_node
!= NULL
&& last_node
->next
!= NULL
) {
926 node
= (AudioListNode
*) last_node
->next
;
927 if (node
->generation
!= current_generation
&& (!only_playing
|| node
->source
->IsPlaying ()))
931 // Loop through all the nodes looking for a node not in the
932 // current generation.
933 node
= (AudioListNode
*) list
.First ();
934 while (node
!= NULL
&& (node
->generation
== current_generation
|| (only_playing
&& !node
->source
->IsPlaying ()))) {
935 node
= (AudioListNode
*) node
->next
;
938 // Its possible that the loop has started but nothing is playing, which without this guard would
939 // return list.First () in an infinite loop while we're downloading / buffering.
940 // (due to the while loop above not clearing out the first value (list.First ()) if the condition is false and there's no other
941 // node which satifies the condition)
942 if (only_playing
&& node
!= NULL
&& !node
->source
->IsPlaying ())
947 node
->generation
= current_generation
;
949 result
= node
->source
;
950 result
->SetCurrentDeployment (false);
953 Deployment::SetCurrent (NULL
, false);
962 AudioSources::GetHead ()
964 AudioSource
*result
= NULL
;
969 node
= (AudioListNode
*) list
.First ();
971 result
= node
->source
;
972 result
->SetCurrentDeployment (false);
983 AudioSources::Length ()
988 result
= list
.Length ();
999 AudioPlayer
* AudioPlayer::instance
= NULL
;
1000 pthread_mutex_t
AudioPlayer::instance_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1002 AudioPlayer::AudioPlayer ()
1010 g_atomic_int_inc (&refcount
);
1014 AudioPlayer::unref ()
1016 int v
= g_atomic_int_exchange_and_add (&refcount
, -1) - 1;
1025 AudioPlayer::GetInstance ()
1027 AudioPlayer
*result
;
1028 pthread_mutex_lock (&instance_mutex
);
1032 pthread_mutex_unlock (&instance_mutex
);
1037 AudioPlayer::Add (MediaPlayer
*mplayer
, AudioStream
*stream
)
1040 AudioSource
*result
= NULL
;
1042 LOG_AUDIO ("AudioPlayer::Add (%p)\n", mplayer
);
1044 if (moonlight_flags
& RUNTIME_INIT_DISABLE_AUDIO
) {
1045 LOG_AUDIO ("AudioPlayer: audio is disabled.\n");
1049 pthread_mutex_lock (&instance_mutex
);
1050 if (instance
== NULL
) {
1051 /* here we get a (global) ref which is unreffed in Shutdown () */
1052 instance
= CreatePlayer ();
1056 inst
->ref (); /* this is the ref we unref below */
1057 pthread_mutex_unlock (&instance_mutex
);
1060 result
= inst
->AddImpl (mplayer
, stream
);
1068 AudioPlayer::Remove (AudioSource
*source
)
1072 LOG_AUDIO ("AudioPlayer::Remove (%p)\n", source
);
1074 inst
= GetInstance ();
1076 inst
->RemoveImpl (source
);
1082 AudioPlayer::Shutdown ()
1084 AudioPlayer
*player
= NULL
;
1086 LOG_AUDIO ("AudioPlayer::Shutdown ()\n");
1088 pthread_mutex_lock (&instance_mutex
);
1089 if (instance
!= NULL
) {
1093 pthread_mutex_unlock (&instance_mutex
);
1100 AudioPlayer::CreatePlayer ()
1103 AudioPlayer
*result
= NULL
;
1105 // If any of the flags are specified, we disable all players
1106 // and re-enable according to the flag.
1108 overridden
= moonlight_flags
& (RUNTIME_INIT_AUDIO_PULSE
| RUNTIME_INIT_AUDIO_ALSA
| RUNTIME_INIT_AUDIO_ALSA_MMAP
| RUNTIME_INIT_AUDIO_ALSA_RW
);
1110 #if INCLUDE_PULSEAUDIO
1111 if (result
!= NULL
) {
1112 LOG_AUDIO ("AudioPlayer: Not checking for PulseAudio support, we already found support for another configuration.\n");
1113 } else if (overridden
&& !(moonlight_flags
& RUNTIME_INIT_AUDIO_PULSE
)) {
1114 LOG_AUDIO ("AudioPlayer: PulseAudio disabled with environment variable (MOONLIGHT_OVERRIDES)\n");
1115 } else if (!PulsePlayer::IsInstalled ()) {
1116 LOG_AUDIO ("AudioPlayer: PulseAudio is not installed or configured correctly.\n");
1118 printf ("AudioPlayer: Using PulseAudio.\n");
1119 result
= new PulsePlayer ();
1122 if (result
!= NULL
) {
1123 if (!result
->Initialize ()) {
1124 LOG_AUDIO ("AudioPlayer: Failed initialization.\n");
1132 LOG_AUDIO ("AudioPlayer: Built without support for pulseaudio.\n");
1136 if (result
!= NULL
) {
1137 LOG_AUDIO ("AudioPlayer: Not checking for Alsa support, we already found support for another configuration.\n");
1138 } else if (overridden
&& !(moonlight_flags
& (RUNTIME_INIT_AUDIO_ALSA
| RUNTIME_INIT_AUDIO_ALSA_MMAP
| RUNTIME_INIT_AUDIO_ALSA_RW
))) {
1139 LOG_AUDIO ("AudioPlayer: Alsa disabled with environment variable (MOONLIGHT_OVERRIDES)\n");
1140 } else if (!AlsaPlayer::IsInstalled ()) {
1141 LOG_AUDIO ("AudioPlayer: Alsa is not installed or configured correctly.\n");
1143 printf ("AudioPlayer: Using Alsa.\n");
1144 result
= new AlsaPlayer ();
1147 if (result
!= NULL
) {
1148 if (!result
->Initialize ()) {
1149 LOG_AUDIO ("AudioPlayer: Failed initialization.\n");
1157 LOG_AUDIO ("AudioPlayer: Built without support for alsa.\n");
1164 AudioPlayer::AddImpl (MediaPlayer
*mplayer
, AudioStream
*stream
)
1166 AudioSource
*result
= CreateNode (mplayer
, stream
);
1168 if (result
->Initialize ()) {
1169 sources
.Add (result
);
1170 AddInternal (result
);
1180 AudioPlayer::RemoveImpl (AudioSource
*node
)
1183 if (sources
.Remove (node
)) {
1184 RemoveInternal (node
);
1191 AudioPlayer::Dispose ()
1197 AudioPlayer::ShutdownImpl ()
1199 AudioSource
*source
;
1201 PrepareShutdownInternal ();
1203 // Remove all the sources.
1204 while ((source
= sources
.GetHead ()) != NULL
) {
1205 RemoveImpl (source
);
1209 FinishShutdownInternal ();