<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/audio/audio_output_controller.h"

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/message_loop.h"
#include "base/threading/platform_thread.h"
#include "base/time.h"
#include "build/build_config.h"
#include "media/audio/audio_util.h"
#include "media/audio/shared_memory_util.h"

using base::Time;
using base::TimeDelta;

namespace media {

// Polling-related constants.
const int AudioOutputController::kPollNumAttempts = 3;
const int AudioOutputController::kPollPauseInMilliseconds = 3;

AudioOutputController::AudioOutputController(AudioManager* audio_manager,
                                             EventHandler* handler,
                                             const AudioParameters& params,
                                             SyncReader* sync_reader)
    : audio_manager_(audio_manager),
      params_(params),
      handler_(handler),
      stream_(NULL),
      diverting_to_stream_(NULL),
      volume_(1.0),
      state_(kEmpty),
      num_allowed_io_(0),
      sync_reader_(sync_reader),
      message_loop_(audio_manager->GetMessageLoop()),
      number_polling_attempts_left_(0),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)) {
  DCHECK(audio_manager);
  DCHECK(handler_);
  DCHECK(sync_reader_);
  DCHECK(message_loop_);
}

AudioOutputController::~AudioOutputController() {
  DCHECK_EQ(kClosed, state_);
}

// static
scoped_refptr<AudioOutputController> AudioOutputController::Create(
    AudioManager* audio_manager,
    EventHandler* event_handler,
    const AudioParameters& params,
    SyncReader* sync_reader) {
  DCHECK(audio_manager);
  DCHECK(sync_reader);

  if (!params.IsValid() || !audio_manager)
    return NULL;

  scoped_refptr<AudioOutputController> controller(new AudioOutputController(
      audio_manager, event_handler, params, sync_reader));
  controller->message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoCreate, controller, false));
  return controller;
}

void AudioOutputController::Play() {
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoPlay, this));
}

void AudioOutputController::Pause() {
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoPause, this));
}

void AudioOutputController::Flush() {
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoFlush, this));
}

void AudioOutputController::Close(const base::Closure& closed_task) {
  DCHECK(!closed_task.is_null());
  message_loop_->PostTaskAndReply(FROM_HERE, base::Bind(
      &AudioOutputController::DoClose, this), closed_task);
}

void AudioOutputController::SetVolume(double volume) {
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoSetVolume, this, volume));
}

void AudioOutputController::DoCreate(bool is_for_device_change) {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // Close() can be called before DoCreate() is executed.
  if (state_ == kClosed)
    return;

  DoStopCloseAndClearStream();  // Calls RemoveOutputDeviceChangeListener().
  DCHECK_EQ(kEmpty, state_);

  stream_ = diverting_to_stream_ ? diverting_to_stream_ :
      audio_manager_->MakeAudioOutputStreamProxy(params_);
  if (!stream_) {
    state_ = kError;

    // TODO(hclam): Define error types.
    handler_->OnError(this, 0);
    return;
  }

  if (!stream_->Open()) {
    DoStopCloseAndClearStream();
    state_ = kError;

    // TODO(hclam): Define error types.
    handler_->OnError(this, 0);
    return;
  }

  // Everything started okay, so re-register for state change callbacks if
  // stream_ was created via AudioManager.
  if (stream_ != diverting_to_stream_)
    audio_manager_->AddOutputDeviceChangeListener(this);

  // We have successfully opened the stream. Set the initial volume.
  stream_->SetVolume(volume_);

  // Finally set the state to kCreated.
  state_ = kCreated;

  // And then report we have been created if we haven't done so already.
  if (!is_for_device_change)
    handler_->OnCreated(this);
}

void AudioOutputController::DoPlay() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // We can start from created or paused state.
  if (state_ != kCreated && state_ != kPaused)
    return;

  state_ = kStarting;

  // Ask for first packet.
  sync_reader_->UpdatePendingBytes(0);

  // Cannot start stream immediately, should give renderer some time
  // to deliver data.
  // TODO(vrk): The polling here and in WaitTillDataReady() is pretty clunky.
  // Refine the API such that polling is no longer needed. (crbug.com/112196)
  number_polling_attempts_left_ = kPollNumAttempts;
  DCHECK(!weak_this_.HasWeakPtrs());
  message_loop_->PostDelayedTask(
      FROM_HERE,
      base::Bind(&AudioOutputController::PollAndStartIfDataReady,
      weak_this_.GetWeakPtr()),
      TimeDelta::FromMilliseconds(kPollPauseInMilliseconds));
}

void AudioOutputController::PollAndStartIfDataReady() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  DCHECK_EQ(kStarting, state_);

  // If we are ready to start the stream, start it.
  if (--number_polling_attempts_left_ == 0 ||
      sync_reader_->DataReady()) {
    StartStream();
  } else {
    message_loop_->PostDelayedTask(
        FROM_HERE,
        base::Bind(&AudioOutputController::PollAndStartIfDataReady,
        weak_this_.GetWeakPtr()),
        TimeDelta::FromMilliseconds(kPollPauseInMilliseconds));
  }
}

void AudioOutputController::StartStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  state_ = kPlaying;

  // We start the AudioOutputStream lazily.
  AllowEntryToOnMoreIOData();
  stream_->Start(this);

  // Tell the event handler that we are now playing.
  handler_->OnPlaying(this);
}

void AudioOutputController::StopStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kStarting) {
    // Cancel in-progress polling start.
    weak_this_.InvalidateWeakPtrs();
    state_ = kPaused;
  } else if (state_ == kPlaying) {
    stream_->Stop();
    DisallowEntryToOnMoreIOData();
    state_ = kPaused;
  }
}

void AudioOutputController::DoPause() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  StopStream();

  if (state_ != kPaused)
    return;

  // Send a special pause mark to the low-latency audio thread.
  sync_reader_->UpdatePendingBytes(kPauseMark);

  handler_->OnPaused(this);
}

void AudioOutputController::DoFlush() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // TODO(hclam): Actually flush the audio device.
}

void AudioOutputController::DoClose() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ != kClosed) {
    DoStopCloseAndClearStream();
    sync_reader_->Close();
    state_ = kClosed;
  }
}

void AudioOutputController::DoSetVolume(double volume) {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // Saves the volume to a member first. We may not be able to set the volume
  // right away but when the stream is created we'll set the volume.
  volume_ = volume;

  switch (state_) {
    case kCreated:
    case kStarting:
    case kPlaying:
    case kPaused:
      stream_->SetVolume(volume_);
      break;
    default:
      return;
  }
}

void AudioOutputController::DoReportError(int code) {
  DCHECK(message_loop_->BelongsToCurrentThread());
  if (state_ != kClosed)
    handler_->OnError(this, code);
}

int AudioOutputController::OnMoreData(AudioBus* dest,
                                      AudioBuffersState buffers_state) {
  return OnMoreIOData(NULL, dest, buffers_state);
}

int AudioOutputController::OnMoreIOData(AudioBus* source,
                                        AudioBus* dest,
                                        AudioBuffersState buffers_state) {
  DisallowEntryToOnMoreIOData();
  TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData");

  const int frames = sync_reader_->Read(source, dest);
  DCHECK_LE(0, frames);
  sync_reader_->UpdatePendingBytes(
      buffers_state.total_bytes() + frames * params_.GetBytesPerFrame());

  AllowEntryToOnMoreIOData();
  return frames;
}

void AudioOutputController::WaitTillDataReady() {
  base::Time start = base::Time::Now();
  // Wait for up to 1.5 seconds for DataReady().  1.5 seconds was chosen because
  // it's larger than the playback time of the WaveOut buffer size using the
  // minimum supported sample rate: 4096 / 3000 = ~1.4 seconds.  Even a client
  // expecting real time playout should be able to fill in this time.
  const base::TimeDelta max_wait = base::TimeDelta::FromMilliseconds(1500);
  while (!sync_reader_->DataReady() &&
         ((base::Time::Now() - start) < max_wait)) {
    base::PlatformThread::YieldCurrentThread();
  }
}

void AudioOutputController::OnError(AudioOutputStream* stream, int code) {
  // Handle error on the audio controller thread.
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoReportError, this, code));
}

void AudioOutputController::DoStopCloseAndClearStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // Allow calling unconditionally and bail if we don't have a stream_ to close.
  if (stream_) {
    // De-register from state change callbacks if stream_ was created via
    // AudioManager.
    if (stream_ != diverting_to_stream_)
      audio_manager_->RemoveOutputDeviceChangeListener(this);

    StopStream();
    stream_->Close();
    if (stream_ == diverting_to_stream_)
      diverting_to_stream_ = NULL;
    stream_ = NULL;
  }

  state_ = kEmpty;
}

void AudioOutputController::OnDeviceChange() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // TODO(dalecurtis): Notify the renderer side that a device change has
  // occurred.  Currently querying the hardware information here will lead to
  // crashes on OSX.  See http://crbug.com/158170.

  // Recreate the stream (DoCreate() will first shut down an existing stream).
  // Exit if we ran into an error.
  const State original_state = state_;
  DoCreate(true);
  if (!stream_ || state_ == kError)
    return;

  // Get us back to the original state or an equivalent state.
  switch (original_state) {
    case kStarting:
    case kPlaying:
      DoPlay();
      return;
    case kCreated:
    case kPaused:
      // From the outside these two states are equivalent.
      return;
    default:
      NOTREACHED() << "Invalid original state.";
  }
}

const AudioParameters& AudioOutputController::GetAudioParameters() {
  return params_;
}

void AudioOutputController::StartDiverting(AudioOutputStream* to_stream) {
  message_loop_->PostTask(
      FROM_HERE,
      base::Bind(&AudioOutputController::DoStartDiverting, this, to_stream));
}

void AudioOutputController::StopDiverting() {
  message_loop_->PostTask(
      FROM_HERE, base::Bind(&AudioOutputController::DoStopDiverting, this));
}

void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kClosed)
    return;

  DCHECK(!diverting_to_stream_);
  diverting_to_stream_ = to_stream;
  // Note: OnDeviceChange() will engage the "re-create" process, which will
  // detect and use the alternate AudioOutputStream rather than create a new one
  // via AudioManager.
  OnDeviceChange();
}

void AudioOutputController::DoStopDiverting() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kClosed)
    return;

  // Note: OnDeviceChange() will cause the existing stream (the consumer of the
  // diverted audio data) to be closed, and diverting_to_stream_ will be set
  // back to NULL.
  OnDeviceChange();
  DCHECK(!diverting_to_stream_);
}

void AudioOutputController::AllowEntryToOnMoreIOData() {
  DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_));
  base::AtomicRefCountInc(&num_allowed_io_);
}

void AudioOutputController::DisallowEntryToOnMoreIOData() {
  const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_);
  DCHECK(is_zero);
}

}  // namespace media
<commit_msg>Wait for the renderer even on WASAPI.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/audio/audio_output_controller.h"

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/message_loop.h"
#include "base/threading/platform_thread.h"
#include "base/time.h"
#include "build/build_config.h"
#include "media/audio/audio_util.h"
#include "media/audio/shared_memory_util.h"

using base::Time;
using base::TimeDelta;

