<commit_before>// Copyright (c) 2010 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_input_controller.h"
#include "media/base/limits.h"

namespace {

const int kMaxInputChannels = 2;

}  // namespace

namespace media {

// static
AudioInputController::Factory* AudioInputController::factory_ = NULL;

AudioInputController::AudioInputController(EventHandler* handler)
    : handler_(handler),
      stream_(NULL),
      state_(kEmpty),
      thread_("AudioInputControllerThread") {
}

AudioInputController::~AudioInputController() {
  DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_);
}

// static
scoped_refptr<AudioInputController> AudioInputController::Create(
    EventHandler* event_handler,
    AudioParameters params) {
  if (!params.IsValid() || (params.channels > kMaxInputChannels))
    return NULL;

  if (factory_) {
    return factory_->Create(event_handler, params);
  }

  scoped_refptr<AudioInputController> controller(new AudioInputController(
      event_handler));

  // Start the thread and post a task to create the audio input stream.
  controller->thread_.Start();
  controller->thread_.message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(controller.get(), &AudioInputController::DoCreate,
                        params));
  return controller;
}

void AudioInputController::Record() {
  DCHECK(thread_.IsRunning());
  thread_.message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &AudioInputController::DoRecord));
}

void AudioInputController::Close() {
  if (!thread_.IsRunning()) {
    // If the thread is not running make sure we are stopped.
    DCHECK_EQ(kClosed, state_);
    return;
  }

  // Wait for all tasks to complete on the audio thread.
  thread_.message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &AudioInputController::DoClose));
  thread_.Stop();
}

void AudioInputController::DoCreate(AudioParameters params) {
  stream_ = AudioManager::GetAudioManager()->MakeAudioInputStream(params);

  if (!stream_) {
    // TODO(satish): Define error types.
    handler_->OnError(this, 0);
    return;
  }

  if (stream_ && !stream_->Open()) {<commit_msg>Set scoped IO access when closing the audio input thread to allow joining.<commit_after>// Copyright (c) 2010 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_input_controller.h"

#include "base/thread_restrictions.h"
#include "media/base/limits.h"

namespace {

const int kMaxInputChannels = 2;

}  // namespace

namespace media {

// static
AudioInputController::Factory* AudioInputController::factory_ = NULL;

AudioInputController::AudioInputController(EventHandler* handler)
    : handler_(handler),
      stream_(NULL),
      state_(kEmpty),
      thread_("AudioInputControllerThread") {
}

AudioInputController::~AudioInputController() {
  DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_);
}

// static
scoped_refptr<AudioInputController> AudioInputController::Create(
    EventHandler* event_handler,
    AudioParameters params) {
  if (!params.IsValid() || (params.channels > kMaxInputChannels))
    return NULL;

  if (factory_) {
    return factory_->Create(event_handler, params);
  }

  scoped_refptr<AudioInputController> controller(new AudioInputController(
      event_handler));

  // Start the thread and post a task to create the audio input stream.
  controller->thread_.Start();
  controller->thread_.message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(controller.get(), &AudioInputController::DoCreate,
                        params));
  return controller;
}

void AudioInputController::Record() {
  DCHECK(thread_.IsRunning());
  thread_.message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &AudioInputController::DoRecord));
}

void AudioInputController::Close() {
  if (!thread_.IsRunning()) {
    // If the thread is not running make sure we are stopped.
    DCHECK_EQ(kClosed, state_);
    return;
  }

  // Wait for all tasks to complete on the audio thread.
  thread_.message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &AudioInputController::DoClose));

  // A ScopedAllowIO object is required to join the thread when calling Stop.
  // This is because as joining threads may be a long operation it's now
  // not allowed in threads without IO access, which is the case of the IO
  // thread (it is missnamed) being used here. This object overrides
  // temporarily this restriction and should be used only in specific
  // infrequent cases where joining is guaranteed to be fast.
  // Bug: http://code.google.com/p/chromium/issues/detail?id=67806
  base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join;
  thread_.Stop();
}

void AudioInputController::DoCreate(AudioParameters params) {
  stream_ = AudioManager::GetAudioManager()->MakeAudioInputStream(params);

  if (!stream_) {
    // TODO(satish): Define error types.
    handler_->OnError(this, 0);
    return;
  }

  if (stream_ && !stream_->Open()) {
{'fraction_non_alphanumeric': 0.11181072314443809, 'fraction_numerical': 0.003243655790879603, 'mean_word_length': 4.149312377210216, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3613934', 'n_tokens_mistral': 1498, 'n_tokens_neox': 1468, 'n_words': 402}