2011-01-04 23:30:21 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set sw=2 ts=8 et tw=80 : */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2010-11-17 04:14:19 +00:00
|
|
|
|
|
|
|
#include "mozilla/dom/AudioParent.h"
|
2011-03-31 19:38:30 +00:00
|
|
|
#include "mozilla/unused.h"
|
2010-11-17 04:14:19 +00:00
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
|
|
|
|
// C++ file contents
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2012-07-02 04:59:43 +00:00
|
|
|
class AudioWriteDoneEvent : public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AudioWriteDoneEvent(AudioParent* owner)
|
|
|
|
{
|
|
|
|
mOwner = owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
|
|
|
mOwner->SendWriteDone();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<AudioParent> mOwner;
|
|
|
|
};
|
|
|
|
|
2010-11-17 04:14:19 +00:00
|
|
|
class AudioWriteEvent : public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
2012-08-22 15:56:38 +00:00
|
|
|
AudioWriteEvent(AudioParent* parent, nsAudioStream* owner, nsCString data, uint32_t frames)
|
2010-11-17 04:14:19 +00:00
|
|
|
{
|
2012-07-02 04:59:43 +00:00
|
|
|
mParent = parent;
|
2010-11-17 04:14:19 +00:00
|
|
|
mOwner = owner;
|
|
|
|
mData = data;
|
2011-09-27 03:31:18 +00:00
|
|
|
mFrames = frames;
|
2010-11-17 04:14:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
2011-09-27 03:31:18 +00:00
|
|
|
mOwner->Write(mData.get(), mFrames);
|
2012-07-02 04:59:43 +00:00
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioWriteDoneEvent(mParent);
|
|
|
|
NS_DispatchToMainThread(event);
|
2010-11-17 04:14:19 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2012-07-02 04:59:43 +00:00
|
|
|
nsRefPtr<AudioParent> mParent;
|
2010-11-17 04:14:19 +00:00
|
|
|
nsRefPtr<nsAudioStream> mOwner;
|
|
|
|
nsCString mData;
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t mFrames;
|
2010-11-17 04:14:19 +00:00
|
|
|
};
|
|
|
|
|
2010-11-26 04:13:54 +00:00
|
|
|
class AudioPauseEvent : public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
2011-09-29 06:19:26 +00:00
|
|
|
AudioPauseEvent(nsAudioStream* owner, bool aPause)
|
2010-11-26 04:13:54 +00:00
|
|
|
{
|
|
|
|
mOwner = owner;
|
|
|
|
mPause = aPause;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
|
|
|
if (mPause)
|
|
|
|
mOwner->Pause();
|
|
|
|
else
|
|
|
|
mOwner->Resume();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<nsAudioStream> mOwner;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool mPause;
|
2010-11-26 04:13:54 +00:00
|
|
|
};
|
|
|
|
|
2011-01-04 23:30:21 +00:00
|
|
|
class AudioStreamShutdownEvent : public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AudioStreamShutdownEvent(nsAudioStream* owner)
|
|
|
|
{
|
|
|
|
mOwner = owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
|
|
|
mOwner->Shutdown();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<nsAudioStream> mOwner;
|
|
|
|
};
|
|
|
|
|
2011-05-15 10:53:55 +00:00
|
|
|
|
2011-09-27 03:31:18 +00:00
|
|
|
class AudioMinWriteSizeDone : public nsRunnable
|
2011-05-15 10:53:55 +00:00
|
|
|
{
|
|
|
|
public:
|
2012-08-22 15:56:38 +00:00
|
|
|
AudioMinWriteSizeDone(AudioParent* owner, int32_t minFrames)
|
2011-05-15 10:53:55 +00:00
|
|
|
{
|
|
|
|
mOwner = owner;
|
2011-09-27 03:31:18 +00:00
|
|
|
mMinFrames = minFrames;
|
2011-05-15 10:53:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
2011-09-27 03:31:18 +00:00
|
|
|
mOwner->SendMinWriteSizeDone(mMinFrames);
|
2011-05-15 10:53:55 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<AudioParent> mOwner;
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t mMinFrames;
|
2011-05-15 10:53:55 +00:00
|
|
|
};
|
|
|
|
|
2011-09-27 03:31:18 +00:00
|
|
|
class AudioMinWriteSizeEvent : public nsRunnable
|
2011-05-15 10:53:55 +00:00
|
|
|
{
|
|
|
|
public:
|
2011-09-27 03:31:18 +00:00
|
|
|
AudioMinWriteSizeEvent(AudioParent* parent, nsAudioStream* owner)
|
2011-05-15 10:53:55 +00:00
|
|
|
{
|
|
|
|
mParent = parent;
|
|
|
|
mOwner = owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t minFrames = mOwner->GetMinWriteSize();
|
2011-09-27 03:31:18 +00:00
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioMinWriteSizeDone(mParent, minFrames);
|
2011-05-15 10:53:55 +00:00
|
|
|
NS_DispatchToMainThread(event);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<nsAudioStream> mOwner;
|
|
|
|
nsRefPtr<AudioParent> mParent;
|
|
|
|
};
|
|
|
|
|
2010-11-30 05:37:32 +00:00
|
|
|
class AudioDrainDoneEvent : public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AudioDrainDoneEvent(AudioParent* owner)
|
|
|
|
{
|
|
|
|
mOwner = owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
|
|
|
mOwner->SendDrainDone();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<AudioParent> mOwner;
|
|
|
|
};
|
|
|
|
|
|
|
|
class AudioDrainEvent : public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AudioDrainEvent(AudioParent* parent, nsAudioStream* owner)
|
|
|
|
{
|
|
|
|
mParent = parent;
|
|
|
|
mOwner = owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
|
|
|
mOwner->Drain();
|
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioDrainDoneEvent(mParent);
|
|
|
|
NS_DispatchToMainThread(event);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<nsAudioStream> mOwner;
|
|
|
|
nsRefPtr<AudioParent> mParent;
|
|
|
|
};
|
|
|
|
|
2010-11-17 04:14:19 +00:00
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS1(AudioParent, nsITimerCallback)
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
AudioParent::Notify(nsITimer* timer)
|
|
|
|
{
|
2011-01-04 23:30:21 +00:00
|
|
|
if (!mIPCOpen) {
|
2010-11-17 04:14:19 +00:00
|
|
|
timer->Cancel();
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2011-01-04 23:30:21 +00:00
|
|
|
NS_ASSERTION(mStream, "AudioStream not initialized.");
|
2012-08-22 15:56:38 +00:00
|
|
|
int64_t position = mStream->GetPositionInFrames();
|
2011-09-27 03:31:18 +00:00
|
|
|
unused << SendPositionInFramesUpdate(position, PR_IntervalNow());
|
2010-11-17 04:14:19 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-01-04 23:30:21 +00:00
|
|
|
|
2010-11-17 04:14:19 +00:00
|
|
|
bool
|
2012-08-22 15:56:38 +00:00
|
|
|
AudioParent::RecvWrite(const nsCString& data, const uint32_t& frames)
|
2010-11-17 04:14:19 +00:00
|
|
|
{
|
2011-01-04 23:30:21 +00:00
|
|
|
if (!mStream)
|
|
|
|
return false;
|
2012-07-02 04:59:43 +00:00
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioWriteEvent(this, mStream, data, frames);
|
2010-11-30 05:37:32 +00:00
|
|
|
nsCOMPtr<nsIThread> thread = mStream->GetThread();
|
2010-11-17 04:14:19 +00:00
|
|
|
thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
|
|
|
return true;
|
|
|
|
}
|
2010-11-30 05:37:32 +00:00
|
|
|
|
2010-11-17 04:14:19 +00:00
|
|
|
bool
|
|
|
|
AudioParent::RecvSetVolume(const float& aVolume)
|
|
|
|
{
|
2011-01-04 23:30:21 +00:00
|
|
|
if (!mStream)
|
|
|
|
return false;
|
|
|
|
mStream->SetVolume(aVolume);
|
2010-11-17 04:14:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-05-15 10:53:55 +00:00
|
|
|
bool
|
2011-09-27 03:31:18 +00:00
|
|
|
AudioParent::RecvMinWriteSize()
|
2011-05-15 10:53:55 +00:00
|
|
|
{
|
|
|
|
if (!mStream)
|
|
|
|
return false;
|
2011-09-27 03:31:18 +00:00
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioMinWriteSizeEvent(this, mStream);
|
2011-05-15 10:53:55 +00:00
|
|
|
nsCOMPtr<nsIThread> thread = mStream->GetThread();
|
|
|
|
thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-11-17 04:14:19 +00:00
|
|
|
bool
|
|
|
|
AudioParent::RecvDrain()
|
|
|
|
{
|
2011-01-04 23:30:21 +00:00
|
|
|
if (!mStream)
|
|
|
|
return false;
|
2010-11-30 05:37:32 +00:00
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioDrainEvent(this, mStream);
|
|
|
|
nsCOMPtr<nsIThread> thread = mStream->GetThread();
|
|
|
|
thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
2010-11-17 04:14:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
AudioParent::RecvPause()
|
|
|
|
{
|
2011-01-04 23:30:21 +00:00
|
|
|
if (!mStream)
|
|
|
|
return false;
|
2011-10-17 14:59:28 +00:00
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(mStream, true);
|
2010-11-30 05:37:32 +00:00
|
|
|
nsCOMPtr<nsIThread> thread = mStream->GetThread();
|
2010-11-26 04:13:54 +00:00
|
|
|
thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
2010-11-17 04:14:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
AudioParent::RecvResume()
|
|
|
|
{
|
2011-01-04 23:30:21 +00:00
|
|
|
if (!mStream)
|
|
|
|
return false;
|
2011-10-17 14:59:28 +00:00
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(mStream, false);
|
2010-11-30 05:37:32 +00:00
|
|
|
nsCOMPtr<nsIThread> thread = mStream->GetThread();
|
2010-11-26 04:13:54 +00:00
|
|
|
thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
2010-11-17 04:14:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2011-01-29 05:40:23 +00:00
|
|
|
AudioParent::RecvShutdown()
|
2010-11-17 04:14:19 +00:00
|
|
|
{
|
2011-01-29 05:40:23 +00:00
|
|
|
Shutdown();
|
2011-03-31 19:38:30 +00:00
|
|
|
unused << PAudioParent::Send__delete__(this);
|
2010-11-17 04:14:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-05-15 10:53:55 +00:00
|
|
|
bool
|
2012-08-22 15:56:38 +00:00
|
|
|
AudioParent::SendMinWriteSizeDone(int32_t minFrames)
|
2011-05-15 10:53:55 +00:00
|
|
|
{
|
|
|
|
if (mIPCOpen)
|
2011-09-27 03:31:18 +00:00
|
|
|
return PAudioParent::SendMinWriteSizeDone(minFrames);
|
2011-05-15 10:53:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-02-15 21:58:52 +00:00
|
|
|
bool
|
|
|
|
AudioParent::SendDrainDone()
|
|
|
|
{
|
|
|
|
if (mIPCOpen)
|
|
|
|
return PAudioParent::SendDrainDone();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-07-02 04:59:43 +00:00
|
|
|
bool
|
|
|
|
AudioParent::SendWriteDone()
|
|
|
|
{
|
|
|
|
if (mIPCOpen)
|
|
|
|
return PAudioParent::SendWriteDone();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
AudioParent::AudioParent(int32_t aNumChannels, int32_t aRate, int32_t aFormat)
|
2011-10-17 14:59:28 +00:00
|
|
|
: mIPCOpen(true)
|
2010-11-17 04:14:19 +00:00
|
|
|
{
|
|
|
|
mStream = nsAudioStream::AllocateStream();
|
2011-01-04 23:30:21 +00:00
|
|
|
NS_ASSERTION(mStream, "AudioStream allocation failed.");
|
2012-08-17 01:10:36 +00:00
|
|
|
if (NS_FAILED(mStream->Init(aNumChannels, aRate))) {
|
2011-01-04 23:30:21 +00:00
|
|
|
NS_WARNING("AudioStream initialization failed.");
|
2012-07-30 14:20:58 +00:00
|
|
|
mStream = nullptr;
|
2011-01-04 23:30:21 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-11-17 04:14:19 +00:00
|
|
|
|
|
|
|
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
mTimer->InitWithCallback(this, 1000, nsITimer::TYPE_REPEATING_SLACK);
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioParent::~AudioParent()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-11-26 04:13:54 +00:00
|
|
|
void
|
|
|
|
AudioParent::ActorDestroy(ActorDestroyReason aWhy)
|
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
mIPCOpen = false;
|
2011-01-29 05:40:23 +00:00
|
|
|
|
|
|
|
Shutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AudioParent::Shutdown()
|
|
|
|
{
|
|
|
|
if (mTimer) {
|
|
|
|
mTimer->Cancel();
|
2012-07-30 14:20:58 +00:00
|
|
|
mTimer = nullptr;
|
2011-01-29 05:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mStream) {
|
|
|
|
nsCOMPtr<nsIRunnable> event = new AudioStreamShutdownEvent(mStream);
|
|
|
|
nsCOMPtr<nsIThread> thread = mStream->GetThread();
|
|
|
|
thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
2012-07-30 14:20:58 +00:00
|
|
|
mStream = nullptr;
|
2011-01-29 05:40:23 +00:00
|
|
|
}
|
2010-11-26 04:13:54 +00:00
|
|
|
}
|
|
|
|
|
2010-11-17 04:14:19 +00:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|