namespace media {

// Polling-related constants.
const int AudioOutputController::kPollNumAttempts = 3;
const int AudioOutputController::kPollPauseInMilliseconds = 3;

AudioOutputController::AudioOutputController(AudioManager* audio_manager,
                                             EventHandler* handler,
                                             const AudioParameters& params,
                                             SyncReader* sync_reader)
    : audio_manager_(audio_manager),
      params_(params),
      handler_(handler),
      stream_(NULL),
      diverting_to_stream_(NULL),
      volume_(1.0),
      state_(kEmpty),
      num_allowed_io_(0),
      sync_reader_(sync_reader),
      message_loop_(audio_manager->GetMessageLoop()),
      number_polling_attempts_left_(0),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)) {
  DCHECK(audio_manager);
  DCHECK(handler_);
  DCHECK(sync_reader_);
  DCHECK(message_loop_);
}

AudioOutputController::~AudioOutputController() {
  DCHECK_EQ(kClosed, state_);
}

// static
scoped_refptr<AudioOutputController> AudioOutputController::Create(
    AudioManager* audio_manager,
    EventHandler* event_handler,
    const AudioParameters& params,
    SyncReader* sync_reader) {
  DCHECK(audio_manager);
  DCHECK(sync_reader);

  if (!params.IsValid() || !audio_manager)
    return NULL;

  scoped_refptr<AudioOutputController> controller(new AudioOutputController(
      audio_manager, event_handler, params, sync_reader));
  controller->message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoCreate, controller, false));
  return controller;
}

void AudioOutputController::Play() {
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoPlay, this));
}

void AudioOutputController::Pause() {
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoPause, this));
}

void AudioOutputController::Flush() {
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoFlush, this));
}

void AudioOutputController::Close(const base::Closure& closed_task) {
  DCHECK(!closed_task.is_null());
  message_loop_->PostTaskAndReply(FROM_HERE, base::Bind(
      &AudioOutputController::DoClose, this), closed_task);
}

void AudioOutputController::SetVolume(double volume) {
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoSetVolume, this, volume));
}

void AudioOutputController::DoCreate(bool is_for_device_change) {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // Close() can be called before DoCreate() is executed.
  if (state_ == kClosed)
    return;

  DoStopCloseAndClearStream();  // Calls RemoveOutputDeviceChangeListener().
  DCHECK_EQ(kEmpty, state_);

  stream_ = diverting_to_stream_ ? diverting_to_stream_ :
      audio_manager_->MakeAudioOutputStreamProxy(params_);
  if (!stream_) {
    state_ = kError;

    // TODO(hclam): Define error types.
    handler_->OnError(this, 0);
    return;
  }

  if (!stream_->Open()) {
    DoStopCloseAndClearStream();
    state_ = kError;

    // TODO(hclam): Define error types.
    handler_->OnError(this, 0);
    return;
  }

  // Everything started okay, so re-register for state change callbacks if
  // stream_ was created via AudioManager.
  if (stream_ != diverting_to_stream_)
    audio_manager_->AddOutputDeviceChangeListener(this);

  // We have successfully opened the stream. Set the initial volume.
  stream_->SetVolume(volume_);

  // Finally set the state to kCreated.
  state_ = kCreated;

  // And then report we have been created if we haven't done so already.
  if (!is_for_device_change)
    handler_->OnCreated(this);
}

void AudioOutputController::DoPlay() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // We can start from created or paused state.
  if (state_ != kCreated && state_ != kPaused)
    return;

  state_ = kStarting;

  // Ask for first packet.
  sync_reader_->UpdatePendingBytes(0);

  // Cannot start stream immediately, should give renderer some time
  // to deliver data.
  // TODO(vrk): The polling here and in WaitTillDataReady() is pretty clunky.
  // Refine the API such that polling is no longer needed. (crbug.com/112196)
  number_polling_attempts_left_ = kPollNumAttempts;
  DCHECK(!weak_this_.HasWeakPtrs());
  message_loop_->PostDelayedTask(
      FROM_HERE,
      base::Bind(&AudioOutputController::PollAndStartIfDataReady,
      weak_this_.GetWeakPtr()),
      TimeDelta::FromMilliseconds(kPollPauseInMilliseconds));
}

void AudioOutputController::PollAndStartIfDataReady() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  DCHECK_EQ(kStarting, state_);

  // If we are ready to start the stream, start it.
  if (--number_polling_attempts_left_ == 0 ||
      sync_reader_->DataReady()) {
    StartStream();
  } else {
    message_loop_->PostDelayedTask(
        FROM_HERE,
        base::Bind(&AudioOutputController::PollAndStartIfDataReady,
        weak_this_.GetWeakPtr()),
        TimeDelta::FromMilliseconds(kPollPauseInMilliseconds));
  }
}

void AudioOutputController::StartStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  state_ = kPlaying;

  // We start the AudioOutputStream lazily.
  AllowEntryToOnMoreIOData();
  stream_->Start(this);

  // Tell the event handler that we are now playing.
  handler_->OnPlaying(this);
}

void AudioOutputController::StopStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kStarting) {
    // Cancel in-progress polling start.
    weak_this_.InvalidateWeakPtrs();
    state_ = kPaused;
  } else if (state_ == kPlaying) {
    stream_->Stop();
    DisallowEntryToOnMoreIOData();
    state_ = kPaused;
  }
}

void AudioOutputController::DoPause() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  StopStream();

  if (state_ != kPaused)
    return;

  // Send a special pause mark to the low-latency audio thread.
  sync_reader_->UpdatePendingBytes(kPauseMark);

  handler_->OnPaused(this);
}

void AudioOutputController::DoFlush() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // TODO(hclam): Actually flush the audio device.
}

void AudioOutputController::DoClose() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ != kClosed) {
    DoStopCloseAndClearStream();
    sync_reader_->Close();
    state_ = kClosed;
  }
}

void AudioOutputController::DoSetVolume(double volume) {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // Saves the volume to a member first. We may not be able to set the volume
  // right away but when the stream is created we'll set the volume.
  volume_ = volume;

  switch (state_) {
    case kCreated:
    case kStarting:
    case kPlaying:
    case kPaused:
      stream_->SetVolume(volume_);
      break;
    default:
      return;
  }
}

void AudioOutputController::DoReportError(int code) {
  DCHECK(message_loop_->BelongsToCurrentThread());
  if (state_ != kClosed)
    handler_->OnError(this, code);
}

int AudioOutputController::OnMoreData(AudioBus* dest,
                                      AudioBuffersState buffers_state) {
  return OnMoreIOData(NULL, dest, buffers_state);
}

int AudioOutputController::OnMoreIOData(AudioBus* source,
                                        AudioBus* dest,
                                        AudioBuffersState buffers_state) {
  DisallowEntryToOnMoreIOData();
  TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData");

  // The OS level audio APIs on Linux and Windows all have problems requesting
  // data on a fixed interval.  Sometimes they will issue calls back to back
  // which can cause glitching, so wait until the renderer is ready for Read().
  //
  // See many bugs for context behind this decision: http://crbug.com/170498,
  // http://crbug.com/171651, http://crbug.com/174985, and more.
#if defined(OS_WIN) || defined(OS_LINUX)
  WaitTillDataReady();
#endif

  const int frames = sync_reader_->Read(source, dest);
  DCHECK_LE(0, frames);
  sync_reader_->UpdatePendingBytes(
      buffers_state.total_bytes() + frames * params_.GetBytesPerFrame());

  AllowEntryToOnMoreIOData();
  return frames;
}

void AudioOutputController::WaitTillDataReady() {
  base::Time start = base::Time::Now();
  // Wait for up to 683ms for DataReady().  683ms was chosen because it's larger
  // than the playback time of the WaveOut buffer size using the minimum
  // supported sample rate: 2048 / 3000 = ~683ms.
  const base::TimeDelta kMaxWait = base::TimeDelta::FromMilliseconds(683);
  while (!sync_reader_->DataReady() &&
         ((base::Time::Now() - start) < kMaxWait)) {
    base::PlatformThread::YieldCurrentThread();
  }
}

void AudioOutputController::OnError(AudioOutputStream* stream, int code) {
  // Handle error on the audio controller thread.
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputController::DoReportError, this, code));
}

void AudioOutputController::DoStopCloseAndClearStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // Allow calling unconditionally and bail if we don't have a stream_ to close.
  if (stream_) {
    // De-register from state change callbacks if stream_ was created via
    // AudioManager.
    if (stream_ != diverting_to_stream_)
      audio_manager_->RemoveOutputDeviceChangeListener(this);

    StopStream();
    stream_->Close();
    if (stream_ == diverting_to_stream_)
      diverting_to_stream_ = NULL;
    stream_ = NULL;
  }

  state_ = kEmpty;
}

void AudioOutputController::OnDeviceChange() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  // TODO(dalecurtis): Notify the renderer side that a device change has
  // occurred.  Currently querying the hardware information here will lead to
  // crashes on OSX.  See http://crbug.com/158170.

  // Recreate the stream (DoCreate() will first shut down an existing stream).
  // Exit if we ran into an error.
  const State original_state = state_;
  DoCreate(true);
  if (!stream_ || state_ == kError)
    return;

  // Get us back to the original state or an equivalent state.
  switch (original_state) {
    case kStarting:
    case kPlaying:
      DoPlay();
      return;
    case kCreated:
    case kPaused:
      // From the outside these two states are equivalent.
      return;
    default:
      NOTREACHED() << "Invalid original state.";
  }
}

const AudioParameters& AudioOutputController::GetAudioParameters() {
  return params_;
}

void AudioOutputController::StartDiverting(AudioOutputStream* to_stream) {
  message_loop_->PostTask(
      FROM_HERE,
      base::Bind(&AudioOutputController::DoStartDiverting, this, to_stream));
}

void AudioOutputController::StopDiverting() {
  message_loop_->PostTask(
      FROM_HERE, base::Bind(&AudioOutputController::DoStopDiverting, this));
}

void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kClosed)
    return;

  DCHECK(!diverting_to_stream_);
  diverting_to_stream_ = to_stream;
  // Note: OnDeviceChange() will engage the "re-create" process, which will
  // detect and use the alternate AudioOutputStream rather than create a new one
  // via AudioManager.
  OnDeviceChange();
}

void AudioOutputController::DoStopDiverting() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kClosed)
    return;

  // Note: OnDeviceChange() will cause the existing stream (the consumer of the
  // diverted audio data) to be closed, and diverting_to_stream_ will be set
  // back to NULL.
  OnDeviceChange();
  DCHECK(!diverting_to_stream_);
}

void AudioOutputController::AllowEntryToOnMoreIOData() {
  DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_));
  base::AtomicRefCountInc(&num_allowed_io_);
}

void AudioOutputController::DisallowEntryToOnMoreIOData() {
  const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_);
  DCHECK(is_zero);
}

}  // namespace media
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/engine/config.h"
#include "sky/engine/core/painting/LayoutRoot.h"

#include "sky/engine/core/dom/Document.h"
#include "sky/engine/core/dom/Element.h"
#include "sky/engine/core/frame/FrameView.h"
#include "sky/engine/core/frame/LocalFrame.h"
#include "sky/engine/core/frame/Settings.h"
#include "sky/engine/core/painting/PaintingTasks.h"
#include "sky/engine/platform/geometry/IntRect.h"
#include "third_party/skia/include/core/SkCanvas.h"

