--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -593,17 +593,17 @@ protected:
nsRefPtr<gfxASurface> mPrintSurface;
// Reference to the source element last returned by GetNextSource().
// This is the child source element which we're trying to load from.
nsCOMPtr<nsIContent> mSourceLoadCandidate;
// An audio stream for writing audio directly from JS.
- nsAutoPtr<nsAudioStream> mAudioStream;
+ nsRefPtr<nsAudioStream> mAudioStream;
// PR_TRUE if MozAudioAvailable events can be safely dispatched, based on
// a media and element same-origin check.
PRBool mAllowAudioData;
// If true then we have begun downloading the media content.
// Set to false when completed, or not yet started.
PRPackedBool mBegun;
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -163,17 +163,17 @@ nsHTMLAudioElement::MozSetup(PRUint32 aC
if (0 == aChannels) {
return NS_ERROR_FAILURE;
}
if (mAudioStream) {
mAudioStream->Shutdown();
}
- mAudioStream = new nsAudioStream();
+ mAudioStream = nsAudioStream::AllocateStream();
nsresult rv = mAudioStream->Init(aChannels, aRate,
nsAudioStream::FORMAT_FLOAT32);
if (NS_FAILED(rv)) {
mAudioStream->Shutdown();
mAudioStream = nsnull;
return rv;
}
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -93,14 +93,16 @@ PARALLEL_DIRS += webm
endif
ifdef ENABLE_TESTS
PARALLEL_DIRS += test
endif
FORCE_STATIC_LIB = 1
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../base/src \
-I$(srcdir)/../html/content/src \
$(NULL)
--- a/content/media/nsAudioStream.cpp
+++ b/content/media/nsAudioStream.cpp
@@ -30,107 +30,381 @@
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+
+#ifdef MOZ_IPC
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/PAudioChild.h"
+#include "mozilla/dom/AudioChild.h"
+#include "nsXULAppAPI.h"
+using namespace mozilla::dom;
+#endif
+
#include <stdio.h>
#include <math.h>
#include "prlog.h"
#include "prmem.h"
#include "nsAutoPtr.h"
#include "nsAudioStream.h"
#include "nsAlgorithm.h"
extern "C" {
#include "sydneyaudio/sydney_audio.h"
}
#include "mozilla/TimeStamp.h"
+#include "nsThreadUtils.h"
#if defined(XP_MACOSX)
#define SA_PER_STREAM_VOLUME 1
#endif
using mozilla::TimeStamp;
#ifdef PR_LOGGING
PRLogModuleInfo* gAudioStreamLog = nsnull;
#endif
+#ifdef MOZ_IPC
+static nsIThread *gAudioPlaybackThread = nsnull;
+#endif
+
#define FAKE_BUFFER_SIZE 176400
#define MILLISECONDS_PER_SECOND 1000
+class nsAudioStreamLocal : public nsAudioStream
+{
+ public:
+ NS_DECL_ISUPPORTS
+
+ ~nsAudioStreamLocal();
+ nsAudioStreamLocal();
+
+ nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
+ void Shutdown();
+ nsresult Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking);
+ PRUint32 Available();
+ void SetVolume(float aVolume);
+ void Drain();
+ void Pause();
+ void Resume();
+ PRInt64 GetPosition();
+ PRInt64 GetSampleOffset();
+ PRBool IsPaused();
+
+ private:
+
+ double mVolume;
+ void* mAudioHandle;
+ int mRate;
+ int mChannels;
+
+ SampleFormat mFormat;
+
+ // When a Write() request is made, and the number of samples
+ // requested to be written exceeds the buffer size of the audio
+ // backend, the remaining samples are stored in this variable. They
+ // will be written on the next Write() request.
+ nsTArray<short> mBufferOverflow;
+
+ // PR_TRUE if this audio stream is paused.
+ PRPackedBool mPaused;
+
+ // PR_TRUE if this stream has encountered an error.
+ PRPackedBool mInError;
+
+};
+
+#ifdef MOZ_IPC
+class nsAudioStreamRemote : public nsAudioStream
+{
+ public:
+ NS_DECL_ISUPPORTS
+
+ nsAudioStreamRemote();
+ ~nsAudioStreamRemote();
+
+ nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
+ void Shutdown();
+ nsresult Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking);
+ PRUint32 Available();
+ void SetVolume(float aVolume);
+ void Drain();
+ void Pause();
+ void Resume();
+ PRInt64 GetPosition();
+ PRInt64 GetSampleOffset();
+ PRBool IsPaused();
+
+ AudioChild* mAudioChild;
+
+ SampleFormat mFormat;
+ int mRate;
+ int mChannels;
+ // PR_TRUE if this audio stream is paused.
+ PRPackedBool mPaused;
+
+ PRInt32 mBytesPerSample;
+
+ friend class AudioInitEvent;
+ friend class AudioShutdownEvent;
+ friend class AudioWriteEvent;
+ friend class AudioSetVolumeEvent;
+ friend class AudioPauseEvent;
+ friend class AudioDrainEvent;
+ friend class AudioGetSampleEvent;
+};
+
+class AudioInitEvent : public nsRunnable
+{
+ public:
+ AudioInitEvent(nsAudioStreamRemote* owner)
+ {
+ mOwner = owner;
+ }
+
+ NS_IMETHOD Run()
+ {
+ ContentChild * cpc = ContentChild::GetSingleton();
+ NS_ASSERTION(cpc, "Content Protocol is NULL!");
+ mOwner->mAudioChild = static_cast<AudioChild*> (cpc->SendPAudioConstructor(mOwner->mChannels,
+ mOwner->mRate,
+ mOwner->mFormat));
+ return NS_OK;
+ }
+
+ nsRefPtr<nsAudioStreamRemote> mOwner;
+};
+
+class AudioShutdownEvent : public nsRunnable
+{
+ public:
+ AudioShutdownEvent(nsAudioStreamRemote* owner)
+ {
+ mOwner = owner;
+ }
+
+ NS_IMETHOD Run()
+ {
+ if (mOwner->mAudioChild) {
+ PAudioChild::Send__delete__(mOwner->mAudioChild);
+ mOwner->mAudioChild = nsnull;
+ }
+ mOwner = nsnull;
+ return NS_OK;
+ }
+ nsRefPtr<nsAudioStreamRemote> mOwner;
+};
+
+class AudioWriteEvent : public nsRunnable
+{
+ public:
+ AudioWriteEvent(nsAudioStreamRemote* owner,
+ const void* aBuf,
+ PRUint32 aNumberOfSamples,
+ PRUint32 aBytesPerSample)
+ {
+ mOwner = owner;
+ mBytesPerSample = aBytesPerSample;
+ mBuffer.Assign((const char*)aBuf, aNumberOfSamples*aBytesPerSample);
+ }
+
+ NS_IMETHOD Run()
+ {
+ if (!mOwner->mAudioChild)
+ return NS_OK;
+
+ mOwner->mAudioChild->SendWrite(mBuffer,
+ mBuffer.Length() / mBytesPerSample);
+ return NS_OK;
+ }
+
+ nsRefPtr<nsAudioStreamRemote> mOwner;
+ nsCString mBuffer;
+ PRUint32 mBytesPerSample;
+};
+
+class AudioSetVolumeEvent : public nsRunnable
+{
+ public:
+ AudioSetVolumeEvent(nsAudioStreamRemote* owner, float volume)
+ {
+ mOwner = owner;
+ mVolume = volume;
+ }
+
+ NS_IMETHOD Run()
+ {
+ if (!mOwner->mAudioChild)
+ return NS_OK;
+
+ mOwner->mAudioChild->SendSetVolume(mVolume);
+ return NS_OK;
+ }
+
+ nsRefPtr<nsAudioStreamRemote> mOwner;
+ float mVolume;
+};
+
+class AudioDrainEvent : public nsRunnable
+{
+ public:
+ AudioDrainEvent(nsAudioStreamRemote* owner)
+ {
+ mOwner = owner;
+ }
+
+ NS_IMETHOD Run()
+ {
+ if (!mOwner->mAudioChild)
+ return NS_OK;
+
+ mOwner->mAudioChild->SendDrain();
+ return NS_OK;
+ }
+
+ nsRefPtr<nsAudioStreamRemote> mOwner;
+};
+
+
+class AudioPauseEvent : public nsRunnable
+{
+ public:
+ AudioPauseEvent(nsAudioStreamRemote* owner, PRBool pause)
+ {
+ mOwner = owner;
+ mPause = pause;
+ }
+
+ NS_IMETHOD Run()
+ {
+ if (!mOwner->mAudioChild)
+ return NS_OK;
+
+ if (mPause)
+ mOwner->mAudioChild->SendPause();
+ else
+ mOwner->mAudioChild->SendResume();
+
+ return NS_OK;
+ }
+
+ nsRefPtr<nsAudioStreamRemote> mOwner;
+ PRBool mPause;
+};
+
+
+#endif // MOZ_IPC
+
+
void nsAudioStream::InitLibrary()
{
#ifdef PR_LOGGING
gAudioStreamLog = PR_NewLogModule("nsAudioStream");
#endif
+
+#ifdef MOZ_IPC
+ // We only need this thread in the main process.
+ if (XRE_GetProcessType() == GeckoProcessType_Default) {
+ NS_NewThread(&gAudioPlaybackThread);
+ }
+#endif
}
void nsAudioStream::ShutdownLibrary()
{
+#ifdef MOZ_IPC
+ NS_IF_RELEASE(gAudioPlaybackThread);
+#endif
}
-nsAudioStream::nsAudioStream() :
+
+nsIThread *
+nsAudioStream::GetGlobalThread()
+{
+#ifdef MOZ_IPC
+ NS_IF_ADDREF(gAudioPlaybackThread);
+ return gAudioPlaybackThread;
+#else
+ return nsnull;
+#endif
+}
+
+nsAudioStream* nsAudioStream::AllocateStream()
+{
+ nsAudioStream* result = nsnull;
+
+#ifdef MOZ_IPC
+ if (XRE_GetProcessType() == GeckoProcessType_Content) {
+ return new nsAudioStreamRemote();
+ }
+#endif
+ return new nsAudioStreamLocal();
+}
+
+nsAudioStreamLocal::nsAudioStreamLocal() :
mVolume(1.0),
mAudioHandle(0),
mRate(0),
mChannels(0),
mFormat(FORMAT_S16_LE),
mPaused(PR_FALSE),
mInError(PR_FALSE)
{
}
-nsAudioStream::~nsAudioStream()
-{
- Shutdown();
-}
+nsAudioStreamLocal::~nsAudioStreamLocal(){}
-nsresult nsAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
+NS_IMPL_THREADSAFE_ISUPPORTS0(nsAudioStreamLocal)
+
+nsresult nsAudioStreamLocal::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
{
mRate = aRate;
mChannels = aNumChannels;
mFormat = aFormat;
+
if (sa_stream_create_pcm(reinterpret_cast<sa_stream_t**>(&mAudioHandle),
NULL,
SA_MODE_WRONLY,
SA_PCM_FORMAT_S16_NE,
aRate,
aNumChannels) != SA_SUCCESS) {
mAudioHandle = nsnull;
mInError = PR_TRUE;
- PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_create_pcm error"));
+ PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStreamLocal: sa_stream_create_pcm error"));
return NS_ERROR_FAILURE;
}
if (sa_stream_open(static_cast<sa_stream_t*>(mAudioHandle)) != SA_SUCCESS) {
sa_stream_destroy(static_cast<sa_stream_t*>(mAudioHandle));
mAudioHandle = nsnull;
mInError = PR_TRUE;
- PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_open error"));
+ PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStreamLocal: sa_stream_open error"));
return NS_ERROR_FAILURE;
}
mInError = PR_FALSE;
+
return NS_OK;
}
-void nsAudioStream::Shutdown()
+void nsAudioStreamLocal::Shutdown()
{
- if (!mAudioHandle)
+ if (!mAudioHandle)
return;
sa_stream_destroy(static_cast<sa_stream_t*>(mAudioHandle));
mAudioHandle = nsnull;
mInError = PR_TRUE;
}
-nsresult nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking)
+nsresult nsAudioStreamLocal::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking)
{
NS_ABORT_IF_FALSE(aCount % mChannels == 0,
"Buffer size must be divisible by channel count");
NS_ASSERTION(!mPaused, "Don't write audio when paused, you'll block");
if (mInError)
return NS_ERROR_FAILURE;
@@ -194,100 +468,99 @@ nsresult nsAudioStream::Write(const void
count = available;
}
}
if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
s_data.get(),
count * sizeof(short)) != SA_SUCCESS)
{
- PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error"));
+ PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStreamLocal: sa_stream_write error"));
mInError = PR_TRUE;
return NS_ERROR_FAILURE;
}
}
return NS_OK;
}
-PRUint32 nsAudioStream::Available()
+PRUint32 nsAudioStreamLocal::Available()
{
// If the audio backend failed to open, lie and say we'll accept some
// data.
if (mInError)
return FAKE_BUFFER_SIZE;
size_t s = 0;
if (sa_stream_get_write_size(static_cast<sa_stream_t*>(mAudioHandle), &s) != SA_SUCCESS)
return 0;
return s / sizeof(short);
}
-void nsAudioStream::SetVolume(float aVolume)
+void nsAudioStreamLocal::SetVolume(float aVolume)
{
NS_ASSERTION(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
#if defined(SA_PER_STREAM_VOLUME)
if (sa_stream_set_volume_abs(static_cast<sa_stream_t*>(mAudioHandle), aVolume) != SA_SUCCESS) {
- PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_set_volume_abs error"));
+ PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStreamLocal: sa_stream_set_volume_abs error"));
mInError = PR_TRUE;
}
#else
mVolume = aVolume;
#endif
}
-void nsAudioStream::Drain()
+void nsAudioStreamLocal::Drain()
{
if (mInError)
return;
// Write any remaining unwritten sound data in the overflow buffer
if (!mBufferOverflow.IsEmpty()) {
if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
mBufferOverflow.Elements(),
mBufferOverflow.Length() * sizeof(short)) != SA_SUCCESS)
- PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error"));
+ PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStreamLocal: sa_stream_write error"));
mInError = PR_TRUE;
return;
}
int r = sa_stream_drain(static_cast<sa_stream_t*>(mAudioHandle));
if (r != SA_SUCCESS && r != SA_ERROR_INVALID) {
- PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_drain error"));
+ PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStreamLocal: sa_stream_drain error"));
mInError = PR_TRUE;
}
}
-void nsAudioStream::Pause()
+void nsAudioStreamLocal::Pause()
{
if (mInError)
return;
mPaused = PR_TRUE;
sa_stream_pause(static_cast<sa_stream_t*>(mAudioHandle));
}
-void nsAudioStream::Resume()
+void nsAudioStreamLocal::Resume()
{
if (mInError)
return;
mPaused = PR_FALSE;
sa_stream_resume(static_cast<sa_stream_t*>(mAudioHandle));
}
-PRInt64 nsAudioStream::GetPosition()
+PRInt64 nsAudioStreamLocal::GetPosition()
{
PRInt64 sampleOffset = GetSampleOffset();
if (sampleOffset >= 0) {
return ((MILLISECONDS_PER_SECOND * sampleOffset) / mRate / mChannels);
}
-
return -1;
}
-PRInt64 nsAudioStream::GetSampleOffset()
+PRInt64 nsAudioStreamLocal::GetSampleOffset()
{
if (mInError) {
return -1;
}
sa_position_t positionType = SA_POSITION_WRITE_SOFTWARE;
#if defined(XP_WIN)
positionType = SA_POSITION_WRITE_HARDWARE;
@@ -295,8 +568,146 @@ PRInt64 nsAudioStream::GetSampleOffset()
PRInt64 position = 0;
if (sa_stream_get_position(static_cast<sa_stream_t*>(mAudioHandle),
positionType, &position) == SA_SUCCESS) {
return position / sizeof(short);
}
return -1;
}
+
+PRBool nsAudioStreamLocal::IsPaused()
+{
+ return mPaused;
+}
+
+#ifdef MOZ_IPC
+
+nsAudioStreamRemote::nsAudioStreamRemote()
+ : mAudioChild(NULL),
+ mFormat(FORMAT_S16_LE),
+ mRate(0),
+ mChannels(0),
+ mPaused(PR_FALSE),
+ mBytesPerSample(1)
+{}
+
+nsAudioStreamRemote::~nsAudioStreamRemote()
+{}
+
+NS_IMPL_THREADSAFE_ISUPPORTS0(nsAudioStreamRemote)
+
+nsresult
+nsAudioStreamRemote::Init(PRInt32 aNumChannels,
+ PRInt32 aRate,
+ SampleFormat aFormat)
+{
+ mRate = aRate;
+ mChannels = aNumChannels;
+ mFormat = aFormat;
+
+ switch (mFormat) {
+ case FORMAT_U8: {
+ mBytesPerSample = sizeof(PRUint8);
+ break;
+ }
+ case FORMAT_S16_LE: {
+ mBytesPerSample = sizeof(short);
+ break;
+ }
+ case FORMAT_FLOAT32: {
+ mBytesPerSample = sizeof(float);
+ }
+ }
+
+ nsCOMPtr<nsIRunnable> event = new AudioInitEvent(this);
+ NS_DispatchToMainThread(event);
+ return NS_OK;
+}
+
+void
+nsAudioStreamRemote::Shutdown()
+{
+ nsCOMPtr<nsIRunnable> event = new AudioShutdownEvent(this);
+ NS_DispatchToMainThread(event);
+}
+
+nsresult
+nsAudioStreamRemote::Write(const void* aBuf,
+ PRUint32 aCount,
+ PRBool aBlocking)
+{
+ nsCOMPtr<nsIRunnable> event = new AudioWriteEvent(this,
+ aBuf,
+ aCount,
+ mBytesPerSample);
+ NS_DispatchToMainThread(event);
+ return NS_OK;
+}
+
+PRUint32
+nsAudioStreamRemote::Available()
+{
+ return FAKE_BUFFER_SIZE;
+}
+
+void
+nsAudioStreamRemote::SetVolume(float aVolume)
+{
+ nsCOMPtr<nsIRunnable> event = new AudioSetVolumeEvent(this, aVolume);
+ NS_DispatchToMainThread(event);
+}
+
+void
+nsAudioStreamRemote::Drain()
+{
+ nsCOMPtr<nsIRunnable> event = new AudioDrainEvent(this);
+ NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
+}
+
+void
+nsAudioStreamRemote::Pause()
+{
+ mPaused = PR_TRUE;
+ nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(this, PR_TRUE);
+ NS_DispatchToMainThread(event);
+}
+
+void
+nsAudioStreamRemote::Resume()
+{
+ mPaused = PR_FALSE;
+ nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(this, PR_FALSE);
+ NS_DispatchToMainThread(event);
+}
+
+PRInt64 nsAudioStreamRemote::GetPosition()
+{
+ PRInt64 sampleOffset = GetSampleOffset();
+ if (sampleOffset >= 0) {
+ return ((MILLISECONDS_PER_SECOND * sampleOffset) / mRate / mChannels);
+ }
+ return 0;
+}
+
+PRInt64
+nsAudioStreamRemote::GetSampleOffset()
+{
+ if(!mAudioChild)
+ return 0;
+
+ PRInt64 offset = mAudioChild->GetLastKnownSampleOffset();
+ if (offset == -1)
+ return 0;
+
+ PRInt64 time = mAudioChild->GetLastKnownSampleOffsetTime();
+ PRInt64 result = offset + (mRate * mChannels * (PR_IntervalNow() - time) / MILLISECONDS_PER_SECOND);
+
+ return result;
+}
+
+PRBool
+nsAudioStreamRemote::IsPaused()
+{
+ return mPaused;
+}
+
+#endif // MOZ_IPC
--- a/content/media/nsAudioStream.h
+++ b/content/media/nsAudioStream.h
@@ -34,99 +34,86 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#if !defined(nsAudioStream_h_)
#define nsAudioStream_h_
#include "nscore.h"
-#include "prlog.h"
-#include "nsTArray.h"
+#include "nsISupportsImpl.h"
+#include "nsIThread.h"
-extern PRLogModuleInfo* gAudioStreamLog;
+class nsAudioStream : public nsISupports
+{
+public:
-class nsAudioStream
-{
- public:
enum SampleFormat
{
FORMAT_U8,
FORMAT_S16_LE,
FORMAT_FLOAT32
};
// Initialize Audio Library. Some Audio backends require initializing the
// library before using it.
static void InitLibrary();
// Shutdown Audio Library. Some Audio backends require shutting down the
// library after using it.
static void ShutdownLibrary();
- nsAudioStream();
- ~nsAudioStream();
+ // Thread, usually for MOZ_IPC handling, that is shared between audio streams.
+ // This may return null in the child process
+ static nsIThread *GetGlobalThread();
+
+ // AllocateStream will return either a local stream or a remoted stream
+ // depending on where you call it from. If MOZ_IPC is enabled, and you
+ // call this from a child process, you may recieve an implementation which
+ // forwards to a compositing process.
+ static nsAudioStream* AllocateStream();
// Initialize the audio stream. aNumChannels is the number of audio channels
// (1 for mono, 2 for stereo, etc) and aRate is the frequency of the sound
// samples (22050, 44100, etc).
- nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
+ virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) = 0;
// Closes the stream. All future use of the stream is an error.
- void Shutdown();
+ virtual void Shutdown() = 0;
// Write sound data to the audio hardware. aBuf is an array of samples in
// the format specified by mFormat of length aCount. aCount should be
// evenly divisible by the number of channels in this audio stream.
// When aBlocking is PR_TRUE, we'll block until the write has completed,
// otherwise we'll buffer any data we can't write immediately, and write
// it in a later call.
- nsresult Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking);
+ virtual nsresult Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking) = 0;
// Return the number of sound samples that can be written to the audio device
// without blocking.
- PRUint32 Available();
+ virtual PRUint32 Available() = 0;
// Set the current volume of the audio playback. This is a value from
// 0 (meaning muted) to 1 (meaning full volume).
- void SetVolume(float aVolume);
+ virtual void SetVolume(float aVolume) = 0;
// Block until buffered audio data has been consumed.
- void Drain();
+ virtual void Drain() = 0;
// Pause audio playback
- void Pause();
+ virtual void Pause() = 0;
// Resume audio playback
- void Resume();
+ virtual void Resume() = 0;
// Return the position in milliseconds of the sample being played by the
// audio hardware.
- PRInt64 GetPosition();
+ virtual PRInt64 GetPosition() = 0;
// Return the position, measured in samples played since the start, by
// the audio hardware.
- PRInt64 GetSampleOffset();
+ virtual PRInt64 GetSampleOffset() = 0;
// Returns PR_TRUE when the audio stream is paused.
- PRBool IsPaused() { return mPaused; }
-
- private:
- double mVolume;
- void* mAudioHandle;
- int mRate;
- int mChannels;
-
- SampleFormat mFormat;
+ virtual PRBool IsPaused() = 0;
+};
- // When a Write() request is made, and the number of samples
- // requested to be written exceeds the buffer size of the audio
- // backend, the remaining samples are stored in this variable. They
- // will be written on the next Write() request.
- nsTArray<short> mBufferOverflow;
-
- // PR_TRUE if this audio stream is paused.
- PRPackedBool mPaused;
-
- // PR_TRUE if this stream has encountered an error.
- PRPackedBool mInError;
-};
#endif
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -156,16 +156,22 @@ nsBuiltinDecoderStateMachine::nsBuiltinD
mEventManager(aDecoder)
{
MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
}
nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
{
MOZ_COUNT_DTOR(nsBuiltinDecoderStateMachine);
+
+ if (mAudioStream) {
+ MonitorAutoEnter mon(mDecoder->GetMonitor());
+ mAudioStream->Shutdown();
+ mAudioStream = nsnull;
+ }
}
PRBool nsBuiltinDecoderStateMachine::HasFutureAudio() const {
mDecoder->GetMonitor().AssertCurrentThreadIn();
NS_ASSERTION(HasAudio(), "Should only call HasFutureAudio() when we have audio");
// We've got audio ready to play if:
// 1. We've not completed playback of audio, and
// 2. we either have more than the threshold of decoded audio available, or
@@ -606,17 +612,17 @@ void nsBuiltinDecoderStateMachine::Start
MonitorAutoEnter audioMon(mAudioMonitor);
if (mAudioStream) {
// We have an audiostream, so it must have been paused the last time
// StopPlayback() was called.
mAudioStream->Resume();
} else {
// No audiostream, create one.
const nsVideoInfo& info = mReader->GetInfo();
- mAudioStream = new nsAudioStream();
+ mAudioStream = nsAudioStream::AllocateStream();
mAudioStream->Init(info.mAudioChannels,
info.mAudioRate,
MOZ_SOUND_DATA_FORMAT);
mAudioStream->SetVolume(mVolume);
}
}
mPlayStartTime = TimeStamp::Now();
mDecoder->GetMonitor().NotifyAll();
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -421,17 +421,17 @@ protected:
// Position to seek to in milliseconds when the seek state transition occurs.
// The decoder monitor lock must be obtained before reading or writing
// this value. Accessed on main and state machine thread.
PRInt64 mSeekTime;
// The audio stream resource. Used on the state machine, audio, and main
// threads. You must hold the mAudioMonitor, and must NOT hold the decoder
// monitor when using the audio stream!
- nsAutoPtr<nsAudioStream> mAudioStream;
+ nsRefPtr<nsAudioStream> mAudioStream;
// The reader, don't call its methods with the decoder monitor held.
// This is created in the play state machine's constructor, and destroyed
// in the play state machine's destructor.
nsAutoPtr<nsBuiltinDecoderReader> mReader;
// The time of the current frame in milliseconds. This is referenced from
// 0 which is the initial playback position. Set by the state machine
--- a/content/media/wave/nsWaveDecoder.cpp
+++ b/content/media/wave/nsWaveDecoder.cpp
@@ -290,17 +290,17 @@ private:
// the state machine. The stream is threadsafe, but is only used on the
// playback thread except for create, open, and cancel, which are called
// from the main thread.
nsMediaStream* mStream;
// Our audio stream. Created on demand when entering playback state. It
// is destroyed when seeking begins and will not be reinitialized until
// playback resumes, so it is possible for this to be null.
- nsAutoPtr<nsAudioStream> mAudioStream;
+ nsRefPtr<nsAudioStream> mAudioStream;
// Maximum time to spend waiting for data during buffering.
TimeDuration mBufferingWait;
// Machine time that buffering began, used with mBufferingWait to time out
// buffering.
TimeStamp mBufferingStart;
@@ -901,17 +901,17 @@ nsWaveStateMachine::ChangeState(State aS
#endif
mState = aState;
monitor.NotifyAll();
}
void
nsWaveStateMachine::OpenAudioStream()
{
- mAudioStream = new nsAudioStream();
+ mAudioStream = nsAudioStream::AllocateStream();
if (!mAudioStream) {
LOG(PR_LOG_ERROR, ("Could not create audio stream"));
} else {
NS_ABORT_IF_FALSE(mMetadataValid,
"Attempting to initialize audio stream with invalid metadata");
mAudioStream->Init(mChannels, mSampleRate, mSampleFormat);
mAudioStream->SetVolume(mInitialVolume);
}
new file mode 100644
--- /dev/null
+++ b/dom/ipc/AudioChild.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Audio IPC
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozilla/dom/AudioChild.h"
+
+namespace mozilla {
+namespace dom {
+
+AudioChild::AudioChild()
+ : mLastSampleOffset(-1),
+ mLastSampleOffsetTime(0)
+{
+ MOZ_COUNT_CTOR(AudioChild);
+}
+
+AudioChild::~AudioChild()
+{
+ MOZ_COUNT_DTOR(AudioChild);
+}
+
+bool
+AudioChild::RecvSampleOffsetUpdate(const PRInt64& offset,
+ const PRInt64& time)
+{
+ mLastSampleOffset = offset;
+ mLastSampleOffsetTime = time;
+ return true;
+}
+
+PRInt64
+AudioChild::GetLastKnownSampleOffset()
+{
+ return mLastSampleOffset;
+}
+
+PRInt64
+AudioChild::GetLastKnownSampleOffsetTime()
+{
+ return mLastSampleOffsetTime;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/AudioChild.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Audio IPC
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_dom_AudioChild_h
+#define mozilla_dom_AudioChild_h
+
+#include "mozilla/dom/PAudioChild.h"
+
+namespace mozilla {
+namespace dom {
+
+class AudioChild : public PAudioChild
+{
+ public:
+ AudioChild();
+ virtual ~AudioChild();
+ virtual bool RecvSampleOffsetUpdate(const PRInt64&, const PRInt64&);
+
+ PRInt64 GetLastKnownSampleOffset();
+ PRInt64 GetLastKnownSampleOffsetTime();
+ private:
+ PRInt64 mLastSampleOffset, mLastSampleOffsetTime;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/ipc/AudioParent.cpp
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Audio IPC
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozilla/dom/AudioParent.h"
+#include "nsThreadUtils.h"
+
+// C++ file contents
+namespace mozilla {
+namespace dom {
+
+class AudioWriteEvent : public nsRunnable
+{
+ public:
+ AudioWriteEvent(nsAudioStream* owner, nsCString data, PRUint32 count)
+ {
+ mOwner = owner;
+ mData = data;
+ mCount = count;
+ }
+
+ NS_IMETHOD Run()
+ {
+ mOwner->Write(mData.get(), mCount, true);
+ return NS_OK;
+ }
+
+ private:
+ nsRefPtr<nsAudioStream> mOwner;
+ nsCString mData;
+ PRUint32 mCount;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(AudioParent, nsITimerCallback)
+
+nsresult
+AudioParent::Notify(nsITimer* timer)
+{
+ if (!mStream) {
+ timer->Cancel();
+ return NS_ERROR_FAILURE;
+ }
+
+ PRInt64 offset = mStream->GetSampleOffset();
+ SendSampleOffsetUpdate(offset, PR_IntervalNow());
+ return NS_OK;
+}
+bool
+AudioParent::RecvWrite(
+ const nsCString& data,
+ const PRUint32& count)
+{
+ nsCOMPtr<nsIRunnable> event = new AudioWriteEvent(mStream, data, count);
+ nsCOMPtr<nsIThread> thread = nsAudioStream::GetGlobalThread();
+ thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
+ return true;
+}
+
+bool
+AudioParent::RecvSetVolume(const float& aVolume)
+{
+ if (mStream)
+ mStream->SetVolume(aVolume);
+ return true;
+}
+
+bool
+AudioParent::RecvDrain()
+{
+ if (mStream)
+ mStream->Drain();
+ return true;
+}
+
+bool
+AudioParent::RecvPause()
+{
+ if (mStream)
+ mStream->Pause();
+ return true;
+}
+
+bool
+AudioParent::RecvResume()
+{
+ if (mStream)
+ mStream->Resume();
+ return true;
+}
+
+bool
+AudioParent::Recv__delete__()
+{
+ if (mStream) {
+ mStream->Shutdown();
+ mStream = nsnull;
+ }
+
+ if (mTimer) {
+ mTimer->Cancel();
+ mTimer = nsnull;
+ }
+ return true;
+}
+
+AudioParent::AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat)
+{
+ mStream = nsAudioStream::AllocateStream();
+ if (mStream)
+ mStream->Init(aNumChannels,
+ aRate,
+ (nsAudioStream::SampleFormat) aFormat);
+ if (!mStream)
+ return;
+
+ mTimer = do_CreateInstance("@mozilla.org/timer;1");
+ mTimer->InitWithCallback(this, 1000, nsITimer::TYPE_REPEATING_SLACK);
+}
+
+AudioParent::~AudioParent()
+{
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/AudioParent.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Audio IPC
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_dom_AudioParent_h
+#define mozilla_dom_AudioParent_h
+
+#include "mozilla/dom/PAudioParent.h"
+#include "nsAudioStream.h"
+#include "nsITimer.h"
+
+namespace mozilla {
+namespace dom {
+class AudioParent : public PAudioParent, public nsITimerCallback
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITIMERCALLBACK
+
+ virtual bool
+ RecvWrite(
+ const nsCString& data,
+ const PRUint32& count);
+
+ virtual bool
+ RecvSetVolume(const float& aVolume);
+
+ virtual bool
+ RecvDrain();
+
+ virtual bool
+ RecvPause();
+
+ virtual bool
+ RecvResume();
+
+ virtual bool
+ Recv__delete__();
+
+ AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
+ virtual ~AudioParent();
+
+ nsRefPtr<nsAudioStream> mStream;
+ nsCOMPtr<nsITimer> mTimer;
+
+};
+} // namespace dom
+} // namespace mozilla
+
+#endif
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -42,23 +42,26 @@
#endif
#ifdef MOZ_WIDGET_QT
#include "nsQAppInstance.h"
#endif
#include "ContentChild.h"
#include "TabChild.h"
+#include "AudioChild.h"
#include "mozilla/ipc/TestShellChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/ipc/XPCShellEnvironment.h"
#include "mozilla/jsipc/PContextWrapperChild.h"
#include "mozilla/dom/ExternalHelperAppChild.h"
+#include "nsAudioStream.h"
+
#include "nsIObserverService.h"
#include "nsTObserverArray.h"
#include "nsIObserver.h"
#include "nsIPrefService.h"
#include "nsServiceManagerUtils.h"
#include "nsXULAppAPI.h"
#include "nsWeakReference.h"
#include "nsIScriptError.h"
@@ -282,16 +285,32 @@ ContentChild::DeallocPTestShell(PTestShe
bool
ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
{
actor->SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
return true;
}
+PAudioChild*
+ContentChild::AllocPAudio(const PRInt32& numChannels,
+ const PRInt32& rate,
+ const PRInt32& format)
+{
+ PAudioChild *child = new AudioChild();
+ return child;
+}
+
+bool
+ContentChild::DeallocPAudio(PAudioChild* doomed)
+{
+ delete doomed;
+ return true;
+}
+
PNeckoChild*
ContentChild::AllocPNecko()
{
return new NeckoChild();
}
bool
ContentChild::DeallocPNecko(PNeckoChild* necko)
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -78,16 +78,21 @@ public:
virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags);
virtual bool DeallocPBrowser(PBrowserChild*);
virtual PTestShellChild* AllocPTestShell();
virtual bool DeallocPTestShell(PTestShellChild*);
virtual bool RecvPTestShellConstructor(PTestShellChild*);
+ virtual PAudioChild* AllocPAudio(const PRInt32&,
+ const PRInt32&,
+ const PRInt32&);
+ virtual bool DeallocPAudio(PAudioChild*);
+
virtual PNeckoChild* AllocPNecko();
virtual bool DeallocPNecko(PNeckoChild*);
virtual PExternalHelperAppChild *AllocPExternalHelperApp(
const IPC::URI& uri,
const nsCString& aMimeContentType,
const nsCString& aContentDisposition,
const bool& aForceSave,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -61,16 +61,17 @@
#include "nsCExternalHandlerService.h"
#include "nsFrameMessageManager.h"
#include "nsIAlertsService.h"
#include "nsToolkitCompsCID.h"
#include "nsIDOMGeoGeolocation.h"
#include "nsIConsoleService.h"
#include "nsIScriptError.h"
#include "nsConsoleMessage.h"
+#include "AudioParent.h"
#ifdef MOZ_PERMISSIONS
#include "nsPermissionManager.h"
#endif
#include "mozilla/dom/ExternalHelperAppParent.h"
#include "nsAccelerometer.h"
@@ -356,16 +357,34 @@ ContentParent::AllocPTestShell()
}
bool
ContentParent::DeallocPTestShell(PTestShellParent* shell)
{
delete shell;
return true;
}
+
+PAudioParent*
+ContentParent::AllocPAudio(const PRInt32& numChannels,
+ const PRInt32& rate,
+ const PRInt32& format)
+{
+ AudioParent *parent = new AudioParent(numChannels, rate, format);
+ parent->AddRef();
+ return parent;
+}
+
+bool
+ContentParent::DeallocPAudio(PAudioParent* doomed)
+{
+ AudioParent *parent = static_cast<AudioParent*>(doomed);
+ NS_RELEASE(parent);
+ return true;
+}
PNeckoParent*
ContentParent::AllocPNecko()
{
return new NeckoParent();
}
bool
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -112,16 +112,21 @@ private:
virtual ~ContentParent();
virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags);
virtual bool DeallocPBrowser(PBrowserParent* frame);
virtual PTestShellParent* AllocPTestShell();
virtual bool DeallocPTestShell(PTestShellParent* shell);
+ virtual PAudioParent* AllocPAudio(const PRInt32&,
+ const PRInt32&,
+ const PRInt32&);
+ virtual bool DeallocPAudio(PAudioParent*);
+
virtual PNeckoParent* AllocPNecko();
virtual bool DeallocPNecko(PNeckoParent* necko);
virtual PExternalHelperAppParent* AllocPExternalHelperApp(
const IPC::URI& uri,
const nsCString& aMimeContentType,
const nsCString& aContentDisposition,
const bool& aForceSave,
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -47,24 +47,28 @@ LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
EXPORTS = TabMessageUtils.h PCOMContentPermissionRequestChild.h
EXPORTS_NAMESPACES = mozilla/dom
EXPORTS_mozilla/dom = \
+ AudioChild.h \
+ AudioParent.h \
ContentChild.h \
ContentParent.h \
ContentProcess.h \
TabParent.h \
TabChild.h \
$(NULL)
CPPSRCS = \
+ AudioChild.cpp \
+ AudioParent.cpp \
ContentProcess.cpp \
ContentParent.cpp \
ContentChild.cpp \
TabParent.cpp \
TabChild.cpp \
TabMessageUtils.cpp \
$(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/ipc/PAudio.ipdl
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Audio IPC
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+include protocol PContent;
+
+namespace mozilla {
+namespace dom {
+
+sync protocol PAudio
+{
+ manager PContent;
+
+parent:
+
+ __delete__();
+
+ Write(nsCString data, PRUint32 count);
+
+ SetVolume(float aVolume);
+
+ sync Drain();
+
+ Pause();
+ Resume();
+
+ child:
+
+ SampleOffsetUpdate(PRInt64 offset, PRInt64 time);
+
+
+};
+
+} // namespace dom
+} // namespace mozilla
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -31,16 +31,17 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+include protocol PAudio;
include protocol PBrowser;
include protocol PTestShell;
include protocol PNecko;
include protocol PExternalHelperApp;
include "mozilla/chrome/RegistryMessageUtils.h";
include "mozilla/net/NeckoMessageUtils.h";
@@ -56,16 +57,17 @@ using OverrideMapping;
using IPC::URI;
using IPC::Permission;
namespace mozilla {
namespace dom {
rpc protocol PContent
{
+ manages PAudio;
manages PBrowser;
manages PTestShell;
manages PNecko;
manages PExternalHelperApp;
child:
PBrowser(PRUint32 chromeFlags);
@@ -87,16 +89,18 @@ child:
// nsIPermissionManager messages
AddPermission(Permission permission);
AccelerationChanged(double x, double y, double z);
parent:
PNecko();
+ PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
+
// Services remoting
async StartVisitedQuery(URI uri);
async VisitURI(URI uri, URI referrer, PRUint32 flags);
async SetURITitle(URI uri, nsString title);
// filepicker remoting
sync ShowFilePicker(PRInt16 mode, PRInt16 selectedType,
--- a/dom/ipc/ipdl.mk
+++ b/dom/ipc/ipdl.mk
@@ -30,14 +30,15 @@
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
IPDLSRCS = \
+ PAudio.ipdl \
PBrowser.ipdl \
PContent.ipdl \
PContentDialog.ipdl \
PDocumentRenderer.ipdl \
PContentPermissionRequest.ipdl \
$(NULL)