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
, true)
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 ()
103 IMediaStream
*stream
;
104 MediaPlayer
*mplayer
;
105 AudioFrame
*current_frame
;
110 stream
= this->stream
;
112 mplayer
= this->mplayer
;
113 this->mplayer
= NULL
;
114 current_frame
= this->current_frame
;
115 this->current_frame
= NULL
;
119 stream
->RemoveAllHandlers (this);
130 delete current_frame
;
131 current_frame
= NULL
;
134 EventObject::Dispose ();
138 AudioSource::GetMediaPlayerReffed ()
140 MediaPlayer
*result
= NULL
;
142 if (mplayer
!= NULL
) {
153 pthread_mutex_lock (&mutex
);
157 AudioSource::Unlock ()
159 pthread_mutex_unlock (&mutex
);
163 AudioSource::GetAudioStream ()
173 AudioSource::SetAudioStream (AudioStream
*value
)
185 AudioSource::GetInputBytesPerFrame ()
187 /* No locking required, this can only be set during initialization */
188 return channels
* input_bytes_per_sample
;
192 AudioSource::GetInputBytesPerSample ()
194 /* No locking required, this can only be set during initialization */
195 return input_bytes_per_sample
;
199 AudioSource::GetOutputBytesPerFrame ()
201 /* No locking required, this can only be set during initialization */
202 return channels
* output_bytes_per_sample
;
206 AudioSource::GetOutputBytesPerSample ()
208 /* No locking required, this can only be set during initialization */
209 return output_bytes_per_sample
;
213 AudioSource::SetOutputBytesPerSample (guint32 value
)
215 /* No locking required, this can only be set during initialization */
216 output_bytes_per_sample
= value
;
220 AudioSource::GetStreamReffed ()
232 AudioSource::SetFlag (AudioFlags flag
, bool value
)
236 flags
= (AudioFlags
) (flag
| flags
);
238 flags
= (AudioFlags
) (~flag
& flags
);
240 LOG_AUDIO_EX ("AudioSource::SetFlag (%i = %s, %i), resulting flags: %i = %s\n", flag
, GetFlagNames (flag
), value
, flags
, GetFlagNames (flags
));
245 AudioSource::GetFlag (AudioFlags flag
)
252 AudioSource::GetFlagNames (AudioFlags flags
)
256 v
[0] = v
[1] = v
[2] = v
[3] = v
[4] = NULL
;
258 if (flags
& AudioInitialized
)
259 v
[i
++] = "Initialized";
261 if (flags
& AudioEOF
)
264 if (flags
& AudioWaiting
)
267 if (flags
& AudioEnded
)
270 return (char *) g_strjoinv (",", (gchar
**) v
);
276 AudioSource::GetStateName (AudioState state
)
279 case AudioNone
: return "None";
280 case AudioPlaying
: return "Playing";
281 case AudioPaused
: return "Paused";
282 case AudioError
: return "Error";
283 case AudioStopped
: return "Stopped";
284 default: return "Unknown";
289 AudioSource::GetState ()
299 AudioSource::SetState (AudioState value
)
301 AudioState old_state
;
302 bool changed
= false;
303 bool audio_failed
= false;
306 if (state
!= value
) {
307 if (state
== AudioError
) {
308 LOG_AUDIO ("AudioSource::SetState (%s): Current state is Error, can't change that state\n", GetStateName (value
));
313 if (value
== AudioError
)
320 MediaPlayer
*mplayer
= GetMediaPlayerReffed ();
321 if (mplayer
!= NULL
) {
322 mplayer
->AudioFailed (this);
327 LOG_AUDIO_EX ("AudioSource::SetState (%s), old state: %s, changed: %i\n", GetStateName (value
), GetStateName (old_state
), changed
);
330 StateChanged (old_state
);
334 AudioSource::GetBalance ()
344 AudioSource::SetBalance (double value
)
352 AudioSource::GetVolume ()
362 AudioSource::SetVolume (double value
)
370 AudioSource::GetMuted ()
380 AudioSource::SetMuted (bool value
)
388 AudioSource::GetChannels ()
390 // This can only be set during initialization, so there's no need to lock here.
395 AudioSource::GetSampleRate ()
397 // This can only be set during initialization, so there's no need to lock here.
402 AudioSource::IsQueueEmpty ()
407 LOG_AUDIO_EX ("AudioSource::IsQueueEmpty ().\n");
409 stream
= GetStreamReffed ();
411 if (stream
== NULL
) {
414 result
= stream
->IsQueueEmpty ();
422 AudioSource::FirstFrameEnqueuedHandler (EventObject
*sender
, EventArgs
*args
)
424 LOG_AUDIO_EX ("AudioSource::FirstFrameEnqueuedHandler ().\n");
426 if (GetFlag (AudioWaiting
)) {
427 SetFlag (AudioWaiting
, false);
428 if (GetState () == AudioPlaying
)
434 AudioSource::GetDelay ()
436 return GetDelayInternal ();
440 AudioSource::GetCurrentPts ()
443 guint64 current_pts
= 0;
446 if (GetState () != AudioPlaying
) {
447 result
= last_current_pts
;
450 current_pts
= last_write_pts
;
455 if (current_pts
== G_MAXUINT64
) {
456 result
= current_pts
;
457 } else if (delay
== G_MAXUINT64
|| GetState () != AudioPlaying
) {
458 result
= last_current_pts
;
459 } else if (delay
> current_pts
) {
462 result
= current_pts
- delay
;
466 last_current_pts
= result
;
468 LOG_AUDIO_EX ("AudioSource::GetCurrentPts (): %" G_GUINT64_FORMAT
" ms, delay: %" G_GUINT64_FORMAT
", last_write_pts: %llu\n",
469 MilliSeconds_FromPts (result
), MilliSeconds_FromPts (delay
), MilliSeconds_FromPts (last_write_pts
));
477 LOG_AUDIO ("AudioSource::Stop ()\n");
480 SetState (AudioStopped
);
481 last_current_pts
= G_MAXUINT64
;
482 last_write_pts
= G_MAXUINT64
;
483 delete current_frame
;
484 current_frame
= NULL
;
492 LOG_AUDIO ("AudioSource::Play ()\n");
494 SetState (AudioPlaying
);
495 SetFlag ((AudioFlags
) (AudioEnded
| AudioEOF
| AudioWaiting
), false);
500 AudioSource::Pause ()
502 LOG_AUDIO ("AudioSource::Pause ()\n");
504 SetState (AudioPaused
);
509 AudioSource::Underflowed ()
511 MediaPlayer
*mplayer
;
512 LOG_AUDIO ("AudioSource::Underflowed (), state: %s, flags: %s\n", GetStateName (GetState ()), GetFlagNames (flags
));
517 SetCurrentDeployment (false);
519 mplayer
= GetMediaPlayerReffed ();
521 if (GetState () == AudioPlaying
) {
522 if (GetFlag (AudioEOF
)) {
524 SetFlag (AudioEnded
, true);
526 mplayer
->AudioFinished ();
527 } else if (IsQueueEmpty ()) {
528 SetFlag (AudioWaiting
, true);
530 mplayer
->SetBufferUnderflow ();
539 AudioSource::Initialize ()
543 result
= InitializeInternal ();
546 SetFlag (AudioInitialized
, true);
548 SetFlag (AudioInitialized
, false);
549 SetState (AudioError
);
556 AudioSource::Close ()
562 AudioSource::Write (void *dest
, guint32 samples
)
564 AudioData
**data
= (AudioData
**) g_alloca (sizeof (AudioData
*) * (channels
+ 1));
567 for (unsigned int i
= 0; i
< channels
; i
++)
568 data
[i
] = (AudioData
*) g_malloc (sizeof (AudioData
));
570 data
[0]->dest
= dest
;
571 data
[0]->distance
= GetOutputBytesPerFrame ();
572 // Interleaved multi-channel audio data
573 for (unsigned int i
= 1; i
< channels
; i
++) {
574 data
[i
]->dest
= ((char *) dest
) + output_bytes_per_sample
* i
;
575 data
[i
]->distance
= data
[0]->distance
;
577 data
[channels
] = NULL
;
578 result
= WriteFull (data
, samples
);
580 for (int i
= 0; data
[i
] != NULL
; i
++) {
588 AudioSource::WriteFull (AudioData
**channel_data
, guint32 samples
)
590 guint32 channels
= GetChannels ();
591 gint32
*volumes
= (gint32
*) g_alloca (sizeof (gint32
) * channels
);
595 gint16
**write_ptr
= (gint16
**) g_alloca (sizeof (gint16
*) * channels
);
597 guint32 bytes_per_frame
= input_bytes_per_sample
* channels
;
598 guint32 frames_to_write
;
599 guint32 bytes_available
;
600 guint32 bytes_written
;
602 guint64 last_frame_pts
= 0; // The pts of the last frame which was used to write samples
603 guint64 last_frame_samples
= 0; // Samples written from the last frame
604 IMediaStream
*stream
;
606 SetCurrentDeployment (false);
609 if (channel_data
== NULL
) {
610 SetState (AudioError
);
613 for (guint32 i
= 0; i
< channels
; i
++) {
614 if (channel_data
[i
] == NULL
) {
615 LOG_AUDIO ("AudioSource::WriteFull (%p, %u): channel data #%i is NULL\n", channel_data
, samples
, i
);
616 SetState (AudioError
);
620 if (channel_data
[channels
] != NULL
) {
621 SetState (AudioError
);
625 stream
= GetStreamReffed ();
626 if (stream
== NULL
) {
627 LOG_AUDIO ("AudioSource::WriteFull (): no stream.\n");
633 volume
= this->volume
* 8192;
634 balance
= this->balance
;
635 muted
= false; //this->muted;
637 // Set the per-channel volume
639 // TODO: how does the balance work here?
640 // We probably need a channel map to figure out left and right
641 for (unsigned int i
= 0; i
< channels
; i
++) {
642 volumes
[i
] = muted
? 0.0 : volume
;
644 } else if (channels
== 2) {
646 volumes
[0] = volumes
[1] = 0;
647 } else if (balance
< 0.0) {
648 volumes
[0] = volume
;
649 volumes
[1] = (1.0 + balance
) * volume
;
650 } else if (balance
> 0.0) {
651 volumes
[0] = (1.0 - balance
) * volume
;
652 volumes
[1] = volume
;
654 volumes
[0] = volumes
[1] = volume
;
656 } else if (channels
== 1) {
660 volumes
[0] = volume
;
663 SetState (AudioError
);
667 for (guint32 i
= 0; i
< channels
; i
++)
668 write_ptr
[i
] = (gint16
*) channel_data
[i
]->dest
;
670 while (GetState () == AudioPlaying
) {
671 if (current_frame
== NULL
) {
672 MediaFrame
*frame
= stream
->PopFrame ();
674 current_frame
= new AudioFrame (frame
);
679 if (current_frame
== NULL
) {
680 if (stream
->GetOutputEnded ()) {
681 LOG_AUDIO ("AudioSource::WriteFull (): No more data and reached the end.\n");
682 SetFlag (AudioWaiting
, false);
683 SetFlag ((AudioFlags
) (AudioEOF
| AudioEnded
), true);
685 LOG_AUDIO ("AudioSource::WriteFull (): No more data, starting to wait...\n");
686 if (!GetFlag (AudioEOF
) && !GetFlag (AudioEnded
)) {
687 SetFlag (AudioWaiting
, true);
688 SetFlag ((AudioFlags
) (AudioEOF
| AudioEnded
), false);
694 bytes_available
= current_frame
->frame
->buflen
- current_frame
->bytes_used
;
696 if (bytes_available
< bytes_per_frame
) {
697 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
);
698 delete current_frame
;
699 current_frame
= NULL
;
703 frames_to_write
= MIN (bytes_available
/ bytes_per_frame
, samples
- result
);
704 bytes_written
= frames_to_write
* bytes_per_frame
;
707 fwrite ((((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
), 1, bytes_written
, dump_fd
);
710 switch (this->input_bytes_per_sample
) {
712 switch (this->output_bytes_per_sample
) {
714 // 16bit audio -> 16bit audio
715 gint16
*read_ptr
= (gint16
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
717 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
718 for (guint32 channel
= 0; channel
< channels
; channel
++) {
719 value
= ((*read_ptr
) * volumes
[channel
]) >> 13;
720 *(write_ptr
[channel
]) = (gint16
) CLAMP (value
, -32768, 32767);
721 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
727 default: // implement others as needed
728 LOG_AUDIO ("AudioSource::Write (): Invalid output_bytes_per_sample, expected 2, got: %i\n", this->output_bytes_per_sample
);
734 switch (this->output_bytes_per_sample
) {
736 // 24bit audio -> 16bit audio
737 gint16
*read_ptr
= (gint16
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
739 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
740 for (guint32 channel
= 0; channel
< channels
; channel
++) {
741 read_ptr
= (gint16
*) (((gint8
*) read_ptr
) + 1); // +1 byte
743 value
= (gint16
) CLAMP (((value
* volumes
[channel
]) >> 13), -32768, 32767);
744 *write_ptr
[channel
] = value
;
745 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
746 read_ptr
+= 1; // +2 bytes
751 // case 3: // 24bit audio -> 24bit audio, this is painful to both read and write.
753 // 24bit audio -> 32bit audio
754 gint32
*read_ptr
= (gint32
*) (((char *) current_frame
->frame
->buffer
) + current_frame
->bytes_used
);
756 for (guint32 i
= 0; i
< frames_to_write
; i
++) {
757 for (guint32 channel
= 0; channel
< channels
; channel
++) {
758 if (false && i
> 0) {
759 // can overread before, mask out the upper bits.
760 value
= * (gint32
*) (((gint8
*) read_ptr
) - 1);
763 // can't overread before, use byte pointers
765 ((guint8
*) &value
) [1] = (((guint8
*) read_ptr
) [0]);
766 ((guint8
*) &value
) [2] = (((guint8
*) read_ptr
) [1]);
767 ((guint8
*) &value
) [3] = (((guint8
*) read_ptr
) [2]);
769 // not sure how to calculate volume here, this shifts down 13 bits
770 // and then multiply with volume. This loses the lowest 5 bits of information
771 // from the 24 bit sample. Not quite sure how to do this with 32bit math without
772 // losing information though.
773 value
= (value
>> 13) * (volumes
[channel
]);
774 *((gint32
*) write_ptr
[channel
]) = value
;
775 write_ptr
[channel
] = (gint16
*) (((char *) write_ptr
[channel
]) + channel_data
[channel
]->distance
);
776 read_ptr
= (gint32
*) (((gint8
*) read_ptr
) + 3); // += input_bytes_per_sample;
781 default: // implement others as needed
782 LOG_AUDIO ("AudioSource::Write (): Invalid output_bytes_per_sample, expected 2 or 4, got: %i\n", this->output_bytes_per_sample
);
788 LOG_AUDIO ("AudioSource::Write (): Invalid input_bytes_per_sample, can only be 2 or 3, but got: %i\n", this->input_bytes_per_sample
);
789 SetState (AudioError
);
793 result
+= frames_to_write
;
794 current_frame
->bytes_used
+= bytes_written
;
796 last_frame_samples
= current_frame
->bytes_used
/ GetInputBytesPerFrame ();
797 last_frame_pts
= current_frame
->frame
->pts
;
799 if (current_frame
->bytes_used
== current_frame
->frame
->buflen
) {
800 // We used the entire packet
801 delete current_frame
;
802 current_frame
= NULL
;
804 // There is still audio data left in the packet, just leave it.
807 if (result
== samples
) {
808 // We've written all we were requested to write
811 //printf ("AudioSource::WriteFull (): Written %u samples of %u requested samples, getting new packet (%i packets left)\n", result, samples, frames.Length ());
816 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
);
819 last_write_pts
= last_frame_pts
+ MilliSeconds_ToPts (last_frame_samples
* 1000 / GetSampleRate ());
834 AudioListNode::AudioListNode (AudioSource
*source
)
836 this->source
= source
;
837 this->source
->ref ();
841 AudioListNode::~AudioListNode ()
843 this->source
->unref ();
850 AudioSources::AudioSources ()
852 pthread_mutex_init (&mutex
, NULL
);
853 current_generation
= 0;
856 AudioSources::~AudioSources ()
858 pthread_mutex_destroy (&mutex
);
862 AudioSources::Lock ()
864 pthread_mutex_lock (&mutex
);
868 AudioSources::Unlock ()
870 pthread_mutex_unlock (&mutex
);
874 AudioSources::Add (AudioSource
*source
)
877 list
.Append (new AudioListNode (source
));
882 AudioSources::Remove (AudioSource
*source
)
888 node
= (AudioListNode
*) list
.First ();
889 while (node
!= NULL
) {
890 if (node
->source
== source
) {
892 if (last_node
== node
)
893 last_node
= (AudioListNode
*) node
->prev
;
898 node
= (AudioListNode
*) node
->next
;
907 AudioSources::StartEnumeration ()
910 current_generation
++;
916 AudioSources::GetNext (bool only_playing
)
918 AudioListNode
*node
= NULL
;
919 AudioSource
*result
= NULL
;
923 // Check the last node returned from GetNext
924 if (last_node
!= NULL
&& last_node
->next
!= NULL
) {
925 node
= (AudioListNode
*) last_node
->next
;
926 if (node
->generation
!= current_generation
&& (!only_playing
|| node
->source
->IsPlaying ()))
930 // Loop through all the nodes looking for a node not in the
931 // current generation.
932 node
= (AudioListNode
*) list
.First ();
933 while (node
!= NULL
&& (node
->generation
== current_generation
|| (only_playing
&& !node
->source
->IsPlaying ()))) {
934 node
= (AudioListNode
*) node
->next
;
937 // Its possible that the loop has started but nothing is playing, which without this guard would
938 // return list.First () in an infinite loop while we're downloading / buffering.
939 // (due to the while loop above not clearing out the first value (list.First ()) if the condition is false and there's no other
940 // node which satifies the condition)
941 if (only_playing
&& node
!= NULL
&& !node
->source
->IsPlaying ())
946 node
->generation
= current_generation
;
948 result
= node
->source
;
949 result
->SetCurrentDeployment (false);
952 Deployment::SetCurrent (NULL
, false);
961 AudioSources::GetHead ()
963 AudioSource
*result
= NULL
;
968 node
= (AudioListNode
*) list
.First ();
970 result
= node
->source
;
971 result
->SetCurrentDeployment (false);
982 AudioSources::Length ()
987 result
= list
.Length ();
998 AudioPlayer
* AudioPlayer::instance
= NULL
;
999 pthread_mutex_t
AudioPlayer::instance_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1001 AudioPlayer::AudioPlayer ()
1009 g_atomic_int_inc (&refcount
);
1013 AudioPlayer::unref ()
1015 int v
= g_atomic_int_exchange_and_add (&refcount
, -1) - 1;
1024 AudioPlayer::GetInstance ()
1026 AudioPlayer
*result
;
1027 pthread_mutex_lock (&instance_mutex
);
1031 pthread_mutex_unlock (&instance_mutex
);
1036 AudioPlayer::Add (MediaPlayer
*mplayer
, AudioStream
*stream
)
1039 AudioSource
*result
= NULL
;
1041 LOG_AUDIO ("AudioPlayer::Add (%p)\n", mplayer
);
1043 if (moonlight_flags
& RUNTIME_INIT_DISABLE_AUDIO
) {
1044 LOG_AUDIO ("AudioPlayer: audio is disabled.\n");
1048 pthread_mutex_lock (&instance_mutex
);
1049 if (instance
== NULL
) {
1050 /* here we get a (global) ref which is unreffed in Shutdown () */
1051 instance
= CreatePlayer ();
1055 inst
->ref (); /* this is the ref we unref below */
1056 pthread_mutex_unlock (&instance_mutex
);
1059 result
= inst
->AddImpl (mplayer
, stream
);
1067 AudioPlayer::Remove (AudioSource
*source
)
1071 LOG_AUDIO ("AudioPlayer::Remove (%p)\n", source
);
1073 inst
= GetInstance ();
1075 inst
->RemoveImpl (source
);
1081 AudioPlayer::Shutdown ()
1083 AudioPlayer
*player
= NULL
;
1085 LOG_AUDIO ("AudioPlayer::Shutdown ()\n");
1087 pthread_mutex_lock (&instance_mutex
);
1088 if (instance
!= NULL
) {
1092 pthread_mutex_unlock (&instance_mutex
);
1099 AudioPlayer::CreatePlayer ()
1102 AudioPlayer
*result
= NULL
;
1104 // If any of the flags are specified, we disable all players
1105 // and re-enable according to the flag.
1107 overridden
= moonlight_flags
& (RUNTIME_INIT_AUDIO_PULSE
| RUNTIME_INIT_AUDIO_ALSA
| RUNTIME_INIT_AUDIO_ALSA_MMAP
| RUNTIME_INIT_AUDIO_ALSA_RW
);
1109 #if INCLUDE_PULSEAUDIO
1110 if (result
!= NULL
) {
1111 LOG_AUDIO ("AudioPlayer: Not checking for PulseAudio support, we already found support for another configuration.\n");
1112 } else if (overridden
&& !(moonlight_flags
& RUNTIME_INIT_AUDIO_PULSE
)) {
1113 LOG_AUDIO ("AudioPlayer: PulseAudio disabled with environment variable (MOONLIGHT_OVERRIDES)\n");
1114 } else if (!PulsePlayer::IsInstalled ()) {
1115 LOG_AUDIO ("AudioPlayer: PulseAudio is not installed or configured correctly.\n");
1117 printf ("AudioPlayer: Using PulseAudio.\n");
1118 result
= new PulsePlayer ();
1121 if (result
!= NULL
) {
1122 if (!result
->Initialize ()) {
1123 LOG_AUDIO ("AudioPlayer: Failed initialization.\n");
1131 LOG_AUDIO ("AudioPlayer: Built without support for pulseaudio.\n");
1135 if (result
!= NULL
) {
1136 LOG_AUDIO ("AudioPlayer: Not checking for Alsa support, we already found support for another configuration.\n");
1137 } else if (overridden
&& !(moonlight_flags
& (RUNTIME_INIT_AUDIO_ALSA
| RUNTIME_INIT_AUDIO_ALSA_MMAP
| RUNTIME_INIT_AUDIO_ALSA_RW
))) {
1138 LOG_AUDIO ("AudioPlayer: Alsa disabled with environment variable (MOONLIGHT_OVERRIDES)\n");
1139 } else if (!AlsaPlayer::IsInstalled ()) {
1140 LOG_AUDIO ("AudioPlayer: Alsa is not installed or configured correctly.\n");
1142 printf ("AudioPlayer: Using Alsa.\n");
1143 result
= new AlsaPlayer ();
1146 if (result
!= NULL
) {
1147 if (!result
->Initialize ()) {
1148 LOG_AUDIO ("AudioPlayer: Failed initialization.\n");
1156 LOG_AUDIO ("AudioPlayer: Built without support for alsa.\n");
1163 AudioPlayer::AddImpl (MediaPlayer
*mplayer
, AudioStream
*stream
)
1165 AudioSource
*result
= CreateNode (mplayer
, stream
);
1167 if (result
->Initialize ()) {
1168 sources
.Add (result
);
1169 AddInternal (result
);
1179 AudioPlayer::RemoveImpl (AudioSource
*node
)
1182 if (sources
.Remove (node
)) {
1183 RemoveInternal (node
);
1190 AudioPlayer::Dispose ()
1196 AudioPlayer::ShutdownImpl ()
1198 AudioSource
*source
;
1200 PrepareShutdownInternal ();
1202 // Remove all the sources.
1203 while ((source
= sources
.GetHead ()) != NULL
) {
1204 RemoveImpl (source
);
1208 FinishShutdownInternal ();