namespace blink {

PassRefPtr<LayoutRoot> LayoutRoot::create()
{
    return adoptRef(new LayoutRoot);
}

LayoutRoot::LayoutRoot()
    : m_minWidth(0)
    , m_maxWidth(0)
    , m_minHeight(0)
    , m_maxHeight(0)
{
    m_settings = Settings::create();
    m_settings->setDefaultFixedFontSize(13);
    m_settings->setDefaultFontSize(16);
    m_frameHost = FrameHost::createDummy(m_settings.get());
    m_frame = LocalFrame::create(nullptr, m_frameHost.get());
    m_frame->createView(IntSize(), Color::white, false);
}

LayoutRoot::~LayoutRoot()
{
}

Element* LayoutRoot::rootElement() const
{
    if (!m_document)
        return nullptr;
    return m_document->firstElementChild();
}

void LayoutRoot::setRootElement(Element* root)
{
    m_document = &root->document();
    m_frame->setDocument(m_document.get());
    m_document->setFrame(m_frame.get());

    m_document->attach();
    m_document->setChild(root, ASSERT_NO_EXCEPTION);

    m_document->setFrame(nullptr);
    m_frame->setDocument(nullptr);
}

void LayoutRoot::layout()
{
    m_frame->setDocument(m_document.get());
    m_document->setFrame(m_frame.get());

    LayoutUnit maxWidth = std::max(m_minWidth, m_maxWidth);
    LayoutUnit maxHeight = std::max(m_minHeight, m_maxHeight);
    IntSize maxSize(maxWidth, maxHeight);

    m_frame->view()->setFrameRect(IntRect(IntPoint(), maxSize));
    m_frame->view()->setLayoutSize(maxSize);

    m_document->updateLayout();

    m_document->setFrame(nullptr);
    m_frame->setDocument(nullptr);
}

void LayoutRoot::paint(Canvas* canvas)
{
    if (m_document)
        rootElement()->paint(canvas);
}

} // namespace blink
<commit_msg>Make SkyShell stop crashing on scroll in Stocks2.<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/engine/config.h"
#include "sky/engine/core/painting/LayoutRoot.h"

#include "sky/engine/core/dom/Document.h"
#include "sky/engine/core/dom/Element.h"
#include "sky/engine/core/frame/FrameView.h"
#include "sky/engine/core/frame/LocalFrame.h"
#include "sky/engine/core/frame/Settings.h"
#include "sky/engine/core/painting/PaintingTasks.h"
#include "sky/engine/platform/geometry/IntRect.h"
#include "third_party/skia/include/core/SkCanvas.h"

namespace blink {

PassRefPtr<LayoutRoot> LayoutRoot::create()
{
    return adoptRef(new LayoutRoot);
}

LayoutRoot::LayoutRoot()
    : m_minWidth(0)
    , m_maxWidth(0)
    , m_minHeight(0)
    , m_maxHeight(0)
{
    m_settings = Settings::create();
    m_settings->setDefaultFixedFontSize(13);
    m_settings->setDefaultFontSize(16);
    m_frameHost = FrameHost::createDummy(m_settings.get());
    m_frame = LocalFrame::create(nullptr, m_frameHost.get());
    m_frame->createView(IntSize(), Color::white, false);
}

LayoutRoot::~LayoutRoot()
{
    if (!m_document->needsAttach())
        m_document->detach();
}

Element* LayoutRoot::rootElement() const
{
    if (!m_document)
        return nullptr;
    return m_document->firstElementChild();
}

void LayoutRoot::setRootElement(Element* root)
{
    m_document = &root->document();
    m_frame->setDocument(m_document.get());
    m_document->setFrame(m_frame.get());

    m_document->attach();
    m_document->setChild(root, ASSERT_NO_EXCEPTION);

    m_document->setFrame(nullptr);
    m_frame->setDocument(nullptr);
}

void LayoutRoot::layout()
{
    m_frame->setDocument(m_document.get());
    m_document->setFrame(m_frame.get());

    LayoutUnit maxWidth = std::max(m_minWidth, m_maxWidth);
    LayoutUnit maxHeight = std::max(m_minHeight, m_maxHeight);
    IntSize maxSize(maxWidth, maxHeight);

    m_frame->view()->setFrameRect(IntRect(IntPoint(), maxSize));
    m_frame->view()->setLayoutSize(maxSize);

    m_document->updateLayout();

    m_document->setFrame(nullptr);
    m_frame->setDocument(nullptr);
}

void LayoutRoot::paint(Canvas* canvas)
{
    if (m_document)
        rootElement()->paint(canvas);
}

} // namespace blink
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                      Simbody(tm) Example: Long Pendulum                    *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK biosimulation toolkit originating from           *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
 *                                                                            *
 * Portions copyright (c) 2008-13 Stanford University and the Authors.        *
 * Authors: Michael Sherman                                                   *
 * Contributors:                                                              *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

/*                      Simbody ExampleLongPendulum
This example shows how to build a linked chain of bodies programmatically,
simulate it, and produce a simple animation while it is simulating. */

#include "Simbody.h"
#include <iostream>

using namespace SimTK;

int main() {
  try {
    // Create the system.

    MultibodySystem system; system.setUseUniformBackground(true);
    SimbodyMatterSubsystem matter(system);
    GeneralForceSubsystem forces(system);
    Force::UniformGravity gravity(forces, matter, Vec3(0, -9.8, 0));
    Body::Rigid pendulumBody(MassProperties(1.0, Vec3(0), Inertia(1)));
    pendulumBody.addDecoration(Transform(), DecorativeSphere(0.1));

    MobilizedBody lastBody = matter.Ground();
    for (int i = 0; i < 10; ++i) {
        MobilizedBody::Ball pendulum(lastBody,     Transform(Vec3(0)),
                                     pendulumBody, Transform(Vec3(0, 1, 0)));
        lastBody = pendulum;
    }

    Visualizer viz(system);
    system.addEventReporter(new Visualizer::Reporter(viz, 1./30));

    // Initialize the system and state.

    system.realizeTopology();
    State state = system.getDefaultState();
    Random::Gaussian random;
    for (int i = 0; i < state.getNQ(); ++i)
        state.updQ()[i] = random.getValue();

    // Simulate it.

    RungeKuttaMersonIntegrator integ(system);
    TimeStepper ts(system, integ);
    ts.initialize(state);
    ts.stepTo(10.0);

  } catch(const std::exception& e) {
    std::cout << "EXCEPTION: " << e.what() << std::endl;
    return 1;
  }
    return 0;
}
<commit_msg>Update ExampleLongPendulum.cpp<commit_after>/* -------------------------------------------------------------------------- *
 *                      Simbody(tm) Example: Long Pendulum                    *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK biosimulation toolkit originating from           *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
 *                                                                            *
 * Portions copyright (c) 2008-13 Stanford University and the Authors.        *
 * Authors: Michael Sherman                                                   *
 * Contributors:                                                              *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

/*                      Simbody ExampleLongPendulum
This example shows how to build a linked chain of bodies programmatically,
simulate it, and produce a simple animation while it is simulating. */

#include "Simbody.h"
#include <iostream>

using namespace SimTK;

int main() {
  try {
    // Create the system.

    MultibodySystem system; system.setUseUniformBackground(true);
    SimbodyMatterSubsystem matter(system);
    GeneralForceSubsystem forces(system);
    Force::UniformGravity gravity(forces, matter, Vec3(0, -9.8, 0));
    Body::Rigid pendulumBody(MassProperties(1.0, Vec3(0), Inertia(1)));
    pendulumBody.addDecoration(Transform(), DecorativeSphere(0.1));

    MobilizedBody lastBody = matter.Ground();
    for (int i = 0; i < 10; ++i) {
        MobilizedBody::Ball pendulum(lastBody,     Transform(Vec3(0)),
                                     pendulumBody, Transform(Vec3(0, 1, 0)));
        lastBody = pendulum;
    }

    Visualizer viz(system);
    system.addEventReporter(new Visualizer::Reporter(viz, 1./30));

    // Initialize the system and state.

    system.realizeTopology();
    State state = system.getDefaultState();
    Random::Gaussian random;
    for (int i = 0; i < state.getNQ(); ++i)
        state.updQ()[i] = random.getValue();

    // Simulate it.

    RungeKuttaMersonIntegrator integ(system);
    TimeStepper ts(system, integ);
    ts.initialize(state);
    ts.stepTo(10.0);

  } catch(const std::exception& e) {
    std::cout << "EXCEPTION: " << e.what() << std::endl;
    return 1;
  } catch (...) {
      std::cout << "UNKNOWN EXCEPTION\n";
      return 1;
  }
    return 0;
}
<|endoftext|>


<commit_before>#include "fourtaxon.hpp"
using namespace std;

/*-----------------------------------------------------------------------------
| 	Allocates a two-dimensional array of doubles as one contiguous block of
|	memory the dimensions are f by s. The array is set up so that each
|	successive row follows the previous row in memory.
*/
double **NewTwoDArray(unsigned f , unsigned s)
	{
	double **ptr;
	ptr = new double *[f];
	*ptr = new double [f * s];
	for (unsigned fIt = 1 ; fIt < f ; fIt++)
		ptr[fIt] = ptr[fIt -1] +  s ;
	return ptr;
	}

/*-----------------------------------------------------------------------------
|	Delete a two-dimensional array (e.g. one created by NewTwoDArray) and set
|	ptr to NULL.
*/
void DeleteTwoDArray (double ** & ptr)
	{
	if (ptr)
		{
		delete [] * ptr;
		delete [] ptr;
		ptr = NULL;
		}
	}

/*-----------------------------------------------------------------------------
|	Constructor simply calls init().
*/
FourTaxonExample::FourTaxonExample()
	{
	init();
	}

/*-----------------------------------------------------------------------------
|	This function is called if the program encounters an unrecoverable error.
|	After issuing the supplied error message, the program exits, returning 1.
*/
void FourTaxonExample::abort(
  std::string msg)	/**< is the error message to report to the user */
	{
	std::cerr << msg << "\nAborting..." << std::endl;
	std::exit(1);
	}

