in plugin/:
[moon.git] / src / audio.cpp
blob712c306bfe331964f17cc7ee007c747f5387f08e
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"
27 * AudioSource::AudioFrame
30 AudioSource::AudioFrame::AudioFrame (MediaFrame *frame)
32 this->frame = frame;
33 this->frame->ref ();
34 bytes_used = 0;
37 AudioSource::AudioFrame::~AudioFrame ()
39 frame->unref ();
43 * AudioSource
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;
54 this->stream->ref ();
55 this->player = player;
57 stream->AddSafeHandler (IMediaStream::FirstFrameEnqueuedEvent, FirstFrameEnqueuedCallback, this, false);
59 current_frame = NULL;
61 state = AudioNone;
62 flags = (AudioFlags) 0;
64 balance = 0.0f;
65 volume = 1.0f;
66 muted = false;
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);
82 #ifdef DUMP_AUDIO
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);
87 g_free (fname);
88 #endif
91 AudioSource::~AudioSource ()
93 pthread_mutex_destroy (&mutex);
95 #ifdef DUMP_AUDIO
96 fclose (dump_fd);
97 #endif
100 void
101 AudioSource::Dispose ()
103 IMediaStream *stream;
104 MediaPlayer *mplayer;
105 AudioFrame *current_frame;
107 Stop ();
109 Lock ();
110 stream = this->stream;
111 this->stream = NULL;
112 mplayer = this->mplayer;
113 this->mplayer = NULL;
114 current_frame = this->current_frame;
115 this->current_frame = NULL;
116 Unlock ();
118 if (stream) {
119 stream->RemoveAllHandlers (this);
120 stream->unref ();
121 stream = NULL;
124 if (mplayer) {
125 mplayer->unref ();
126 mplayer = NULL;
129 if (current_frame) {
130 delete current_frame;
131 current_frame = NULL;
134 EventObject::Dispose ();
137 MediaPlayer *
138 AudioSource::GetMediaPlayerReffed ()
140 MediaPlayer *result = NULL;
141 Lock ();
142 if (mplayer != NULL) {
143 result = mplayer;
144 result->ref ();
146 Unlock ();
147 return result;
150 void
151 AudioSource::Lock ()
153 pthread_mutex_lock (&mutex);
156 void
157 AudioSource::Unlock ()
159 pthread_mutex_unlock (&mutex);
162 AudioStream *
163 AudioSource::GetAudioStream ()
165 AudioStream *result;
166 Lock ();
167 result = stream;
168 Unlock ();
169 return result;
172 void
173 AudioSource::SetAudioStream (AudioStream *value)
175 Lock ();
176 if (stream)
177 stream->unref ();
178 stream = value;
179 if (stream)
180 stream->ref ();
181 Unlock ();
184 guint32
185 AudioSource::GetInputBytesPerFrame ()
187 /* No locking required, this can only be set during initialization */
188 return channels * input_bytes_per_sample;
191 guint32
192 AudioSource::GetInputBytesPerSample ()
194 /* No locking required, this can only be set during initialization */
195 return input_bytes_per_sample;
198 guint32
199 AudioSource::GetOutputBytesPerFrame ()
201 /* No locking required, this can only be set during initialization */
202 return channels * output_bytes_per_sample;
205 guint32
206 AudioSource::GetOutputBytesPerSample ()
208 /* No locking required, this can only be set during initialization */
209 return output_bytes_per_sample;
212 void
213 AudioSource::SetOutputBytesPerSample (guint32 value)
215 /* No locking required, this can only be set during initialization */
216 output_bytes_per_sample = value;
219 AudioStream *
220 AudioSource::GetStreamReffed ()
222 AudioStream *result;
223 Lock ();
224 result = stream;
225 if (result)
226 result->ref ();
227 Unlock ();
228 return result;
231 void
232 AudioSource::SetFlag (AudioFlags flag, bool value)
234 Lock ();
235 if (value) {
236 flags = (AudioFlags) (flag | flags);
237 } else {
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));
241 Unlock ();
244 bool
245 AudioSource::GetFlag (AudioFlags flag)
247 return flags & flag;
250 #if DEBUG
251 char *
252 AudioSource::GetFlagNames (AudioFlags flags)
254 const char *v [5];
255 int i = 0;
256 v [0] = v [1] = v [2] = v [3] = v [4] = NULL;
258 if (flags & AudioInitialized)
259 v [i++] = "Initialized";
261 if (flags & AudioEOF)
262 v [i++] = "EOF";
264 if (flags & AudioWaiting)
265 v [i++] = "Waiting";
267 if (flags & AudioEnded)
268 v [i++] = "Ended";
270 return (char *) g_strjoinv (",", (gchar **) v);
273 #endif
275 const char *
276 AudioSource::GetStateName (AudioState state)
278 switch (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";
288 AudioState
289 AudioSource::GetState ()
291 AudioState result;
292 Lock ();
293 result = state;
294 Unlock ();
295 return result;
298 void
299 AudioSource::SetState (AudioState value)
301 AudioState old_state;
302 bool changed = false;
303 bool audio_failed = false;
305 Lock ();
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));
309 } else {
310 old_state = state;
311 state = value;
312 changed = true;
313 if (value == AudioError)
314 audio_failed = true;
317 Unlock ();
319 if (audio_failed) {
320 MediaPlayer *mplayer = GetMediaPlayerReffed ();
321 if (mplayer != NULL) {
322 mplayer->AudioFailed (this);
323 mplayer->unref ();
327 LOG_AUDIO_EX ("AudioSource::SetState (%s), old state: %s, changed: %i\n", GetStateName (value), GetStateName (old_state), changed);
329 if (changed)
330 StateChanged (old_state);
333 double
334 AudioSource::GetBalance ()
336 double result;
337 Lock ();
338 result = balance;
339 Unlock ();
340 return result;
343 void
344 AudioSource::SetBalance (double value)
346 Lock ();
347 balance = value;
348 Unlock ();
351 double
352 AudioSource::GetVolume ()
354 double result;
355 Lock ();
356 result = volume;
357 Unlock ();
358 return result;
361 void
362 AudioSource::SetVolume (double value)
364 Lock ();
365 volume = value;
366 Unlock ();
369 bool
370 AudioSource::GetMuted ()
372 bool result;
373 Lock ();
374 result = muted;
375 Unlock ();
376 return result;
379 void
380 AudioSource::SetMuted (bool value)
382 Lock ();
383 muted = value;
384 Unlock ();
387 guint32
388 AudioSource::GetChannels ()
390 // This can only be set during initialization, so there's no need to lock here.
391 return channels;
394 guint32
395 AudioSource::GetSampleRate ()
397 // This can only be set during initialization, so there's no need to lock here.
398 return sample_rate;
401 bool
402 AudioSource::IsQueueEmpty ()
404 bool result;
405 AudioStream *stream;
407 LOG_AUDIO_EX ("AudioSource::IsQueueEmpty ().\n");
409 stream = GetStreamReffed ();
411 if (stream == NULL) {
412 result = true;
413 } else {
414 result = stream->IsQueueEmpty ();
415 stream->unref ();
418 return result;
421 void
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)
429 Play ();
433 guint64
434 AudioSource::GetDelay ()
436 return GetDelayInternal ();
439 guint64
440 AudioSource::GetCurrentPts ()
442 guint64 delay = 0;
443 guint64 current_pts = 0;
444 guint64 result = 0;
446 if (GetState () != AudioPlaying) {
447 result = last_current_pts;
448 } else {
449 Lock ();
450 current_pts = last_write_pts;
451 Unlock ();
453 delay = GetDelay ();
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) {
460 result = 0;
461 } else {
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));
471 return result;
474 void
475 AudioSource::Stop ()
477 LOG_AUDIO ("AudioSource::Stop ()\n");
479 Lock ();
480 SetState (AudioStopped);
481 last_current_pts = G_MAXUINT64;
482 last_write_pts = G_MAXUINT64;
483 delete current_frame;
484 current_frame = NULL;
485 Unlock ();
486 Stopped ();
489 void
490 AudioSource::Play ()
492 LOG_AUDIO ("AudioSource::Play ()\n");
494 SetState (AudioPlaying);
495 SetFlag ((AudioFlags) (AudioEnded | AudioEOF | AudioWaiting), false);
496 Played ();
499 void
500 AudioSource::Pause ()
502 LOG_AUDIO ("AudioSource::Pause ()\n");
504 SetState (AudioPaused);
505 Paused ();
508 void
509 AudioSource::Underflowed ()
511 MediaPlayer *mplayer;
512 LOG_AUDIO ("AudioSource::Underflowed (), state: %s, flags: %s\n", GetStateName (GetState ()), GetFlagNames (flags));
514 if (IsDisposed ())
515 return;
517 SetCurrentDeployment (false);
519 mplayer = GetMediaPlayerReffed ();
521 if (GetState () == AudioPlaying) {
522 if (GetFlag (AudioEOF)) {
523 Stop ();
524 SetFlag (AudioEnded, true);
525 if (mplayer != NULL)
526 mplayer->AudioFinished ();
527 } else if (IsQueueEmpty ()) {
528 SetFlag (AudioWaiting, true);
529 if (mplayer != NULL)
530 mplayer->SetBufferUnderflow ();
534 if (mplayer != NULL)
535 mplayer->unref ();
538 bool
539 AudioSource::Initialize ()
541 bool result;
543 result = InitializeInternal ();
545 if (result) {
546 SetFlag (AudioInitialized, true);
547 } else {
548 SetFlag (AudioInitialized, false);
549 SetState (AudioError);
552 return result;
555 void
556 AudioSource::Close ()
558 CloseInternal ();
561 guint32
562 AudioSource::Write (void *dest, guint32 samples)
564 AudioData **data = (AudioData **) g_alloca (sizeof (AudioData *) * (channels + 1));
565 guint32 result = 0;
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++) {
581 g_free (data [i]);
584 return result;
587 guint32
588 AudioSource::WriteFull (AudioData **channel_data, guint32 samples)
590 guint32 channels = GetChannels ();
591 gint32 *volumes = (gint32 *) g_alloca (sizeof (gint32) * channels);
592 gint32 volume;
593 double balance;
594 bool muted;
595 gint16 **write_ptr = (gint16 **) g_alloca (sizeof (gint16 *) * channels);
596 guint32 result = 0;
597 guint32 bytes_per_frame = input_bytes_per_sample * channels;
598 guint32 frames_to_write;
599 guint32 bytes_available;
600 guint32 bytes_written;
601 gint32 value;
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);
608 // Validate input
609 if (channel_data == NULL) {
610 SetState (AudioError);
611 return 0;
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);
617 return 0;
620 if (channel_data [channels] != NULL) {
621 SetState (AudioError);
622 return 0;
625 stream = GetStreamReffed ();
626 if (stream == NULL) {
627 LOG_AUDIO ("AudioSource::WriteFull (): no stream.\n");
628 return 0;
631 Lock ();
633 volume = this->volume * 8192;
634 balance = this->balance;
635 muted = false; //this->muted;
637 // Set the per-channel volume
638 if (channels > 2) {
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) {
645 if (muted) {
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;
653 } else {
654 volumes [0] = volumes [1] = volume;
656 } else if (channels == 1) {
657 if (muted) {
658 volumes [0] = 0;
659 } else {
660 volumes [0] = volume;
662 } else {
663 SetState (AudioError);
664 goto cleanup;
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 ();
673 if (frame != NULL) {
674 current_frame = new AudioFrame (frame);
675 frame->unref ();
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);
684 } else {
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);
691 goto cleanup;
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;
700 continue;
703 frames_to_write = MIN (bytes_available / bytes_per_frame, samples - result);
704 bytes_written = frames_to_write * bytes_per_frame;
706 #ifdef DUMP_AUDIO
707 fwrite ((((char *) current_frame->frame->buffer) + current_frame->bytes_used), 1, bytes_written, dump_fd);
708 #endif
710 switch (this->input_bytes_per_sample) {
711 case 2: {
712 switch (this->output_bytes_per_sample) {
713 case 2: {
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);
722 read_ptr++;
725 break;
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);
729 break;
731 break;
733 case 3: {
734 switch (this->output_bytes_per_sample) {
735 case 2: {
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
742 value = *read_ptr;
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
749 break;
751 // case 3: // 24bit audio -> 24bit audio, this is painful to both read and write.
752 case 4: {
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);
761 value &= 0xFFFFFF00;
762 } else {
763 // can't overread before, use byte pointers
764 value = 0;
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;
779 break;
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);
783 break;
785 break;
787 default:
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);
790 break;
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;
803 } else {
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
809 goto cleanup;
810 } else {
811 //printf ("AudioSource::WriteFull (): Written %u samples of %u requested samples, getting new packet (%i packets left)\n", result, samples, frames.Length ());
815 cleanup:
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);
818 if (result > 0) {
819 last_write_pts = last_frame_pts + MilliSeconds_ToPts (last_frame_samples * 1000 / GetSampleRate ());
822 Unlock ();
824 if (stream)
825 stream->unref ();
827 return result;
831 * AudioListNode
834 AudioListNode::AudioListNode (AudioSource *source)
836 this->source = source;
837 this->source->ref ();
838 generation = 0;
841 AudioListNode::~AudioListNode ()
843 this->source->unref ();
847 * AudioSources
850 AudioSources::AudioSources ()
852 pthread_mutex_init (&mutex, NULL);
853 current_generation = 0;
856 AudioSources::~AudioSources ()
858 pthread_mutex_destroy (&mutex);
861 void
862 AudioSources::Lock ()
864 pthread_mutex_lock (&mutex);
867 void
868 AudioSources::Unlock ()
870 pthread_mutex_unlock (&mutex);
873 void
874 AudioSources::Add (AudioSource *source)
876 Lock ();
877 list.Append (new AudioListNode (source));
878 Unlock ();
881 bool
882 AudioSources::Remove (AudioSource *source)
884 AudioListNode *node;
885 bool result = false;
887 Lock ();
888 node = (AudioListNode *) list.First ();
889 while (node != NULL) {
890 if (node->source == source) {
891 result = true;
892 if (last_node == node)
893 last_node = (AudioListNode *) node->prev;
894 list.Remove (node);
895 source->unref ();
896 break;
898 node = (AudioListNode *) node->next;
900 last_node = NULL;
901 Unlock ();
903 return result;
906 void
907 AudioSources::StartEnumeration ()
909 Lock ();
910 current_generation++;
911 last_node = NULL;
912 Unlock ();
915 AudioSource *
916 AudioSources::GetNext (bool only_playing)
918 AudioListNode *node = NULL;
919 AudioSource *result = NULL;
921 Lock ();
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 ()))
927 goto cleanup;
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 ())
942 node = NULL;
944 cleanup:
945 if (node) {
946 node->generation = current_generation;
947 last_node = node;
948 result = node->source;
949 result->SetCurrentDeployment (false);
950 result->ref ();
951 } else {
952 Deployment::SetCurrent (NULL, false);
955 Unlock ();
957 return result;
960 AudioSource *
961 AudioSources::GetHead ()
963 AudioSource *result = NULL;
964 AudioListNode *node;
966 Lock ();
968 node = (AudioListNode *) list.First ();
969 if (node != NULL) {
970 result = node->source;
971 result->SetCurrentDeployment (false);
972 result->ref ();
975 Unlock ();
977 return result;
980 #if DEBUG
982 AudioSources::Length ()
984 int result = 0;
986 Lock ();
987 result = list.Length ();
988 Unlock ();
990 return result;
992 #endif
995 * AudioPlayer
998 AudioPlayer * AudioPlayer::instance = NULL;
999 pthread_mutex_t AudioPlayer::instance_mutex = PTHREAD_MUTEX_INITIALIZER;
1001 AudioPlayer::AudioPlayer ()
1003 refcount = 1;
1006 void
1007 AudioPlayer::ref ()
1009 g_atomic_int_inc (&refcount);
1012 void
1013 AudioPlayer::unref ()
1015 int v = g_atomic_int_exchange_and_add (&refcount, -1) - 1;
1017 if (v == 0) {
1018 Dispose ();
1019 delete this;
1023 AudioPlayer *
1024 AudioPlayer::GetInstance ()
1026 AudioPlayer *result;
1027 pthread_mutex_lock (&instance_mutex);
1028 result = instance;
1029 if (result)
1030 result->ref ();
1031 pthread_mutex_unlock (&instance_mutex);
1032 return result;
1035 AudioSource *
1036 AudioPlayer::Add (MediaPlayer *mplayer, AudioStream *stream)
1038 AudioPlayer *inst;
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");
1045 return NULL;
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 ();
1053 inst = instance;
1054 if (inst)
1055 inst->ref (); /* this is the ref we unref below */
1056 pthread_mutex_unlock (&instance_mutex);
1058 if (inst != NULL) {
1059 result = inst->AddImpl (mplayer, stream);
1060 inst->unref ();
1063 return result;
1066 void
1067 AudioPlayer::Remove (AudioSource *source)
1069 AudioPlayer *inst;
1071 LOG_AUDIO ("AudioPlayer::Remove (%p)\n", source);
1073 inst = GetInstance ();
1074 if (inst != NULL) {
1075 inst->RemoveImpl (source);
1076 inst->unref ();
1080 void
1081 AudioPlayer::Shutdown ()
1083 AudioPlayer *player = NULL;
1085 LOG_AUDIO ("AudioPlayer::Shutdown ()\n");
1087 pthread_mutex_lock (&instance_mutex);
1088 if (instance != NULL) {
1089 player = instance;
1090 instance = NULL;
1092 pthread_mutex_unlock (&instance_mutex);
1094 if (player != NULL)
1095 player->unref ();
1098 AudioPlayer *
1099 AudioPlayer::CreatePlayer ()
1101 bool overridden;
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");
1116 } else {
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");
1124 result->unref ();
1125 result = NULL;
1126 } else {
1127 return result;
1130 #else
1131 LOG_AUDIO ("AudioPlayer: Built without support for pulseaudio.\n");
1132 #endif
1134 #if INCLUDE_ALSA
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");
1141 } else {
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");
1149 result->unref ();
1150 result = NULL;
1151 } else {
1152 return result;
1155 #else
1156 LOG_AUDIO ("AudioPlayer: Built without support for alsa.\n");
1157 #endif
1159 return result;
1162 AudioSource *
1163 AudioPlayer::AddImpl (MediaPlayer *mplayer, AudioStream *stream)
1165 AudioSource *result = CreateNode (mplayer, stream);
1167 if (result->Initialize ()) {
1168 sources.Add (result);
1169 AddInternal (result);
1170 } else {
1171 result->unref ();
1172 result = NULL;
1175 return result;
1178 void
1179 AudioPlayer::RemoveImpl (AudioSource *node)
1181 node->ref ();
1182 if (sources.Remove (node)) {
1183 RemoveInternal (node);
1184 node->Close ();
1186 node->unref ();
1189 void
1190 AudioPlayer::Dispose ()
1192 ShutdownImpl ();
1195 void
1196 AudioPlayer::ShutdownImpl ()
1198 AudioSource *source;
1200 PrepareShutdownInternal ();
1202 // Remove all the sources.
1203 while ((source = sources.GetHead ()) != NULL) {
1204 RemoveImpl (source);
1205 source->unref ();
1208 FinishShutdownInternal ();