2009-11-08 Chris Toshok <toshok@ximian.com>
[moon.git] / src / audio.cpp
blobf069e9fd419e76cd05a51e2828047dd6e4c12306
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * audio.cpp:
5 * Contact:
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.
13 #include <config.h>
15 #include <pthread.h>
17 #include "audio.h"
18 #include "audio-alsa.h"
19 #include "audio-pulse.h"
20 #include "pipeline.h"
21 #include "runtime.h"
22 #include "clock.h"
23 #include "debug.h"
24 #include "mediaplayer.h"
25 #include "deployment.h"
28 * AudioSource::AudioFrame
31 AudioSource::AudioFrame::AudioFrame (MediaFrame *frame)
33 this->frame = frame;
34 this->frame->ref ();
35 bytes_used = 0;
38 AudioSource::AudioFrame::~AudioFrame ()
40 frame->unref ();
44 * AudioSource
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;
55 this->stream->ref ();
56 this->player = player;
58 stream->AddSafeHandler (IMediaStream::FirstFrameEnqueuedEvent, FirstFrameEnqueuedCallback, this, false);
60 current_frame = NULL;
62 state = AudioNone;
63 flags = (AudioFlags) 0;
65 balance = 0.0f;
66 volume = 1.0f;
67 muted = false;
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);
83 #ifdef DUMP_AUDIO
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);
88 g_free (fname);
89 #endif
92 AudioSource::~AudioSource ()
94 pthread_mutex_destroy (&mutex);
96 #ifdef DUMP_AUDIO
97 fclose (dump_fd);
98 #endif
101 void
102 AudioSource::Dispose ()
104 IMediaStream *stream;
105 MediaPlayer *mplayer;
106 AudioFrame *current_frame;
108 Stop ();
110 Lock ();
111 stream = this->stream;
112 this->stream = NULL;
113 mplayer = this->mplayer;
114 this->mplayer = NULL;
115 current_frame = this->current_frame;
116 this->current_frame = NULL;
117 Unlock ();
119 if (stream) {
120 stream->RemoveAllHandlers (this);
121 stream->unref ();
122 stream = NULL;
125 if (mplayer) {
126 mplayer->unref ();
127 mplayer = NULL;
130 if (current_frame) {
131 delete current_frame;
132 current_frame = NULL;
135 EventObject::Dispose ();
138 MediaPlayer *
139 AudioSource::GetMediaPlayerReffed ()
141 MediaPlayer *result = NULL;
142 Lock ();
143 if (mplayer != NULL) {
144 result = mplayer;
145 result->ref ();
147 Unlock ();
148 return result;
151 void
152 AudioSource::Lock ()
154 pthread_mutex_lock (&mutex);
157 void
158 AudioSource::Unlock ()
160 pthread_mutex_unlock (&mutex);
163 AudioStream *
164 AudioSource::GetAudioStream ()
166 AudioStream *result;
167 Lock ();
168 result = stream;
169 Unlock ();
170 return result;
173 void
174 AudioSource::SetAudioStream (AudioStream *value)
176 Lock ();
177 if (stream)
178 stream->unref ();
179 stream = value;
180 if (stream)
181 stream->ref ();
182 Unlock ();
185 guint32
186 AudioSource::GetInputBytesPerFrame ()
188 /* No locking required, this can only be set during initialization */
189 return channels * input_bytes_per_sample;
192 guint32
193 AudioSource::GetInputBytesPerSample ()
195 /* No locking required, this can only be set during initialization */
196 return input_bytes_per_sample;
199 guint32
200 AudioSource::GetOutputBytesPerFrame ()
202 /* No locking required, this can only be set during initialization */
203 return channels * output_bytes_per_sample;
206 guint32
207 AudioSource::GetOutputBytesPerSample ()
209 /* No locking required, this can only be set during initialization */
210 return output_bytes_per_sample;
213 void
214 AudioSource::SetOutputBytesPerSample (guint32 value)
216 /* No locking required, this can only be set during initialization */
217 output_bytes_per_sample = value;
220 AudioStream *
221 AudioSource::GetStreamReffed ()
223 AudioStream *result;
224 Lock ();
225 result = stream;
226 if (result)
227 result->ref ();
228 Unlock ();
229 return result;
232 void
233 AudioSource::SetFlag (AudioFlags flag, bool value)
235 Lock ();
236 if (value) {
237 flags = (AudioFlags) (flag | flags);
238 } else {
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));
242 Unlock ();
245 bool
246 AudioSource::GetFlag (AudioFlags flag)
248 return flags & flag;
251 #if DEBUG
252 char *
253 AudioSource::GetFlagNames (AudioFlags flags)
255 const char *v [5];
256 int i = 0;
257 v [0] = v [1] = v [2] = v [3] = v [4] = NULL;
259 if (flags & AudioInitialized)
260 v [i++] = "Initialized";
262 if (flags & AudioEOF)
263 v [i++] = "EOF";
265 if (flags & AudioWaiting)
266 v [i++] = "Waiting";
268 if (flags & AudioEnded)
269 v [i++] = "Ended";
271 return (char *) g_strjoinv (",", (gchar **) v);
274 #endif
276 const char *
277 AudioSource::GetStateName (AudioState state)
279 switch (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";
289 AudioState
290 AudioSource::GetState ()
292 AudioState result;
293 Lock ();
294 result = state;
295 Unlock ();
296 return result;
299 void
300 AudioSource::SetState (AudioState value)
302 AudioState old_state;
303 bool changed = false;
304 bool audio_failed = false;
306 Lock ();
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));
310 } else {
311 old_state = state;
312 state = value;
313 changed = true;
314 if (value == AudioError)
315 audio_failed = true;
318 Unlock ();
320 if (audio_failed) {
321 MediaPlayer *mplayer = GetMediaPlayerReffed ();
322 if (mplayer != NULL) {
323 mplayer->AudioFailed (this);
324 mplayer->unref ();
328 LOG_AUDIO_EX ("AudioSource::SetState (%s), old state: %s, changed: %i\n", GetStateName (value), GetStateName (old_state), changed);
330 if (changed)
331 StateChanged (old_state);
334 double
335 AudioSource::GetBalance ()
337 double result;
338 Lock ();
339 result = balance;
340 Unlock ();
341 return result;
344 void
345 AudioSource::SetBalance (double value)
347 Lock ();
348 balance = value;
349 Unlock ();
352 double
353 AudioSource::GetVolume ()
355 double result;
356 Lock ();
357 result = volume;
358 Unlock ();
359 return result;
362 void
363 AudioSource::SetVolume (double value)
365 Lock ();
366 volume = value;
367 Unlock ();
370 bool
371 AudioSource::GetMuted ()
373 bool result;
374 Lock ();
375 result = muted;
376 Unlock ();
377 return result;
380 void
381 AudioSource::SetMuted (bool value)
383 Lock ();
384 muted = value;
385 Unlock ();
388 guint32
389 AudioSource::GetChannels ()
391 // This can only be set during initialization, so there's no need to lock here.
392 return channels;
395 guint32
396 AudioSource::GetSampleRate ()
398 // This can only be set during initialization, so there's no need to lock here.
399 return sample_rate;
402 bool
403 AudioSource::IsQueueEmpty ()
405 bool result;
406 AudioStream *stream;
408 LOG_AUDIO_EX ("AudioSource::IsQueueEmpty ().\n");
410 stream = GetStreamReffed ();
412 if (stream == NULL) {
413 result = true;
414 } else {
415 result = stream->IsQueueEmpty ();
416 stream->unref ();
419 return result;
422 void
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)
430 Play ();
434 guint64
435 AudioSource::GetDelay ()
437 return GetDelayInternal ();
440 guint64
441 AudioSource::GetCurrentPts ()
443 guint64 delay = 0;
444 guint64 current_pts = 0;
445 guint64 result = 0;
447 if (GetState () != AudioPlaying) {
448 result = last_current_pts;
449 } else {
450 Lock ();
451 current_pts = last_write_pts;
452 Unlock ();
454 delay = GetDelay ();
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) {
461 result = 0;
462 } else {
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));
472 return result;
475 void
476 AudioSource::Stop ()
478 LOG_AUDIO ("AudioSource::Stop ()\n");
480 Lock ();
481 SetState (AudioStopped);
482 last_current_pts = G_MAXUINT64;
483 last_write_pts = G_MAXUINT64;
484 delete current_frame;
485 current_frame = NULL;
486 Unlock ();
487 Stopped ();
490 void
491 AudioSource::Play ()
493 LOG_AUDIO ("AudioSource::Play ()\n");
495 SetState (AudioPlaying);
496 SetFlag ((AudioFlags) (AudioEnded | AudioEOF | AudioWaiting), false);
497 Played ();
500 void
501 AudioSource::Pause ()
503 LOG_AUDIO ("AudioSource::Pause ()\n");
505 SetState (AudioPaused);
506 Paused ();
509 void
510 AudioSource::Underflowed ()
512 MediaPlayer *mplayer;
513 LOG_AUDIO ("AudioSource::Underflowed (), state: %s, flags: %s\n", GetStateName (GetState ()), GetFlagNames (flags));
515 if (IsDisposed ())
516 return;
518 SetCurrentDeployment (false);
520 mplayer = GetMediaPlayerReffed ();
522 if (GetState () == AudioPlaying) {
523 if (GetFlag (AudioEOF)) {
524 Stop ();
525 SetFlag (AudioEnded, true);
526 if (mplayer != NULL)
527 mplayer->AudioFinished ();
528 } else if (IsQueueEmpty ()) {
529 SetFlag (AudioWaiting, true);
530 if (mplayer != NULL)
531 mplayer->SetBufferUnderflow ();
535 if (mplayer != NULL)
536 mplayer->unref ();
539 bool
540 AudioSource::Initialize ()
542 bool result;
544 result = InitializeInternal ();
546 if (result) {
547 SetFlag (AudioInitialized, true);
548 } else {
549 SetFlag (AudioInitialized, false);
550 SetState (AudioError);
553 return result;
556 void
557 AudioSource::Close ()
559 CloseInternal ();
562 guint32
563 AudioSource::Write (void *dest, guint32 samples)
565 AudioData **data = (AudioData **) g_alloca (sizeof (AudioData *) * (channels + 1));
566 guint32 result = 0;
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++) {
582 g_free (data [i]);
585 return result;
588 guint32
589 AudioSource::WriteFull (AudioData **channel_data, guint32 samples)
591 guint32 channels = GetChannels ();
592 gint32 *volumes = (gint32 *) g_alloca (sizeof (gint32) * channels);
593 gint32 volume;
594 double balance;
595 bool muted;
596 gint16 **write_ptr = (gint16 **) g_alloca (sizeof (gint16 *) * channels);
597 guint32 result = 0;
598 guint32 bytes_per_frame = input_bytes_per_sample * channels;
599 guint32 frames_to_write;
600 guint32 bytes_available;
601 guint32 bytes_written;
602 gint32 value;
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);
609 // Validate input
610 if (channel_data == NULL) {
611 SetState (AudioError);
612 return 0;
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);
618 return 0;
621 if (channel_data [channels] != NULL) {
622 SetState (AudioError);
623 return 0;
626 stream = GetStreamReffed ();
627 if (stream == NULL) {
628 LOG_AUDIO ("AudioSource::WriteFull (): no stream.\n");
629 return 0;
632 Lock ();
634 volume = this->volume * 8192;
635 balance = this->balance;
636 muted = false; //this->muted;
638 // Set the per-channel volume
639 if (channels > 2) {
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) {
646 if (muted) {
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;
654 } else {
655 volumes [0] = volumes [1] = volume;
657 } else if (channels == 1) {
658 if (muted) {
659 volumes [0] = 0;
660 } else {
661 volumes [0] = volume;
663 } else {
664 SetState (AudioError);
665 goto cleanup;
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 ();
674 if (frame != NULL) {
675 current_frame = new AudioFrame (frame);
676 frame->unref ();
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);
685 } else {
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);
692 goto cleanup;
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;
701 continue;
704 frames_to_write = MIN (bytes_available / bytes_per_frame, samples - result);
705 bytes_written = frames_to_write * bytes_per_frame;
707 #ifdef DUMP_AUDIO
708 fwrite ((((char *) current_frame->frame->buffer) + current_frame->bytes_used), 1, bytes_written, dump_fd);
709 #endif
711 switch (this->input_bytes_per_sample) {
712 case 2: {
713 switch (this->output_bytes_per_sample) {
714 case 2: {
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);
723 read_ptr++;
726 break;
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);
730 break;
732 break;
734 case 3: {
735 switch (this->output_bytes_per_sample) {
736 case 2: {
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
743 value = *read_ptr;
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
750 break;
752 // case 3: // 24bit audio -> 24bit audio, this is painful to both read and write.
753 case 4: {
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);
762 value &= 0xFFFFFF00;
763 } else {
764 // can't overread before, use byte pointers
765 value = 0;
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;
780 break;
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);
784 break;
786 break;
788 default:
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);
791 break;
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;
804 } else {
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
810 goto cleanup;
811 } else {
812 //printf ("AudioSource::WriteFull (): Written %u samples of %u requested samples, getting new packet (%i packets left)\n", result, samples, frames.Length ());
816 cleanup:
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);
819 if (result > 0) {
820 last_write_pts = last_frame_pts + MilliSeconds_ToPts (last_frame_samples * 1000 / GetSampleRate ());
823 Unlock ();
825 if (stream)
826 stream->unref ();
828 return result;
832 * AudioListNode
835 AudioListNode::AudioListNode (AudioSource *source)
837 this->source = source;
838 this->source->ref ();
839 generation = 0;
842 AudioListNode::~AudioListNode ()
844 this->source->unref ();
848 * AudioSources
851 AudioSources::AudioSources ()
853 pthread_mutex_init (&mutex, NULL);
854 current_generation = 0;
857 AudioSources::~AudioSources ()
859 pthread_mutex_destroy (&mutex);
862 void
863 AudioSources::Lock ()
865 pthread_mutex_lock (&mutex);
868 void
869 AudioSources::Unlock ()
871 pthread_mutex_unlock (&mutex);
874 void
875 AudioSources::Add (AudioSource *source)
877 Lock ();
878 list.Append (new AudioListNode (source));
879 Unlock ();
882 bool
883 AudioSources::Remove (AudioSource *source)
885 AudioListNode *node;
886 bool result = false;
888 Lock ();
889 node = (AudioListNode *) list.First ();
890 while (node != NULL) {
891 if (node->source == source) {
892 result = true;
893 if (last_node == node)
894 last_node = (AudioListNode *) node->prev;
895 list.Remove (node);
896 source->unref ();
897 break;
899 node = (AudioListNode *) node->next;
901 last_node = NULL;
902 Unlock ();
904 return result;
907 void
908 AudioSources::StartEnumeration ()
910 Lock ();
911 current_generation++;
912 last_node = NULL;
913 Unlock ();
916 AudioSource *
917 AudioSources::GetNext (bool only_playing)
919 AudioListNode *node = NULL;
920 AudioSource *result = NULL;
922 Lock ();
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 ()))
928 goto cleanup;
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 ())
943 node = NULL;
945 cleanup:
946 if (node) {
947 node->generation = current_generation;
948 last_node = node;
949 result = node->source;
950 result->SetCurrentDeployment (false);
951 result->ref ();
952 } else {
953 Deployment::SetCurrent (NULL, false);
956 Unlock ();
958 return result;
961 AudioSource *
962 AudioSources::GetHead ()
964 AudioSource *result = NULL;
965 AudioListNode *node;
967 Lock ();
969 node = (AudioListNode *) list.First ();
970 if (node != NULL) {
971 result = node->source;
972 result->SetCurrentDeployment (false);
973 result->ref ();
976 Unlock ();
978 return result;
981 #if DEBUG
983 AudioSources::Length ()
985 int result = 0;
987 Lock ();
988 result = list.Length ();
989 Unlock ();
991 return result;
993 #endif
996 * AudioPlayer
999 AudioPlayer * AudioPlayer::instance = NULL;
1000 pthread_mutex_t AudioPlayer::instance_mutex = PTHREAD_MUTEX_INITIALIZER;
1002 AudioPlayer::AudioPlayer ()
1004 refcount = 1;
1007 void
1008 AudioPlayer::ref ()
1010 g_atomic_int_inc (&refcount);
1013 void
1014 AudioPlayer::unref ()
1016 int v = g_atomic_int_exchange_and_add (&refcount, -1) - 1;
1018 if (v == 0) {
1019 Dispose ();
1020 delete this;
1024 AudioPlayer *
1025 AudioPlayer::GetInstance ()
1027 AudioPlayer *result;
1028 pthread_mutex_lock (&instance_mutex);
1029 result = instance;
1030 if (result)
1031 result->ref ();
1032 pthread_mutex_unlock (&instance_mutex);
1033 return result;
1036 AudioSource *
1037 AudioPlayer::Add (MediaPlayer *mplayer, AudioStream *stream)
1039 AudioPlayer *inst;
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");
1046 return NULL;
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 ();
1054 inst = instance;
1055 if (inst)
1056 inst->ref (); /* this is the ref we unref below */
1057 pthread_mutex_unlock (&instance_mutex);
1059 if (inst != NULL) {
1060 result = inst->AddImpl (mplayer, stream);
1061 inst->unref ();
1064 return result;
1067 void
1068 AudioPlayer::Remove (AudioSource *source)
1070 AudioPlayer *inst;
1072 LOG_AUDIO ("AudioPlayer::Remove (%p)\n", source);
1074 inst = GetInstance ();
1075 if (inst != NULL) {
1076 inst->RemoveImpl (source);
1077 inst->unref ();
1081 void
1082 AudioPlayer::Shutdown ()
1084 AudioPlayer *player = NULL;
1086 LOG_AUDIO ("AudioPlayer::Shutdown ()\n");
1088 pthread_mutex_lock (&instance_mutex);
1089 if (instance != NULL) {
1090 player = instance;
1091 instance = NULL;
1093 pthread_mutex_unlock (&instance_mutex);
1095 if (player != NULL)
1096 player->unref ();
1099 AudioPlayer *
1100 AudioPlayer::CreatePlayer ()
1102 bool overridden;
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");
1117 } else {
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");
1125 result->unref ();
1126 result = NULL;
1127 } else {
1128 return result;
1131 #else
1132 LOG_AUDIO ("AudioPlayer: Built without support for pulseaudio.\n");
1133 #endif
1135 #if INCLUDE_ALSA
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");
1142 } else {
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");
1150 result->unref ();
1151 result = NULL;
1152 } else {
1153 return result;
1156 #else
1157 LOG_AUDIO ("AudioPlayer: Built without support for alsa.\n");
1158 #endif
1160 return result;
1163 AudioSource *
1164 AudioPlayer::AddImpl (MediaPlayer *mplayer, AudioStream *stream)
1166 AudioSource *result = CreateNode (mplayer, stream);
1168 if (result->Initialize ()) {
1169 sources.Add (result);
1170 AddInternal (result);
1171 } else {
1172 result->unref ();
1173 result = NULL;
1176 return result;
1179 void
1180 AudioPlayer::RemoveImpl (AudioSource *node)
1182 node->ref ();
1183 if (sources.Remove (node)) {
1184 RemoveInternal (node);
1185 node->Close ();
1187 node->unref ();
1190 void
1191 AudioPlayer::Dispose ()
1193 ShutdownImpl ();
1196 void
1197 AudioPlayer::ShutdownImpl ()
1199 AudioSource *source;
1201 PrepareShutdownInternal ();
1203 // Remove all the sources.
1204 while ((source = sources.GetHead ()) != NULL) {
1205 RemoveImpl (source);
1206 source->unref ();
1209 FinishShutdownInternal ();