/*-----------------------------------------------------------------------------
|	The init() function sets up the beagle library and initializes all data
|	members.
*/
void FourTaxonExample::init()
	{
	int code;

	taxon_name.resize(4);
	data.resize(4);
	partial.resize(4);

	// hard coded tree topology is (A,B,(C,D))
	// where taxon order is A, B, C, D in the data file
	// Assume nodes 0..3 are the tip node indices
	// Assume node 4 is ancestor of A,B (0,1)
	// Assume node 5 is ancestor of C,D (2,3)
	operations.push_back(4);	// destination (to be calculated)
	operations.push_back(0);	// left child partial index
	operations.push_back(0);	// left child transition matrix index
	operations.push_back(1);	// right child partial index
	operations.push_back(1);	// right child transition matrix index

	operations.push_back(5);	// destination (to be calculated)
	operations.push_back(2);	// left child partial index
	operations.push_back(2);	// left child transition matrix index
	operations.push_back(3);	// right child partial index
	operations.push_back(3);	// right child transition matrix index

	instance_handle = createInstance(
				4,			// tipCount
				7,			// partialsBufferCount
				0,			// compactBufferCount
				4, 			// stateCount
				nsites,		// patternCount
				1,			// eigenBufferCount
				5,			// matrixBufferCount,
				NULL,		// resourceList
				0,			// resourceCount
				0,			// preferenceFlags
				0			// requirementFlags
				);

	if (instance_handle < 0)
		abort("createInstance returned a negative instance handle (and that's not good)");

	transition_matrix_index.resize(5);
	transition_matrix_index.push_back(0);
	transition_matrix_index.push_back(1);
	transition_matrix_index.push_back(2);
	transition_matrix_index.push_back(3);
	transition_matrix_index.push_back(4);

	brlens.resize(5);
	brlens.push_back(0.01);
	brlens.push_back(0.02);
	brlens.push_back(0.03);
	brlens.push_back(0.04);
	brlens.push_back(0.05);

	for (unsigned i = 0; i < 4; ++i)
		{
		code = setPartials(
						instance_handle,			// instance
						i,							// bufferIndex
						&partial[i][0]);			// inPartials
		if (code != 0)
			abort("setPartials encountered a problem");
		}

	double evec[4][4] = {
		{ 1.0,  2.0,  0.0,  0.5},
		{ 1.0,  -2.0,  0.5,  0.0},
		{ 1.0,  2.0, 0.0,  -0.5},
		{ 1.0,  -2.0,  -0.5,  0.0}
	};

	double ivec[4][4] = {
		{ 0.25,  0.25,  0.25,  0.25},
		{ 0.125,  -0.125,  0.125,  -0.125},
		{ 0.0,  1.0,  0.0,  -1.0},
		{ 1.0,  0.0,  -1.0,  0.0}
	};

	double eval[4] = { 0.0, -1.3333333333333333, -1.3333333333333333, -1.3333333333333333 };

	double ** evecP = NewTwoDArray(4,4);
	double ** ivecP = NewTwoDArray(4,4);

	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			evecP[i][j] = evec[i][j];
			ivecP[i][j] = ivec[i][j];
		}
	}

	code = setEigenDecomposition(
			   instance_handle,					// instance
			   0,								// eigenIndex,
			   (const double **)evecP,			// inEigenVectors,
			   (const double **)ivecP,			// inInverseEigenVectors,
			   eval);							// inEigenValues

	DeleteTwoDArray(evecP);
	DeleteTwoDArray(ivecP);

	if (code != 0)
		abort("setEigenDecomposition encountered a problem");
	}

/*-----------------------------------------------------------------------------
|
*/
double FourTaxonExample::calcLnL()
	{
	int code = updateTransitionMatrices(
			instance_handle,				// instance,
			0,								// eigenIndex,
			&transition_matrix_index[0],	// probabilityIndices,
			NULL, 							// firstDerivativeIndices,
			NULL,							// secondDervativeIndices,
			&brlens[0],						// edgeLengths,
			5);								// count

	if (code != 0)
		abort("updateTransitionMatrices encountered a problem");

	code = updatePartials(
		   &instance_handle,	// instance
		   1,					// instanceCount
		   &operations[0],		// operations
		   2,					// operationCount
		   0);					// rescale

	if (code != 0)
		abort("updatePartials encountered a problem");

	int parentBufferIndex = 4;
	int childBufferIndex  = 5;
	int transitionMatrixIndex  = 4;
	double relativeRateProb  = 1.0;
	double stateFreqs[] = {0.25, 0.25, 0.25, 0.25};
	double lnL = 0.0;

	code = calculateEdgeLogLikelihoods(
		 instance_handle,					// instance,
		 &parentBufferIndex,				// parentBufferIndices
		 &childBufferIndex,					// childBufferIndices
		 &transitionMatrixIndex,			// probabilityIndices
		 NULL,								// firstDerivativeIndices
		 NULL,								// secondDerivativeIndices
		 (const double*)&relativeRateProb,	// weights
		 (const double**)&stateFreqs,		// stateFrequencies,
		 1,									// count
		 &lnL,								// outLogLikelihoods,
		 NULL,								// outFirstDerivatives,
		 NULL);								// outSecondDerivatives

	if (code != 0)
		abort("calculateEdgeLogLikelihoods encountered a problem");

	return lnL;
	}

/*-----------------------------------------------------------------------------
|
*/
void FourTaxonExample::run()
	{
	readData("fourtaxon.dat");
	//writeData("example_data.check.txt");

	unsigned nreps = 1000;
	for (unsigned rep = 0; rep < nreps; ++rep)
		{
		std::cerr << rep << ": lnL = " << calcLnL() << std::endl;
		}

	int code = finalize(
		instance_handle);		// instance

	std::cerr << "finalize returned " << code << std::endl;
	}

/*-----------------------------------------------------------------------------
|
*/
void FourTaxonExample::readData(const std::string file_name)
	{
	std::string sequence;
	std::ifstream inf(file_name.c_str());
	if(!inf.good())
		abort("problem reading datafile");
	inf >> ntaxa >> nsites;
	for (unsigned i = 0; i < ntaxa; ++i)
		{
		inf >> taxon_name[i];
		inf >> sequence;
		data[i].resize(nsites);
		partial[i].reserve(nsites*4);
		for (unsigned j = 0; j < nsites; ++j)
			{
			switch (sequence[j])
				{
				case 'a':
				case 'A':
					data[i][j] = 0;
					partial[i].push_back(1.0);
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					break;
				case 'c':
				case 'C':
					data[i][j] = 1;
					partial[i].push_back(0.0);
					partial[i].push_back(1.0);
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					break;
				case 'g':
				case 'G':
					data[i][j] = 2;
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					partial[i].push_back(1.0);
					partial[i].push_back(0.0);
					break;
				case 't':
				case 'T':
					data[i][j] = 3;
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					partial[i].push_back(1.0);
					break;
				default:
					data[i][j] = 4;
					partial[i].push_back(1.0);
					partial[i].push_back(1.0);
					partial[i].push_back(1.0);
					partial[i].push_back(1.0);
				}
			}
		}
	inf.close();
	}

/*-----------------------------------------------------------------------------
|
*/
void FourTaxonExample::writeData(const std::string file_name)
	{
	std::ofstream outf(file_name.c_str(), std::ios::out);
	outf << ntaxa << " " << nsites << std::endl;
	for (unsigned i = 0; i < ntaxa; ++i)
		{
		outf << taxon_name[i] << " ";
		for (unsigned j = 0; j < nsites; ++j)
			{
			switch (data[i][j])
				{
				case 0:
					outf << 'a';
					break;
				case 1:
					outf << 'c';
					break;
				case 2:
					outf << 'g';
					break;
				case 3:
					outf << 't';
					break;
				default:
					outf << '?';
				}
			}
			outf << std::endl;
		}
	outf.close();
	}

/*-----------------------------------------------------------------------------
|
*/
int main(int argc, char* argv[])
	{
	FourTaxonExample().run();
	}

<commit_msg>various bug fixes. Now we get a likelihood, but it does not agree with PAUP<commit_after>#include "fourtaxon.hpp"
#include <algorithm>
using namespace std;

/*-----------------------------------------------------------------------------
| 	Allocates a two-dimensional array of doubles as one contiguous block of
|	memory the dimensions are f by s. The array is set up so that each
|	successive row follows the previous row in memory.
*/
double **NewTwoDArray(unsigned f , unsigned s)
	{
	double **ptr;
	ptr = new double *[f];
	*ptr = new double [f * s];
	for (unsigned fIt = 1 ; fIt < f ; fIt++)
		ptr[fIt] = ptr[fIt -1] +  s ;
	return ptr;
	}

/*-----------------------------------------------------------------------------
|	Delete a two-dimensional array (e.g. one created by NewTwoDArray) and set
|	ptr to NULL.
*/
void DeleteTwoDArray (double ** & ptr)
	{
	if (ptr)
		{
		delete [] * ptr;
		delete [] ptr;
		ptr = NULL;
		}
	}

/*-----------------------------------------------------------------------------
|	Constructor simply calls init().
*/
FourTaxonExample::FourTaxonExample()
	{
	//init();
	}

/*-----------------------------------------------------------------------------
|	This function is called if the program encounters an unrecoverable error.
|	After issuing the supplied error message, the program exits, returning 1.
*/
void FourTaxonExample::abort(
  std::string msg)	/**< is the error message to report to the user */
	{
	std::cerr << msg << "\nAborting..." << std::endl;
	std::exit(1);
	}

/*-----------------------------------------------------------------------------
|	The init() function sets up the beagle library and initializes all data
|	members.
*/
void FourTaxonExample::init()
	{
	int code;
	partial.resize(4);

	// hard coded tree topology is (A,B,(C,D))
	// where taxon order is A, B, C, D in the data file
	// Assume nodes 0..3 are the tip node indices
	// Assume node 4 is ancestor of A,B (0,1)
	// Assume node 5 is ancestor of C,D (2,3)
	operations.push_back(4);	// destination (to be calculated)
	operations.push_back(0);	// left child partial index
	operations.push_back(0);	// left child transition matrix index
	operations.push_back(1);	// right child partial index
	operations.push_back(1);	// right child transition matrix index

	operations.push_back(5);	// destination (to be calculated)
	operations.push_back(2);	// left child partial index
	operations.push_back(2);	// left child transition matrix index
	operations.push_back(3);	// right child partial index
	operations.push_back(3);	// right child transition matrix index

	cout << "nsites\t" << nsites << endl;

	instance_handle = createInstance(
				4,			// tipCount
				7,			// partialsBufferCount
				0,			// compactBufferCount
				4, 			// stateCount
				nsites,		// patternCount
				1,			// eigenBufferCount
				5,			// matrixBufferCount,
				NULL,		// resourceList
				0,			// resourceCount
				0,			// preferenceFlags
				0			// requirementFlags
				);

	if (instance_handle < 0)
		abort("createInstance returned a negative instance handle (and that's not good)");

	transition_matrix_index.resize(5);
	brlens.resize(5);
	for (unsigned brIndex = 0; brIndex < 5; ++brIndex)
		{
		transition_matrix_index[brIndex] = brIndex;
		brlens[brIndex] = 0.01 + ((float)brIndex)/100.0;
		}

	for (unsigned i = 0; i < 4; ++i)
		{
		code = setPartials(
						instance_handle,			// instance
						i,							// bufferIndex
						&partial[i][0]);			// inPartials
		if (code != 0)
			abort("setPartials encountered a problem");
		}
	double evec[4][4] = {
		{ 1.0,  2.0,  0.0,  0.5},
		{ 1.0,  -2.0,  0.5,  0.0},
		{ 1.0,  2.0, 0.0,  -0.5},
		{ 1.0,  -2.0,  -0.5,  0.0}
	};

	double ivec[4][4] = {
		{ 0.25,  0.25,  0.25,  0.25},
		{ 0.125,  -0.125,  0.125,  -0.125},
		{ 0.0,  1.0,  0.0,  -1.0},
		{ 1.0,  0.0,  -1.0,  0.0}
	};

	double eval[4] = { 0.0, -1.3333333333333333, -1.3333333333333333, -1.3333333333333333 };

	double ** evecP = NewTwoDArray(4,4);
	double ** ivecP = NewTwoDArray(4,4);

	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			evecP[i][j] = evec[i][j];
			ivecP[i][j] = ivec[i][j];
		}
	}

	code = setEigenDecomposition(
			   instance_handle,					// instance
			   0,								// eigenIndex,
			   (const double **)evecP,			// inEigenVectors,
			   (const double **)ivecP,			// inInverseEigenVectors,
			   eval);							// inEigenValues

	DeleteTwoDArray(evecP);
	DeleteTwoDArray(ivecP);

	if (code != 0)
		abort("setEigenDecomposition encountered a problem");
	}

