void
AudioDestinationNode::SetIsOnlyNodeForContext(bool aIsOnlyNode)
{
  if (!mStartedBlockingDueToBeingOnlyNode.IsNull() == aIsOnlyNode) {
    // Nothing changed.
    return;
  }

  if (!mStream) {
    // DestroyMediaStream has been called, presumably during CC Unlink().
    return;
  }

  if (mIsOffline) {
    // Don't block the destination stream for offline AudioContexts, since
    // we expect the zero data produced when there are no other nodes to
    // show up in its result buffer. Also, we would get confused by adding
    // ExtraCurrentTime before StartRendering has even been called.
    return;
  }

  if (aIsOnlyNode) {
    mStream->Suspend();
    mStartedBlockingDueToBeingOnlyNode = TimeStamp::Now();
    // Don't do an update of mExtraCurrentTimeSinceLastStartedBlocking until the next stable state.
    mExtraCurrentTimeUpdatedSinceLastStableState = true;
    ScheduleStableStateNotification();
  } else {
    // Force update of mExtraCurrentTimeSinceLastStartedBlocking if necessary
    ExtraCurrentTime();
    mStream->AdvanceAndResume(mExtraCurrentTimeSinceLastStartedBlocking);
    mExtraCurrentTimeSinceLastStartedBlocking = 0;
    mStartedBlockingDueToBeingOnlyNode = TimeStamp();
  }
}
double
AudioDestinationNode::ExtraCurrentTime()
{
    if (!mStartedBlockingDueToBeingOnlyNode.IsNull() &&
            !mExtraCurrentTimeUpdatedSinceLastStableState) {
        mExtraCurrentTimeUpdatedSinceLastStableState = true;
        mExtraCurrentTimeSinceLastStartedBlocking =
            (TimeStamp::Now() - mStartedBlockingDueToBeingOnlyNode).ToSeconds();
        ScheduleStableStateNotification();
    }
    return mExtraCurrentTime + mExtraCurrentTimeSinceLastStartedBlocking;
}
StreamTime
AudioDestinationNode::ExtraCurrentTime()
{
  if (!mStartedBlockingDueToBeingOnlyNode.IsNull() &&
      !mExtraCurrentTimeUpdatedSinceLastStableState) {
    mExtraCurrentTimeUpdatedSinceLastStableState = true;
    // Round to nearest processing block.
    double seconds =
      (TimeStamp::Now() - mStartedBlockingDueToBeingOnlyNode).ToSeconds();
    mExtraCurrentTimeSinceLastStartedBlocking = WEBAUDIO_BLOCK_SIZE *
      StreamTime(seconds * Context()->SampleRate() / WEBAUDIO_BLOCK_SIZE + 0.5);
    ScheduleStableStateNotification();
  }
  return mExtraCurrentTimeSinceLastStartedBlocking;
}