/*-----------------------------------------------------------------------------
|
*/
double FourTaxonExample::calcLnL()
	{
	int code = updateTransitionMatrices(
			instance_handle,				// instance,
			0,								// eigenIndex,
			&transition_matrix_index[0],	// probabilityIndices,
			NULL, 							// firstDerivativeIndices,
			NULL,							// secondDervativeIndices,
			&brlens[0],						// edgeLengths,
			5);								// count

	if (code != 0)
		abort("updateTransitionMatrices encountered a problem");

	code = updatePartials(
		   &instance_handle,	// instance
		   1,					// instanceCount
		   &operations[0],		// operations
		   2,					// operationCount
		   0);					// rescale

	if (code != 0)
		abort("updatePartials encountered a problem");

	int parentBufferIndex = 4;
	int childBufferIndex  = 5;
	int transitionMatrixIndex  = 4;
	double relativeRateProb  = 1.0;
	//double stateFreqs[] = {0.25, 0.25, 0.25, 0.25};
	double ** stateFreqs = NewTwoDArray(1,4);
	for (int i=0;i<4;i++)
		stateFreqs[0][i] = 0.25;

	vector<double> lnL(nsites);

	code = calculateEdgeLogLikelihoods(
		 instance_handle,					// instance,
		 &parentBufferIndex,				// parentBufferIndices
		 &childBufferIndex,					// childBufferIndices
		 &transitionMatrixIndex,			// probabilityIndices
		 NULL,								// firstDerivativeIndices
		 NULL,								// secondDerivativeIndices
		 (const double*)&relativeRateProb,	// weights
		 (const double**)stateFreqs,		// stateFrequencies,
		 1,									// count
		 &lnL[0],								// outLogLikelihoods,
		 NULL,								// outFirstDerivatives,
		 NULL);								// outSecondDerivatives

	if (code != 0)
		abort("calculateEdgeLogLikelihoods encountered a problem");

	//return std::accumulate(lnL.begin(),lnL.end(),0.0);
	double tot=0.0;
	for(int i=0;i<nsites;i++){
//		std::cout << lnL[i] << std::endl;
		tot += lnL[i];
		}
	return tot;
//	return lnL;
	}

/*-----------------------------------------------------------------------------
|
*/
void FourTaxonExample::run()
	{
	readData("fourtaxon.dat");
	init();
	//writeData("example_data.check.txt");

	unsigned nreps = 1;
	for (unsigned rep = 0; rep < nreps; ++rep)
		{
		std::cerr << rep << ": lnL = " << calcLnL() << std::endl;
		}

	int code = finalize(
		instance_handle);		// instance

	std::cerr << "finalize returned " << code << std::endl;
	}

/*-----------------------------------------------------------------------------
|
*/
void FourTaxonExample::readData(const std::string file_name)
	{
	std::cerr << "opening " << file_name.c_str() << " ..." << std::endl;
	std::string sequence;
	std::ifstream inf(file_name.c_str());
	if(!inf.good())
		abort("problem reading datafile");
	inf >> ntaxa >> nsites;
	cout << "ntaxa\t" << ntaxa << "\tnsites\t" << nsites << endl;
	taxon_name.resize(ntaxa);
	data.resize(ntaxa);
	partial.resize(ntaxa);
	for (unsigned i = 0; i < ntaxa; ++i)
		{
		inf >> taxon_name[i];
		inf >> sequence;
		data[i].resize(nsites);
		partial[i].reserve(nsites*4);
		for (unsigned j = 0; j < nsites; ++j)
			{
			switch (sequence[j])
				{
				case 'a':
				case 'A':
					data[i][j] = 0;
					partial[i].push_back(1.0);
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					break;
				case 'c':
				case 'C':
					data[i][j] = 1;
					partial[i].push_back(0.0);
					partial[i].push_back(1.0);
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					break;
				case 'g':
				case 'G':
					data[i][j] = 2;
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					partial[i].push_back(1.0);
					partial[i].push_back(0.0);
					break;
				case 't':
				case 'T':
					data[i][j] = 3;
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					partial[i].push_back(0.0);
					partial[i].push_back(1.0);
					break;
				default:
					data[i][j] = 4;
					partial[i].push_back(1.0);
					partial[i].push_back(1.0);
					partial[i].push_back(1.0);
					partial[i].push_back(1.0);
				}
			}
		}
	inf.close();
	}

/*-----------------------------------------------------------------------------
|
*/
void FourTaxonExample::writeData(const std::string file_name)
	{
	std::ofstream outf(file_name.c_str(), std::ios::out);
	outf << ntaxa << " " << nsites << std::endl;
	for (unsigned i = 0; i < ntaxa; ++i)
		{
		outf << taxon_name[i] << " ";
		for (unsigned j = 0; j < nsites; ++j)
			{
			switch (data[i][j])
				{
				case 0:
					outf << 'a';
					break;
				case 1:
					outf << 'c';
					break;
				case 2:
					outf << 'g';
					break;
				case 3:
					outf << 't';
					break;
				default:
					outf << '?';
				}
			}
			outf << std::endl;
		}
	outf.close();
	}

/*-----------------------------------------------------------------------------
|
*/
int main(int argc, char* argv[])
	{
	FourTaxonExample fte;
	fte.run();
	}

<|endoftext|>


<commit_before>#include "SH_OpenAL.h"
#include "alloca_def.h"
#include <assert.h>

//#define LOGGING
#define SAMPLE_RATE 44100

ALCint g_attrList[] =
{
	ALC_FREQUENCY,	SAMPLE_RATE,
	0,				0
};

#define CHECK_AL_ERROR() { assert(alGetError() == AL_NO_ERROR); }

CSH_OpenAL::CSH_OpenAL() :
m_context(m_device, g_attrList),
m_lastUpdateTime(0),
m_mustSync(true)
{
	m_context.MakeCurrent();
	alGenBuffers(MAX_BUFFERS, m_bufferNames);
	CHECK_AL_ERROR();
	Reset();
}

CSH_OpenAL::~CSH_OpenAL()
{
	Reset();
	alDeleteBuffers(MAX_BUFFERS, m_bufferNames);
	CHECK_AL_ERROR();
}

CSoundHandler* CSH_OpenAL::HandlerFactory()
{
	return new CSH_OpenAL();
}

void CSH_OpenAL::Reset()
{
	m_source.Stop();
	ALint sourceState = m_source.GetState();
	assert(sourceState == AL_INITIAL || sourceState == AL_STOPPED);
	alSourcei(m_source, AL_BUFFER, 0);
	CHECK_AL_ERROR();
	m_availableBuffers.clear();
	m_availableBuffers.insert(m_availableBuffers.begin(), m_bufferNames, m_bufferNames + MAX_BUFFERS);
}

void CSH_OpenAL::RecycleBuffers()
{
	unsigned int bufferCount = m_source.GetBuffersProcessed();
	CHECK_AL_ERROR();
	if(bufferCount != 0)
	{
		ALuint* bufferNames = reinterpret_cast<ALuint*>(alloca(sizeof(ALuint) * bufferCount));
		alSourceUnqueueBuffers(m_source, bufferCount, bufferNames);
		CHECK_AL_ERROR();
		m_availableBuffers.insert(m_availableBuffers.begin(), bufferNames, bufferNames + bufferCount);
	}
}

bool CSH_OpenAL::HasFreeBuffers()
{
	return m_availableBuffers.size() != 0;
}

void CSH_OpenAL::Write(int16* samples, unsigned int sampleCount, unsigned int sampleRate)
{
	assert(m_availableBuffers.size() != 0);
	if(m_availableBuffers.size() == 0) return;
	ALuint buffer = *m_availableBuffers.begin();
	m_availableBuffers.pop_front();

	alBufferData(buffer, AL_FORMAT_STEREO16, samples, sampleCount * sizeof(int16), sampleRate);
	CHECK_AL_ERROR();

	alSourceQueueBuffers(m_source, 1, &buffer);
	CHECK_AL_ERROR();

	if(m_availableBuffers.size() == 0)
	{
		ALint sourceState = m_source.GetState();
		if(sourceState != AL_PLAYING)
		{
			m_source.Play();
			assert(m_source.GetState() == AL_PLAYING);
			RecycleBuffers();
		}
	}
}
<commit_msg>Don't wait for all buffers to be queued before starting playback.<commit_after>#include "SH_OpenAL.h"
#include "alloca_def.h"
#include <assert.h>

//#define LOGGING
#define SAMPLE_RATE 44100

ALCint g_attrList[] =
{
	ALC_FREQUENCY,	SAMPLE_RATE,
	0,				0
};

#define CHECK_AL_ERROR() { assert(alGetError() == AL_NO_ERROR); }

CSH_OpenAL::CSH_OpenAL() :
m_context(m_device, g_attrList),
m_lastUpdateTime(0),
m_mustSync(true)
{
	m_context.MakeCurrent();
	alGenBuffers(MAX_BUFFERS, m_bufferNames);
	CHECK_AL_ERROR();
	Reset();
}

CSH_OpenAL::~CSH_OpenAL()
{
	Reset();
	alDeleteBuffers(MAX_BUFFERS, m_bufferNames);
	CHECK_AL_ERROR();
}

CSoundHandler* CSH_OpenAL::HandlerFactory()
{
	return new CSH_OpenAL();
}

void CSH_OpenAL::Reset()
{
	m_source.Stop();
	ALint sourceState = m_source.GetState();
	assert(sourceState == AL_INITIAL || sourceState == AL_STOPPED);
	alSourcei(m_source, AL_BUFFER, 0);
	CHECK_AL_ERROR();
	m_availableBuffers.clear();
	m_availableBuffers.insert(m_availableBuffers.begin(), m_bufferNames, m_bufferNames + MAX_BUFFERS);
}

void CSH_OpenAL::RecycleBuffers()
{
	unsigned int bufferCount = m_source.GetBuffersProcessed();
	CHECK_AL_ERROR();
	if(bufferCount != 0)
	{
		ALuint* bufferNames = reinterpret_cast<ALuint*>(alloca(sizeof(ALuint) * bufferCount));
		alSourceUnqueueBuffers(m_source, bufferCount, bufferNames);
		CHECK_AL_ERROR();
		m_availableBuffers.insert(m_availableBuffers.begin(), bufferNames, bufferNames + bufferCount);
	}
}

bool CSH_OpenAL::HasFreeBuffers()
{
	return m_availableBuffers.size() != 0;
}

void CSH_OpenAL::Write(int16* samples, unsigned int sampleCount, unsigned int sampleRate)
{
	assert(m_availableBuffers.size() != 0);
	if(m_availableBuffers.size() == 0) return;
	ALuint buffer = *m_availableBuffers.begin();
	m_availableBuffers.pop_front();

	alBufferData(buffer, AL_FORMAT_STEREO16, samples, sampleCount * sizeof(int16), sampleRate);
	CHECK_AL_ERROR();

	alSourceQueueBuffers(m_source, 1, &buffer);
	CHECK_AL_ERROR();

	ALint sourceState = m_source.GetState();
	if(sourceState != AL_PLAYING)
	{
		m_source.Play();
		assert(m_source.GetState() == AL_PLAYING);
	}
}
<|endoftext|>


<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2014-2015 Pedro Côrte-Real

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decoders/RafDecoder.h"
#include "common/Common.h"                          // for uint32, ushort16
#include "common/Point.h"                           // for iPoint2D, iRecta...
#include "decoders/RawDecoderException.h"           // for RawDecoderExcept...
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
#include "io/Buffer.h"                              // for Buffer
#include "io/ByteStream.h"                          // for ByteStream
#include "io/Endianness.h"                          // for getHostEndianness
#include "metadata/BlackArea.h"                     // for BlackArea
#include "metadata/Camera.h"                        // for Camera, Hints
#include "metadata/CameraMetaData.h"                // for CameraMetaData
#include "metadata/CameraSensorInfo.h"              // for CameraSensorInfo
#include "metadata/ColorFilterArray.h"              // for ColorFilterArray
#include "tiff/TiffEntry.h"                         // for TiffEntry
#include "tiff/TiffIFD.h"                           // for TiffRootIFD, Tif...
#include "tiff/TiffTag.h"                           // for TiffTag::FUJIOLDWB
#include <cassert>                                  // for assert
#include <cstdio>                                   // for size_t
#include <cstring>                                  // for memcmp
#include <memory>                                   // for unique_ptr, allo...
#include <string>                                   // for string
#include <vector>                                   // for vector

namespace rawspeed {

bool RafDecoder::isRAF(const Buffer* input) {
  static const char magic[] = "FUJIFILMCCD-RAW ";
  static const size_t magic_size = sizeof(magic) - 1; // excluding \0
  const unsigned char* data = input->getData(0, magic_size);
  return 0 == memcmp(&data[0], magic, magic_size);
}

bool RafDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD,
                                      const Buffer* file) {
  const auto id = rootIFD->getID();
  const std::string& make = id.make;

  // FIXME: magic

  return make == "FUJIFILM";
}

RawImage RafDecoder::decodeRawInternal() {
  auto raw = mRootIFD->getIFDWithTag(FUJI_STRIPOFFSETS);
  uint32 height = 0;
  uint32 width = 0;

  if (raw->hasEntry(FUJI_RAWIMAGEFULLHEIGHT)) {
    height = raw->getEntry(FUJI_RAWIMAGEFULLHEIGHT)->getU32();
    width = raw->getEntry(FUJI_RAWIMAGEFULLWIDTH)->getU32();
  } else if (raw->hasEntry(IMAGEWIDTH)) {
    TiffEntry *e = raw->getEntry(IMAGEWIDTH);
    height = e->getU16(0);
    width = e->getU16(1);
  } else
    ThrowRDE("Unable to locate image size");

  if (raw->hasEntry(FUJI_LAYOUT)) {
    TiffEntry *e = raw->getEntry(FUJI_LAYOUT);
    alt_layout = !(e->getByte(0) >> 7);
  }

  TiffEntry *offsets = raw->getEntry(FUJI_STRIPOFFSETS);
  TiffEntry *counts = raw->getEntry(FUJI_STRIPBYTECOUNTS);

  if (offsets->count != 1 || counts->count != 1)
    ThrowRDE("Multiple Strips found: %u %u", offsets->count, counts->count);

  if (counts->getU32() * 8 / (width * height) < 10)
    ThrowRDE("Don't know how to decode compressed images");

  ByteStream input(offsets->getRootIfdData());
  input = input.getSubStream(offsets->getU32(), counts->getU32());

  // x-trans sensors report 14bpp, but data isn't packed
  // thus, unless someone has any better ideas, let's autodetect it.
  int bps;

  // Some fuji SuperCCD cameras include a second raw image next to the first one
  // that is identical but darker to the first. The two combined can produce
  // a higher dynamic range image. Right now we're ignoring it.
  bool double_width;

  if (8UL * counts->getU32() >= 2UL * 16UL * width * height) {
    bps = 16;
    double_width = true;
  } else if (8UL * counts->getU32() >= 2UL * 14UL * width * height) {
    bps = 14;
    double_width = true;
  } else if (8UL * counts->getU32() >= 2UL * 12UL * width * height) {
    bps = 12;
    double_width = true;
  } else if (8UL * counts->getU32() >= 16UL * width * height) {
    bps = 16;
    double_width = false;
  } else if (8UL * counts->getU32() >= 14UL * width * height) {
    bps = 14;
    double_width = false;
  } else if (8UL * counts->getU32() >= 12UL * width * height) {
    bps = 12;
    double_width = false;
  } else {
    ThrowRDE("Can not detect bitdepth. StripByteCounts = %u, width = %u, "
             "height = %u",
             counts->getU32(), width, height);
  }

  double_width = hints.has("double_width_unpacked");
  const uint32 real_width = double_width ? 2U * width : width;

  mRaw->dim = iPoint2D(real_width, height);
  mRaw->createData();

  UncompressedDecompressor u(input, mRaw);

  iPoint2D pos(0, 0);

  if (double_width) {
    u.decodeRawUnpacked<16, little>(width * 2, height);
  } else if (input.isInNativeByteOrder() == (getHostEndianness() == big)) {
    u.decodeRawUnpacked<16, big>(width, height);
  } else {
    if (hints.has("jpeg32_bitorder")) {
      u.readUncompressedRaw(mRaw->dim, pos, width * bps / 8, bps,
                            BitOrder_MSB32);
    } else {
      u.readUncompressedRaw(mRaw->dim, pos, width * bps / 8, bps, BitOrder_LSB);
    }
  }

  return mRaw;
}

void RafDecoder::checkSupportInternal(const CameraMetaData* meta) {
  if (!this->checkCameraSupported(meta, mRootIFD->getID(), ""))
    ThrowRDE("Unknown camera. Will not guess.");
}

void RafDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
  int iso = 0;
  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getU32();
  mRaw->metadata.isoSpeed = iso;

  // This is where we'd normally call setMetaData but since we may still need
  // to rotate the image for SuperCCD cameras we do everything ourselves
  auto id = mRootIFD->getID();
  const Camera* cam = meta->getCamera(id.make, id.model, "");
  if (!cam)
    ThrowRDE("Couldn't find camera");

  assert(cam != nullptr);

  iPoint2D new_size(mRaw->dim);
  iPoint2D crop_offset = iPoint2D(0,0);

  if (applyCrop) {
    new_size = cam->cropSize;
    crop_offset = cam->cropPos;
    bool double_width = hints.has("double_width_unpacked");
    // If crop size is negative, use relative cropping
    if (new_size.x <= 0)
      new_size.x = mRaw->dim.x / (double_width ? 2 : 1) - cam->cropPos.x + new_size.x;
    else
      new_size.x /= (double_width ? 2 : 1);
    if (new_size.y <= 0)
      new_size.y = mRaw->dim.y - cam->cropPos.y + new_size.y;
  }

  bool rotate = hints.has("fuji_rotate");
  rotate = rotate && fujiRotate;

  // Rotate 45 degrees - could be multithreaded.
  if (rotate && !this->uncorrectedRawValues) {
    // Calculate the 45 degree rotated size;
    uint32 rotatedsize;
    uint32 rotationPos;
    if (alt_layout) {
      rotatedsize = new_size.y+new_size.x/2;
      rotationPos = new_size.x/2 - 1;
    }
    else {
      rotatedsize = new_size.x+new_size.y/2;
      rotationPos = new_size.x - 1;
    }

    iPoint2D final_size(rotatedsize, rotatedsize-1);
    RawImage rotated = RawImage::create(final_size, TYPE_USHORT16, 1);
    rotated->clearArea(iRectangle2D(iPoint2D(0,0), rotated->dim));
    rotated->metadata = mRaw->metadata;
    rotated->metadata.fujiRotationPos = rotationPos;

    int dest_pitch = static_cast<int>(rotated->pitch) / 2;
    auto* dst = reinterpret_cast<ushort16*>(rotated->getData(0, 0));

    for (int y = 0; y < new_size.y; y++) {
      auto* src = reinterpret_cast<ushort16*>(
          mRaw->getData(crop_offset.x, crop_offset.y + y));
      for (int x = 0; x < new_size.x; x++) {
        int h;
        int w;
        if (alt_layout) { // Swapped x and y
          h = rotatedsize - (new_size.y + 1 - y + (x >> 1));
          w = ((x+1) >> 1) + y;
        } else {
          h = new_size.x - 1 - x + (y >> 1);
          w = ((y+1) >> 1) + x;
        }
        if (h < rotated->dim.y && w < rotated->dim.x)
          dst[w + h * dest_pitch] = src[x];
        else
          ThrowRDE("Trying to write out of bounds");
      }
    }
    mRaw = rotated;
  } else if (applyCrop) {
    mRaw->subFrame(iRectangle2D(crop_offset, new_size));
  }

  const CameraSensorInfo *sensor = cam->getSensorInfo(iso);
  mRaw->blackLevel = sensor->mBlackLevel;

  // at least the (bayer sensor) X100 comes with a tag like this:
  if (mRootIFD->hasEntryRecursive(FUJI_BLACKLEVEL)) {
    TiffEntry* sep_black = mRootIFD->getEntryRecursive(FUJI_BLACKLEVEL);
    if (sep_black->count == 4)
    {
      for(int k=0;k<4;k++)
        mRaw->blackLevelSeparate[k] = sep_black->getU32(k);
    } else if (sep_black->count == 36) {
      for (int& k : mRaw->blackLevelSeparate)
        k = 0;

      for (int y = 0; y < 6; y++) {
        for (int x = 0; x < 6; x++)
          mRaw->blackLevelSeparate[2 * (y % 2) + (x % 2)] +=
              sep_black->getU32(6 * y + x);
      }

      for (int& k : mRaw->blackLevelSeparate)
        k /= 9;
    }
  }

  mRaw->whitePoint = sensor->mWhiteLevel;
  mRaw->blackAreas = cam->blackAreas;
  mRaw->cfa = cam->cfa;
  mRaw->metadata.canonical_make = cam->canonical_make;
  mRaw->metadata.canonical_model = cam->canonical_model;
  mRaw->metadata.canonical_alias = cam->canonical_alias;
  mRaw->metadata.canonical_id = cam->canonical_id;
  mRaw->metadata.make = id.make;
  mRaw->metadata.model = id.model;

  if (mRootIFD->hasEntryRecursive(FUJI_WB_GRBLEVELS)) {
    TiffEntry *wb = mRootIFD->getEntryRecursive(FUJI_WB_GRBLEVELS);
    if (wb->count == 3) {
      mRaw->metadata.wbCoeffs[0] = wb->getFloat(1);
      mRaw->metadata.wbCoeffs[1] = wb->getFloat(0);
      mRaw->metadata.wbCoeffs[2] = wb->getFloat(2);
    }
  } else if (mRootIFD->hasEntryRecursive(FUJIOLDWB)) {
    TiffEntry *wb = mRootIFD->getEntryRecursive(FUJIOLDWB);
    if (wb->count == 8) {
      mRaw->metadata.wbCoeffs[0] = wb->getFloat(1);
      mRaw->metadata.wbCoeffs[1] = wb->getFloat(0);
      mRaw->metadata.wbCoeffs[2] = wb->getFloat(3);
    }
  }
}

} // namespace rawspeed
<commit_msg>RafDecoder::decodeRawInternal(): check w/h before doing anything<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2014-2015 Pedro Côrte-Real

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decoders/RafDecoder.h"
#include "common/Common.h"                          // for uint32, ushort16
#include "common/Point.h"                           // for iPoint2D, iRecta...
#include "decoders/RawDecoderException.h"           // for RawDecoderExcept...
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
#include "io/Buffer.h"                              // for Buffer
#include "io/ByteStream.h"                          // for ByteStream
#include "io/Endianness.h"                          // for getHostEndianness
#include "metadata/BlackArea.h"                     // for BlackArea
#include "metadata/Camera.h"                        // for Camera, Hints
#include "metadata/CameraMetaData.h"                // for CameraMetaData
#include "metadata/CameraSensorInfo.h"              // for CameraSensorInfo
#include "metadata/ColorFilterArray.h"              // for ColorFilterArray
#include "tiff/TiffEntry.h"                         // for TiffEntry
#include "tiff/TiffIFD.h"                           // for TiffRootIFD, Tif...
#include "tiff/TiffTag.h"                           // for TiffTag::FUJIOLDWB
#include <cassert>                                  // for assert
#include <cstdio>                                   // for size_t
#include <cstring>                                  // for memcmp
#include <memory>                                   // for unique_ptr, allo...
#include <string>                                   // for string
#include <vector>                                   // for vector

namespace rawspeed {

bool RafDecoder::isRAF(const Buffer* input) {
  static const char magic[] = "FUJIFILMCCD-RAW ";
  static const size_t magic_size = sizeof(magic) - 1; // excluding \0
  const unsigned char* data = input->getData(0, magic_size);
  return 0 == memcmp(&data[0], magic, magic_size);
}

bool RafDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD,
                                      const Buffer* file) {
  const auto id = rootIFD->getID();
  const std::string& make = id.make;

  // FIXME: magic

  return make == "FUJIFILM";
}

RawImage RafDecoder::decodeRawInternal() {
  auto raw = mRootIFD->getIFDWithTag(FUJI_STRIPOFFSETS);
  uint32 height = 0;
  uint32 width = 0;

  if (raw->hasEntry(FUJI_RAWIMAGEFULLHEIGHT)) {
    height = raw->getEntry(FUJI_RAWIMAGEFULLHEIGHT)->getU32();
    width = raw->getEntry(FUJI_RAWIMAGEFULLWIDTH)->getU32();
  } else if (raw->hasEntry(IMAGEWIDTH)) {
    TiffEntry *e = raw->getEntry(IMAGEWIDTH);
    height = e->getU16(0);
    width = e->getU16(1);
  } else
    ThrowRDE("Unable to locate image size");

  if (height < 1 || width < 1)
    ThrowRDE("Bad image dimensions");

  if (raw->hasEntry(FUJI_LAYOUT)) {
    TiffEntry *e = raw->getEntry(FUJI_LAYOUT);
    alt_layout = !(e->getByte(0) >> 7);
  }

  TiffEntry *offsets = raw->getEntry(FUJI_STRIPOFFSETS);
  TiffEntry *counts = raw->getEntry(FUJI_STRIPBYTECOUNTS);

  if (offsets->count != 1 || counts->count != 1)
    ThrowRDE("Multiple Strips found: %u %u", offsets->count, counts->count);

  if (counts->getU32() * 8 / (width * height) < 10)
    ThrowRDE("Don't know how to decode compressed images");

  ByteStream input(offsets->getRootIfdData());
  input = input.getSubStream(offsets->getU32(), counts->getU32());

  // x-trans sensors report 14bpp, but data isn't packed
  // thus, unless someone has any better ideas, let's autodetect it.
  int bps;

  // Some fuji SuperCCD cameras include a second raw image next to the first one
  // that is identical but darker to the first. The two combined can produce
  // a higher dynamic range image. Right now we're ignoring it.
  bool double_width;

  if (8UL * counts->getU32() >= 2UL * 16UL * width * height) {
    bps = 16;
    double_width = true;
  } else if (8UL * counts->getU32() >= 2UL * 14UL * width * height) {
    bps = 14;
    double_width = true;
  } else if (8UL * counts->getU32() >= 2UL * 12UL * width * height) {
    bps = 12;
    double_width = true;
  } else if (8UL * counts->getU32() >= 16UL * width * height) {
    bps = 16;
    double_width = false;
  } else if (8UL * counts->getU32() >= 14UL * width * height) {
    bps = 14;
    double_width = false;
  } else if (8UL * counts->getU32() >= 12UL * width * height) {
    bps = 12;
    double_width = false;
  } else {
    ThrowRDE("Can not detect bitdepth. StripByteCounts = %u, width = %u, "
             "height = %u",
             counts->getU32(), width, height);
  }

  double_width = hints.has("double_width_unpacked");
  const uint32 real_width = double_width ? 2U * width : width;

  mRaw->dim = iPoint2D(real_width, height);
  mRaw->createData();

  UncompressedDecompressor u(input, mRaw);

  iPoint2D pos(0, 0);

  if (double_width) {
    u.decodeRawUnpacked<16, little>(width * 2, height);
  } else if (input.isInNativeByteOrder() == (getHostEndianness() == big)) {
    u.decodeRawUnpacked<16, big>(width, height);
  } else {
    if (hints.has("jpeg32_bitorder")) {
      u.readUncompressedRaw(mRaw->dim, pos, width * bps / 8, bps,
                            BitOrder_MSB32);
    } else {
      u.readUncompressedRaw(mRaw->dim, pos, width * bps / 8, bps, BitOrder_LSB);
    }
  }

  return mRaw;
}

void RafDecoder::checkSupportInternal(const CameraMetaData* meta) {
  if (!this->checkCameraSupported(meta, mRootIFD->getID(), ""))
    ThrowRDE("Unknown camera. Will not guess.");
}

void RafDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
  int iso = 0;
  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getU32();
  mRaw->metadata.isoSpeed = iso;

  // This is where we'd normally call setMetaData but since we may still need
  // to rotate the image for SuperCCD cameras we do everything ourselves
  auto id = mRootIFD->getID();
  const Camera* cam = meta->getCamera(id.make, id.model, "");
  if (!cam)
    ThrowRDE("Couldn't find camera");

  assert(cam != nullptr);

  iPoint2D new_size(mRaw->dim);
  iPoint2D crop_offset = iPoint2D(0,0);

  if (applyCrop) {
    new_size = cam->cropSize;
    crop_offset = cam->cropPos;
    bool double_width = hints.has("double_width_unpacked");
    // If crop size is negative, use relative cropping
    if (new_size.x <= 0)
      new_size.x = mRaw->dim.x / (double_width ? 2 : 1) - cam->cropPos.x + new_size.x;
    else
      new_size.x /= (double_width ? 2 : 1);
    if (new_size.y <= 0)
      new_size.y = mRaw->dim.y - cam->cropPos.y + new_size.y;
  }

  bool rotate = hints.has("fuji_rotate");
  rotate = rotate && fujiRotate;

  // Rotate 45 degrees - could be multithreaded.
  if (rotate && !this->uncorrectedRawValues) {
    // Calculate the 45 degree rotated size;
    uint32 rotatedsize;
    uint32 rotationPos;
    if (alt_layout) {
      rotatedsize = new_size.y+new_size.x/2;
      rotationPos = new_size.x/2 - 1;
    }
    else {
      rotatedsize = new_size.x+new_size.y/2;
      rotationPos = new_size.x - 1;
    }

    iPoint2D final_size(rotatedsize, rotatedsize-1);
    RawImage rotated = RawImage::create(final_size, TYPE_USHORT16, 1);
    rotated->clearArea(iRectangle2D(iPoint2D(0,0), rotated->dim));
    rotated->metadata = mRaw->metadata;
    rotated->metadata.fujiRotationPos = rotationPos;

    int dest_pitch = static_cast<int>(rotated->pitch) / 2;
    auto* dst = reinterpret_cast<ushort16*>(rotated->getData(0, 0));

    for (int y = 0; y < new_size.y; y++) {
      auto* src = reinterpret_cast<ushort16*>(
          mRaw->getData(crop_offset.x, crop_offset.y + y));
      for (int x = 0; x < new_size.x; x++) {
        int h;
        int w;
        if (alt_layout) { // Swapped x and y
          h = rotatedsize - (new_size.y + 1 - y + (x >> 1));
          w = ((x+1) >> 1) + y;
        } else {
          h = new_size.x - 1 - x + (y >> 1);
          w = ((y+1) >> 1) + x;
        }
        if (h < rotated->dim.y && w < rotated->dim.x)
          dst[w + h * dest_pitch] = src[x];
        else
          ThrowRDE("Trying to write out of bounds");
      }
    }
    mRaw = rotated;
  } else if (applyCrop) {
    mRaw->subFrame(iRectangle2D(crop_offset, new_size));
  }

  const CameraSensorInfo *sensor = cam->getSensorInfo(iso);
  mRaw->blackLevel = sensor->mBlackLevel;

  // at least the (bayer sensor) X100 comes with a tag like this:
  if (mRootIFD->hasEntryRecursive(FUJI_BLACKLEVEL)) {
    TiffEntry* sep_black = mRootIFD->getEntryRecursive(FUJI_BLACKLEVEL);
    if (sep_black->count == 4)
    {
      for(int k=0;k<4;k++)
        mRaw->blackLevelSeparate[k] = sep_black->getU32(k);
    } else if (sep_black->count == 36) {
      for (int& k : mRaw->blackLevelSeparate)
        k = 0;

      for (int y = 0; y < 6; y++) {
        for (int x = 0; x < 6; x++)
          mRaw->blackLevelSeparate[2 * (y % 2) + (x % 2)] +=
              sep_black->getU32(6 * y + x);
      }

      for (int& k : mRaw->blackLevelSeparate)
        k /= 9;
    }
  }

  mRaw->whitePoint = sensor->mWhiteLevel;
  mRaw->blackAreas = cam->blackAreas;
  mRaw->cfa = cam->cfa;
  mRaw->metadata.canonical_make = cam->canonical_make;
  mRaw->metadata.canonical_model = cam->canonical_model;
  mRaw->metadata.canonical_alias = cam->canonical_alias;
  mRaw->metadata.canonical_id = cam->canonical_id;
  mRaw->metadata.make = id.make;
  mRaw->metadata.model = id.model;

  if (mRootIFD->hasEntryRecursive(FUJI_WB_GRBLEVELS)) {
    TiffEntry *wb = mRootIFD->getEntryRecursive(FUJI_WB_GRBLEVELS);
    if (wb->count == 3) {
      mRaw->metadata.wbCoeffs[0] = wb->getFloat(1);
      mRaw->metadata.wbCoeffs[1] = wb->getFloat(0);
      mRaw->metadata.wbCoeffs[2] = wb->getFloat(2);
    }
  } else if (mRootIFD->hasEntryRecursive(FUJIOLDWB)) {
    TiffEntry *wb = mRootIFD->getEntryRecursive(FUJIOLDWB);
    if (wb->count == 8) {
      mRaw->metadata.wbCoeffs[0] = wb->getFloat(1);
      mRaw->metadata.wbCoeffs[1] = wb->getFloat(0);
      mRaw->metadata.wbCoeffs[2] = wb->getFloat(3);
    }
  }
}

} // namespace rawspeed
<|endoftext|>


<commit_before>#include "description.h"

#include <sstream>

namespace possumwood {

namespace {

bool starts_with(const std::string& str, const std::string& prefix) {
	if(str.length() < prefix.length())
		return false;

	auto it1 = str.begin();
	auto it2 = prefix.begin();

	while(it2 != prefix.end()) {
		if(*it1 != *it2)
			return false;

		++it1;
		++it2;
	}

	return true;
}

}

Description::Description(const std::string& md) : m_markDown(md) {
}

void Description::clear() {
	m_markDown = "(empty description)";
}

void Description::setMarkdown(const std::string& md) {
	m_markDown = md;
}

const std::string& Description::markdown() const {
	return m_markDown;
}

std::string Description::html() const {
	std::stringstream ss(m_markDown);

	std::string result;

	while(ss.good()) {
		std::string line;
		std::getline(ss, line);

		if(starts_with(line, "# "))
			line = "
" + line.substr(2) + "
\n";
		else if(starts_with(line, "## "))
			line = "
" + line.substr(3) + "
\n";
		else if(starts_with(line, "### "))
			line = "
" + line.substr(4) + "
\n";
		else if(starts_with(line, "#### "))
			line = "
" + line.substr(5) + "
\n";
		else if(!line.empty())
			line = "
" + line + "
\n";

		{
			std::string link_text, link;
			int state = 0;
			std::size_t start = 0;
			std::size_t bracket_counter = 0;

			for(std::size_t i=0; i<line.length(); ++i) {
				switch(state) {
					case 0:
						if(line[i] == '[') {
							state = 1;
							start = i;
						}
						break;

					case 1:
						if(line[i] == ']')
							state = 2;
						else
							link_text += line[i];
						break;

					case 2:
						if(line[i] == '(') {
							state = 3;
							bracket_counter = 1;
						}
						else
							state = 0;
						break;

					case 3:
						if(line[i] == '(')
							bracket_counter++;
						else if(line[i] == ')')
							bracket_counter--;

						if(bracket_counter == 0)
							state = 4;
						else
							link += line[i];
						break;

					case 4:
						line = line.substr(0, start) + "" + link_text + "" + line.substr(i);
						i = 0;
						state = 0;
						link = "";
						link_text = "";
						break;
				};
			}
		}

		{
			int state = 0;
			for(std::size_t i=0; i<line.length(); ++i) {
				switch(state) {
					case 0:
						if(line[i] == '`') {
							line = line.substr(0, i) + "" + line.substr(i+1);
							state = 1;
						}
						break;
					case 1:
						if(line[i] == '`') {
							line = line.substr(0, i) + "" + line.substr(i+1);
							state = 0;
						}
						break;
				}
			}
		}

		result += line;
	}

	return result;
}

std::string Description::serialize() const {

	// std::stringstream ss;

	// for(auto c : m_markDown) {
	// 	if(c == '"')
	// 		ss << "\\\"";
	// 	else if(c == '\n')
	// 		ss << "\\n";
	// 	else if(c == '\r')
	// 		ss << "\\r";
	// 	else
	// 		ss << c;
	// }

	// return ss.str();

	return m_markDown;
}

void Description::deserialize(const std::string& s) {
	// std::string result;

	// auto it = s.begin();
	// while(it != s.end()) {
	// 	if(*it == '\\') {
	// 		++it;
	// 		if(it != s.end()) {
	// 			if(*it == 'n')
	// 				result += '\n';
	// 			else if(*it == 'r')
	// 				result += '\r';
	// 			else if(*it == '"')
	// 				result += '"';
	// 			else
	// 				result += "\\" + *it;
	// 		}
	// 	}
	// 	else
	// 		result += *it;

	// 	++it;
	// }

	// m_markDown = result;

	m_markDown = s;
}

}
<commit_msg>Added support for *bold* in scene description<commit_after>#include "description.h"

#include <sstream>

namespace possumwood {

namespace {

bool starts_with(const std::string& str, const std::string& prefix) {
	if(str.length() < prefix.length())
		return false;

	auto it1 = str.begin();
	auto it2 = prefix.begin();

	while(it2 != prefix.end()) {
		if(*it1 != *it2)
			return false;

		++it1;
		++it2;
	}

	return true;
}

}

Description::Description(const std::string& md) : m_markDown(md) {
}

void Description::clear() {
	m_markDown = "(empty description)";
}

void Description::setMarkdown(const std::string& md) {
	m_markDown = md;
}

const std::string& Description::markdown() const {
	return m_markDown;
}

std::string Description::html() const {
	std::stringstream ss(m_markDown);

	std::string result;

	while(ss.good()) {
		std::string line;
		std::getline(ss, line);

		if(starts_with(line, "# "))
			line = "
" + line.substr(2) + "
\n";
		else if(starts_with(line, "## "))
			line = "
" + line.substr(3) + "
\n";
		else if(starts_with(line, "### "))
			line = "
" + line.substr(4) + "
\n";
		else if(starts_with(line, "#### "))
			line = "
" + line.substr(5) + "
\n";
		else if(!line.empty())
			line = "
" + line + "
\n";

		{
			std::string link_text, link;
			int state = 0;
			std::size_t start = 0;
			std::size_t bracket_counter = 0;

			for(std::size_t i=0; i<line.length(); ++i) {
				switch(state) {
					case 0:
						if(line[i] == '[') {
							state = 1;
							start = i;
						}
						break;

					case 1:
						if(line[i] == ']')
							state = 2;
						else
							link_text += line[i];
						break;

					case 2:
						if(line[i] == '(') {
							state = 3;
							bracket_counter = 1;
						}
						else
							state = 0;
						break;

					case 3:
						if(line[i] == '(')
							bracket_counter++;
						else if(line[i] == ')')
							bracket_counter--;

						if(bracket_counter == 0)
							state = 4;
						else
							link += line[i];
						break;

					case 4:
						line = line.substr(0, start) + "" + link_text + "" + line.substr(i);
						i = 0;
						state = 0;
						link = "";
						link_text = "";
						break;
				};
			}
		}

		{
			int state = 1;
			for(std::size_t i=0; i<line.length(); ++i) {
				switch(state) {
					case 0:
						if(line[i] == ' ' || line[i] == '\r' || line[i] == '\n' || line[i] == '\t')
							state = 1;
						break;
					case 1:
						if(line[i] == '`') {
							line = line.substr(0, i) + "" + line.substr(i+1);
							state = 1;
						}
						if(line[i] == '*') {
							line = line.substr(0, i) + "" + line.substr(i+1);
							state = 3;
						}
						break;
					case 2:
						if(line[i] == '`') {
							line = line.substr(0, i) + "" + line.substr(i+1);
							state = 0;
						}
						break;
					case 3:
						if(line[i] == '*') {
							line = line.substr(0, i) + "" + line.substr(i+1);
							state = 0;
						}
						break;
				}
			}
		}

		result += line;
	}

	return result;
}

std::string Description::serialize() const {

	// std::stringstream ss;

	// for(auto c : m_markDown) {
	// 	if(c == '"')
	// 		ss << "\\\"";
	// 	else if(c == '\n')
	// 		ss << "\\n";
	// 	else if(c == '\r')
	// 		ss << "\\r";
	// 	else
	// 		ss << c;
	// }

	// return ss.str();

	return m_markDown;
}

void Description::deserialize(const std::string& s) {
	// std::string result;

	// auto it = s.begin();
	// while(it != s.end()) {
	// 	if(*it == '\\') {
	// 		++it;
	// 		if(it != s.end()) {
	// 			if(*it == 'n')
	// 				result += '\n';
	// 			else if(*it == 'r')
	// 				result += '\r';
	// 			else if(*it == '"')
	// 				result += '"';
	// 			else
	// 				result += "\\" + *it;
	// 		}
	// 	}
	// 	else
	// 		result += *it;

	// 	++it;
	// }

	// m_markDown = result;

	m_markDown = s;
}

}
<|endoftext|>


<commit_before>#include "Button.h"

void Button::setState(State state)
{
    state_ = state;
}

void Button::fireOnClicked()
{
    onClicked_();
}

void Button::transition()
{
    switch (getState()) {
    case State::LEFT:
        if (getShape().mouseOver && !getShape().leftPressed) {
            state_ = State::MOUSE_OVER;
        }
        break;
    case State::MOUSE_OVER:
        if (getShape().leftPressed) {
            state_ = State::PRESSED;
        }
        else if (!getShape().mouseOver) {
            state_ = State::LEFT;
        }
        break;
    case State::PRESSED:
        if (!getShape().mouseOver) {
            state_ = State::LEFT;
        }
        else if (getShape().leftReleased) {
            state_ = State::RELEASED;
        }
        break;
    case State::RELEASED:
        state_ = State::MOUSE_OVER;
        break;
    default:
        break;
    }
}

ButtonBuilder Button::builder()
{
    return ButtonBuilder();
}

void Button::draw() const
{
    if (view_ != nullptr) {
        switch (getState()) {
        case ButtonInterface::State::LEFT:
            view_->drawLeft();
            break;
        case ButtonInterface::State::MOUSE_OVER:
            view_->drawMouseOver();
            break;
        case ButtonInterface::State::PRESSED:
            view_->drawPressed();
            break;
        case ButtonInterface::State::RELEASED:
            view_->drawReleased();
            break;
        default:
            break;
        }
    }
}

ButtonInterface::State Button::getState() const
{
    return state_;
}

Shape const &Button::getShape() const
{
    return shape_;
}
<commit_msg>Buttonクラスを編集<commit_after>#include "Button.h"

void Button::setState(State state)
{
    state_ = state;
}

void Button::fireOnClicked()
{
    onClicked_();
}

void Button::transition()
{
    switch (getState()) {
    case State::LEFT:
        if (getShape().mouseOver && !getShape().leftPressed) {
            setState(State::MOUSE_OVER);
        }
        break;
    case State::MOUSE_OVER:
        if (getShape().leftPressed) {
            setState(State::PRESSED);
        }
        else if (!getShape().mouseOver) {
            setState(State::LEFT);
        }
        break;
    case State::PRESSED:
        if (!getShape().mouseOver) {
            setState(State::LEFT);
        }
        else if (getShape().leftReleased) {
            setState(State::RELEASED);
        }
        break;
    case State::RELEASED:
        setState(State::MOUSE_OVER);
        break;
    default:
        break;
    }
}

ButtonBuilder Button::builder()
{
    return ButtonBuilder();
}

void Button::draw() const
{
    if (view_ != nullptr) {
        switch (getState()) {
        case ButtonInterface::State::LEFT:
            view_->drawLeft();
            break;
        case ButtonInterface::State::MOUSE_OVER:
            view_->drawMouseOver();
            break;
        case ButtonInterface::State::PRESSED:
            view_->drawPressed();
            break;
        case ButtonInterface::State::RELEASED:
            view_->drawReleased();
            break;
        default:
            break;
        }
    }
}

ButtonInterface::State Button::getState() const
{
    return state_;
}

Shape const &Button::getShape() const
{
    return shape_;
}
<|endoftext|>