<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 "chrome/browser/ui/webui/task_manager_handler.h"

#include <algorithm>
#include <functional>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/browser/ui/webui/web_ui_util.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_view_host_delegate.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/webpreferences.h"

namespace {

Value* CreateColumnValue(const TaskManagerModel* tm,
                         const std::string& column_name,
                         const int i) {
  if (column_name == "uniqueId")
    return Value::CreateIntegerValue(tm->GetResourceUniqueId(i));
  if (column_name == "type")
    return Value::CreateStringValue(
        TaskManager::Resource::GetResourceTypeAsString(
        tm->GetResourceType(i)));
  if (column_name == "processId")
    return Value::CreateStringValue(tm->GetResourceProcessId(i));
  if (column_name == "processIdValue")
    return Value::CreateIntegerValue(tm->GetProcessId(i));
  if (column_name == "cpuUsage")
    return Value::CreateStringValue(tm->GetResourceCPUUsage(i));
  if (column_name == "cpuUsageValue")
    return Value::CreateDoubleValue(tm->GetCPUUsage(i));
  if (column_name == "privateMemory")
    return Value::CreateStringValue(tm->GetResourcePrivateMemory(i));
  if (column_name == "privateMemoryValue") {
    size_t private_memory;
    tm->GetPrivateMemory(i, &private_memory);
    return Value::CreateDoubleValue(private_memory);
  }
  if (column_name == "sharedMemory")
    return Value::CreateStringValue(tm->GetResourceSharedMemory(i));
  if (column_name == "sharedMemoryValue") {
    size_t shared_memory;
    tm->GetSharedMemory(i, &shared_memory);
    return Value::CreateDoubleValue(shared_memory);
  }
  if (column_name == "physicalMemory")
    return Value::CreateStringValue(tm->GetResourcePhysicalMemory(i));
  if (column_name == "physicalMemoryValue") {
    size_t physical_memory;
    tm->GetPhysicalMemory(i, &physical_memory);
    return Value::CreateDoubleValue(physical_memory);
  }
  if (column_name == "icon")
    return Value::CreateStringValue(
               web_ui_util::GetImageDataUrl(tm->GetResourceIcon(i)));
  if (column_name == "title")
    return Value::CreateStringValue(tm->GetResourceTitle(i));
  if (column_name == "profileName")
    return Value::CreateStringValue(tm->GetResourceProfileName(i));
  if (column_name == "networkUsage")
    return Value::CreateStringValue(tm->GetResourceNetworkUsage(i));
  if (column_name == "networkUsageValue")
    return Value::CreateDoubleValue(tm->GetNetworkUsage(i));
  if (column_name == "webCoreImageCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreImageCacheSize(i));
  if (column_name == "webCoreImageCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.images.size);
  }
  if (column_name == "webCoreScriptsCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreScriptsCacheSize(i));
  if (column_name == "webCoreScriptsCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.scripts.size);
  }
  if (column_name == "webCoreCSSCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreCSSCacheSize(i));
  if (column_name == "webCoreCSSCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.cssStyleSheets.size);
  }
  if (column_name == "fps")
    return Value::CreateStringValue(tm->GetResourceFPS(i));
  if (column_name == "fpsValue") {
    float fps;
    tm->GetFPS(i, &fps);
    return Value::CreateDoubleValue(fps);
  }
  if (column_name == "sqliteMemoryUsed")
    return Value::CreateStringValue(tm->GetResourceSqliteMemoryUsed(i));
  if (column_name == "sqliteMemoryUsedValue") {
    size_t sqlite_memory;
    tm->GetSqliteMemoryUsedBytes(i, &sqlite_memory);
    return Value::CreateDoubleValue(sqlite_memory);
  }
  if (column_name == "goatsTeleported")
    return Value::CreateStringValue(tm->GetResourceGoatsTeleported(i));
  if (column_name == "goatsTeleportedValue")
    return Value::CreateIntegerValue(tm->GetGoatsTeleported(i));
  if (column_name == "v8MemoryAllocatedSize")
    return Value::CreateStringValue(tm->GetResourceV8MemoryAllocatedSize(i));
  if (column_name == "v8MemoryAllocatedSizeValue") {
    size_t v8_memory;
    tm->GetV8Memory(i, &v8_memory);
    return Value::CreateDoubleValue(v8_memory);
  }
  if (column_name == "canInspect")
    return Value::CreateBooleanValue(tm->CanInspect(i));
  if (column_name == "canActivate")
    return Value::CreateBooleanValue(tm->CanActivate(i));

  NOTREACHED();
  return NULL;
}

void CreateGroupColumnList(const TaskManagerModel* tm,
                           const std::string& column_name,
                           const int index,
                           const int length,
                           DictionaryValue* val) {
  ListValue* list = new ListValue();
  for (int i = index; i < (index + length); ++i) {
    list->Append(CreateColumnValue(tm, column_name, i));
  }
  val->Set(column_name, list);
}

struct ColumnType {
  const char* column_id;
  // Whether the column has the real value separately or not, instead of the
  // formatted value to display.
  const bool has_real_value;
  // Whether the column has single datum or multiple data in each group.
  const bool has_multiple_data;
};

const ColumnType kColumnsList[] = {
  {"type", false, false},
  {"processId", true, false},
  {"cpuUsage", true, false},
  {"physicalMemory", true, false},
  {"sharedMemory", true, false},
  {"privateMemory", true, false},
  {"webCoreImageCacheSize", true, false},
  {"webCoreImageCacheSize", true, false},
  {"webCoreScriptsCacheSize", true, false},
  {"webCoreCSSCacheSize", true, false},
  {"sqliteMemoryUsed", true, false},
  {"v8MemoryAllocatedSize", true, false},
  {"icon", false, true},
  {"title", false, true},
  {"profileName", false, true},
  {"networkUsage", true, true},
  {"fps", true, true},
  {"goatsTeleported", true, true},
  {"canInspect", false, true},
  {"canActivate", false, true}
};

DictionaryValue* CreateTaskGroupValue(
    const TaskManagerModel* tm,
    const int group_index,
    const std::set<std::string>& columns) {
  DictionaryValue* val = new DictionaryValue();

  const int group_count = tm->GroupCount();
  if (group_index >= group_count)
     return val;

  int index = tm->GetResourceIndexForGroup(group_index, 0);
  int length = tm->GetGroupRangeForResource(index).second;

  // Forces to set following 3 columns regardless of |enable_columns|.
  val->SetInteger("index", index);
  val->SetBoolean("isBackgroundResource",
                  tm->IsBackgroundResource(index));
  CreateGroupColumnList(tm, "uniqueId", index, length, val);
  CreateGroupColumnList(tm, "processId", index, 1, val);

  for (size_t i = 0; i < arraysize(kColumnsList); ++i) {
    const std::string column_id = kColumnsList[i].column_id;

    if (columns.find(column_id) == columns.end())
      continue;

    int column_length = kColumnsList[i].has_multiple_data ? length : 1;
    CreateGroupColumnList(tm, column_id, index, column_length, val);

    if (kColumnsList[i].has_real_value)
      CreateGroupColumnList(tm, column_id + "Value", index, column_length, val);
  }

  return val;
}

}  // namespace

TaskManagerHandler::TaskManagerHandler(TaskManager* tm)
    : task_manager_(tm),
      model_(tm->model()),
      is_enabled_(false) {
}

TaskManagerHandler::~TaskManagerHandler() {
  DisableTaskManager(NULL);
}

// TaskManagerHandler, public: -----------------------------------------------

void TaskManagerHandler::OnModelChanged() {
  OnGroupChanged(0, model_->GroupCount());
}

void TaskManagerHandler::OnItemsChanged(const int start, const int length) {
  OnGroupChanged(0, model_->GroupCount());
}

void TaskManagerHandler::OnItemsAdded(const int start, const int length) {
}

void TaskManagerHandler::OnItemsRemoved(const int start, const int length) {
}

void TaskManagerHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback("killProcesses",
      base::Bind(&TaskManagerHandler::HandleKillProcesses,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("inspect",
      base::Bind(&TaskManagerHandler::HandleInspect,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("activatePage",
      base::Bind(&TaskManagerHandler::HandleActivatePage,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("openAboutMemory",
      base::Bind(&TaskManagerHandler::OpenAboutMemory,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("enableTaskManager",
      base::Bind(&TaskManagerHandler::EnableTaskManager,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("disableTaskManager",
      base::Bind(&TaskManagerHandler::DisableTaskManager,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setUpdateColumn",
      base::Bind(&TaskManagerHandler::HandleSetUpdateColumn,
                 base::Unretained(this)));
}

static int parseIndex(const Value* value) {
  int index = -1;
  string16 string16_index;
  double double_index;
  if (value->GetAsString(&string16_index)) {
    bool converted = base::StringToInt(string16_index, &index);
    DCHECK(converted);
  } else if (value->GetAsDouble(&double_index)) {
    index = static_cast<int>(double_index);
  } else {
    value->GetAsInteger(&index);
  }
  return index;
}

void TaskManagerHandler::HandleKillProcesses(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    task_manager_->KillProcess(resource_index);
  }
}

void TaskManagerHandler::HandleActivatePage(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    task_manager_->ActivateProcess(resource_index);
    break;
  }
}

void TaskManagerHandler::HandleInspect(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    if (model_->CanInspect(resource_index))
      model_->Inspect(resource_index);
    break;
  }
}

void TaskManagerHandler::DisableTaskManager(const ListValue* indexes) {
  if (!is_enabled_)
    return;

  is_enabled_ = false;
  model_->StopUpdating();
  model_->RemoveObserver(this);
}

void TaskManagerHandler::EnableTaskManager(const ListValue* indexes) {
  if (is_enabled_)
    return;

  is_enabled_ = true;

  OnGroupChanged(0, model_->GroupCount());

  model_->AddObserver(this);
  model_->StartUpdating();

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_TASK_MANAGER_WINDOW_READY,
      content::Source<TaskManagerModel>(model_),
      content::NotificationService::NoDetails());
}

void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
  RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
  if (rvh && rvh->delegate()) {
    WebPreferences webkit_prefs = rvh->delegate()->GetWebkitPrefs();
    webkit_prefs.allow_scripts_to_close_windows = true;
    rvh->UpdateWebkitPreferences(webkit_prefs);
  } else {
    DCHECK(false);
  }

  task_manager_->OpenAboutMemory();
}

void TaskManagerHandler::HandleSetUpdateColumn(const ListValue* args) {
  DCHECK_EQ(2U, args->GetSize());

  bool ret = true;
  std::string column_id;
  ret &= args->GetString(0, &column_id);
  bool is_enabled;
  ret &= args->GetBoolean(1, &is_enabled);
  DCHECK(ret);

  if (is_enabled)
    enabled_columns_.insert(column_id);
  else
    enabled_columns_.erase(column_id);
}

// TaskManagerHandler, private: -----------------------------------------------

bool TaskManagerHandler::is_alive() {
  return web_ui()->GetWebContents()->GetRenderViewHost() != NULL;
}

void TaskManagerHandler::OnGroupChanged(const int group_start,
                                        const int group_length) {
  base::FundamentalValue start_value(group_start);
  base::FundamentalValue length_value(group_length);
  base::ListValue tasks_value;

  for (int i = 0; i < group_length; ++i)
    tasks_value.Append(
        CreateTaskGroupValue(model_, group_start + i, enabled_columns_));

  if (is_enabled_ && is_alive()) {
    web_ui()->CallJavascriptFunction("taskChanged",
                                     start_value, length_value, tasks_value);
  }
}

void TaskManagerHandler::OnGroupAdded(const int group_start,
                                      const int group_length) {
}

void TaskManagerHandler::OnGroupRemoved(const int group_start,
                                        const int group_length) {
}

void TaskManagerHandler::OnReadyPeriodicalUpdate() {
}
<commit_msg>WebUI TaskManager: Make the button "End process" grayed on selecting the browser process.<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 "chrome/browser/ui/webui/task_manager_handler.h"

#include <algorithm>
#include <functional>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/browser/ui/webui/web_ui_util.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_view_host_delegate.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/webpreferences.h"

namespace {

Value* CreateColumnValue(const TaskManagerModel* tm,
                         const std::string& column_name,
                         const int i) {
  if (column_name == "uniqueId")
    return Value::CreateIntegerValue(tm->GetResourceUniqueId(i));
  if (column_name == "type")
    return Value::CreateStringValue(
        TaskManager::Resource::GetResourceTypeAsString(
        tm->GetResourceType(i)));
  if (column_name == "processId")
    return Value::CreateStringValue(tm->GetResourceProcessId(i));
  if (column_name == "processIdValue")
    return Value::CreateIntegerValue(tm->GetProcessId(i));
  if (column_name == "cpuUsage")
    return Value::CreateStringValue(tm->GetResourceCPUUsage(i));
  if (column_name == "cpuUsageValue")
    return Value::CreateDoubleValue(tm->GetCPUUsage(i));
  if (column_name == "privateMemory")
    return Value::CreateStringValue(tm->GetResourcePrivateMemory(i));
  if (column_name == "privateMemoryValue") {
    size_t private_memory;
    tm->GetPrivateMemory(i, &private_memory);
    return Value::CreateDoubleValue(private_memory);
  }
  if (column_name == "sharedMemory")
    return Value::CreateStringValue(tm->GetResourceSharedMemory(i));
  if (column_name == "sharedMemoryValue") {
    size_t shared_memory;
    tm->GetSharedMemory(i, &shared_memory);
    return Value::CreateDoubleValue(shared_memory);
  }
  if (column_name == "physicalMemory")
    return Value::CreateStringValue(tm->GetResourcePhysicalMemory(i));
  if (column_name == "physicalMemoryValue") {
    size_t physical_memory;
    tm->GetPhysicalMemory(i, &physical_memory);
    return Value::CreateDoubleValue(physical_memory);
  }
  if (column_name == "icon")
    return Value::CreateStringValue(
               web_ui_util::GetImageDataUrl(tm->GetResourceIcon(i)));
  if (column_name == "title")
    return Value::CreateStringValue(tm->GetResourceTitle(i));
  if (column_name == "profileName")
    return Value::CreateStringValue(tm->GetResourceProfileName(i));
  if (column_name == "networkUsage")
    return Value::CreateStringValue(tm->GetResourceNetworkUsage(i));
  if (column_name == "networkUsageValue")
    return Value::CreateDoubleValue(tm->GetNetworkUsage(i));
  if (column_name == "webCoreImageCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreImageCacheSize(i));
  if (column_name == "webCoreImageCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.images.size);
  }
  if (column_name == "webCoreScriptsCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreScriptsCacheSize(i));
  if (column_name == "webCoreScriptsCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.scripts.size);
  }
  if (column_name == "webCoreCSSCacheSize")
    return Value::CreateStringValue(tm->GetResourceWebCoreCSSCacheSize(i));
  if (column_name == "webCoreCSSCacheSizeValue") {
    WebKit::WebCache::ResourceTypeStats resource_stats;
    tm->GetWebCoreCacheStats(i, &resource_stats);
    return Value::CreateDoubleValue(resource_stats.cssStyleSheets.size);
  }
  if (column_name == "fps")
    return Value::CreateStringValue(tm->GetResourceFPS(i));
  if (column_name == "fpsValue") {
    float fps;
    tm->GetFPS(i, &fps);
    return Value::CreateDoubleValue(fps);
  }
  if (column_name == "sqliteMemoryUsed")
    return Value::CreateStringValue(tm->GetResourceSqliteMemoryUsed(i));
  if (column_name == "sqliteMemoryUsedValue") {
    size_t sqlite_memory;
    tm->GetSqliteMemoryUsedBytes(i, &sqlite_memory);
    return Value::CreateDoubleValue(sqlite_memory);
  }
  if (column_name == "goatsTeleported")
    return Value::CreateStringValue(tm->GetResourceGoatsTeleported(i));
  if (column_name == "goatsTeleportedValue")
    return Value::CreateIntegerValue(tm->GetGoatsTeleported(i));
  if (column_name == "v8MemoryAllocatedSize")
    return Value::CreateStringValue(tm->GetResourceV8MemoryAllocatedSize(i));
  if (column_name == "v8MemoryAllocatedSizeValue") {
    size_t v8_memory;
    tm->GetV8Memory(i, &v8_memory);
    return Value::CreateDoubleValue(v8_memory);
  }
  if (column_name == "canInspect")
    return Value::CreateBooleanValue(tm->CanInspect(i));
  if (column_name == "canActivate")
    return Value::CreateBooleanValue(tm->CanActivate(i));

  NOTREACHED();
  return NULL;
}

void CreateGroupColumnList(const TaskManagerModel* tm,
                           const std::string& column_name,
                           const int index,
                           const int length,
                           DictionaryValue* val) {
  ListValue* list = new ListValue();
  for (int i = index; i < (index + length); ++i) {
    list->Append(CreateColumnValue(tm, column_name, i));
  }
  val->Set(column_name, list);
}

struct ColumnType {
  const char* column_id;
  // Whether the column has the real value separately or not, instead of the
  // formatted value to display.
  const bool has_real_value;
  // Whether the column has single datum or multiple data in each group.
  const bool has_multiple_data;
};

const ColumnType kColumnsList[] = {
  {"type", false, false},
  {"processId", true, false},
  {"cpuUsage", true, false},
  {"physicalMemory", true, false},
  {"sharedMemory", true, false},
  {"privateMemory", true, false},
  {"webCoreImageCacheSize", true, false},
  {"webCoreImageCacheSize", true, false},
  {"webCoreScriptsCacheSize", true, false},
  {"webCoreCSSCacheSize", true, false},
  {"sqliteMemoryUsed", true, false},
  {"v8MemoryAllocatedSize", true, false},
  {"icon", false, true},
  {"title", false, true},
  {"profileName", false, true},
  {"networkUsage", true, true},
  {"fps", true, true},
  {"goatsTeleported", true, true},
  {"canInspect", false, true},
  {"canActivate", false, true}
};

DictionaryValue* CreateTaskGroupValue(
    const TaskManagerModel* tm,
    const int group_index,
    const std::set<std::string>& columns) {
  DictionaryValue* val = new DictionaryValue();

  const int group_count = tm->GroupCount();
  if (group_index >= group_count)
     return val;

  int index = tm->GetResourceIndexForGroup(group_index, 0);
  int length = tm->GetGroupRangeForResource(index).second;

  // Forces to set following 3 columns regardless of |enable_columns|.
  val->SetInteger("index", index);
  val->SetBoolean("isBackgroundResource",
                  tm->IsBackgroundResource(index));
  CreateGroupColumnList(tm, "processId", index, 1, val);
  CreateGroupColumnList(tm, "type", index, length, val);
  CreateGroupColumnList(tm, "uniqueId", index, length, val);

  for (size_t i = 0; i < arraysize(kColumnsList); ++i) {
    const std::string column_id = kColumnsList[i].column_id;

    if (columns.find(column_id) == columns.end())
      continue;

    int column_length = kColumnsList[i].has_multiple_data ? length : 1;
    CreateGroupColumnList(tm, column_id, index, column_length, val);

    if (kColumnsList[i].has_real_value)
      CreateGroupColumnList(tm, column_id + "Value", index, column_length, val);
  }

  return val;
}

}  // namespace

TaskManagerHandler::TaskManagerHandler(TaskManager* tm)
    : task_manager_(tm),
      model_(tm->model()),
      is_enabled_(false) {
}

TaskManagerHandler::~TaskManagerHandler() {
  DisableTaskManager(NULL);
}

// TaskManagerHandler, public: -----------------------------------------------

void TaskManagerHandler::OnModelChanged() {
  OnGroupChanged(0, model_->GroupCount());
}

void TaskManagerHandler::OnItemsChanged(const int start, const int length) {
  OnGroupChanged(0, model_->GroupCount());
}

void TaskManagerHandler::OnItemsAdded(const int start, const int length) {
}

void TaskManagerHandler::OnItemsRemoved(const int start, const int length) {
}

void TaskManagerHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback("killProcesses",
      base::Bind(&TaskManagerHandler::HandleKillProcesses,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("inspect",
      base::Bind(&TaskManagerHandler::HandleInspect,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("activatePage",
      base::Bind(&TaskManagerHandler::HandleActivatePage,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("openAboutMemory",
      base::Bind(&TaskManagerHandler::OpenAboutMemory,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("enableTaskManager",
      base::Bind(&TaskManagerHandler::EnableTaskManager,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("disableTaskManager",
      base::Bind(&TaskManagerHandler::DisableTaskManager,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setUpdateColumn",
      base::Bind(&TaskManagerHandler::HandleSetUpdateColumn,
                 base::Unretained(this)));
}

static int parseIndex(const Value* value) {
  int index = -1;
  string16 string16_index;
  double double_index;
  if (value->GetAsString(&string16_index)) {
    bool converted = base::StringToInt(string16_index, &index);
    DCHECK(converted);
  } else if (value->GetAsDouble(&double_index)) {
    index = static_cast<int>(double_index);
  } else {
    value->GetAsInteger(&index);
  }
  return index;
}

void TaskManagerHandler::HandleKillProcesses(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    task_manager_->KillProcess(resource_index);
  }
}

void TaskManagerHandler::HandleActivatePage(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    task_manager_->ActivateProcess(resource_index);
    break;
  }
}

void TaskManagerHandler::HandleInspect(const ListValue* unique_ids) {
  for (ListValue::const_iterator i = unique_ids->begin();
       i != unique_ids->end(); ++i) {
    int unique_id = parseIndex(*i);
    int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
    if (resource_index == -1)
      continue;

    if (model_->CanInspect(resource_index))
      model_->Inspect(resource_index);
    break;
  }
}

void TaskManagerHandler::DisableTaskManager(const ListValue* indexes) {
  if (!is_enabled_)
    return;

  is_enabled_ = false;
  model_->StopUpdating();
  model_->RemoveObserver(this);
}

void TaskManagerHandler::EnableTaskManager(const ListValue* indexes) {
  if (is_enabled_)
    return;

  is_enabled_ = true;

  OnGroupChanged(0, model_->GroupCount());

  model_->AddObserver(this);
  model_->StartUpdating();

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_TASK_MANAGER_WINDOW_READY,
      content::Source<TaskManagerModel>(model_),
      content::NotificationService::NoDetails());
}

void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
  RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
  if (rvh && rvh->delegate()) {
    WebPreferences webkit_prefs = rvh->delegate()->GetWebkitPrefs();
    webkit_prefs.allow_scripts_to_close_windows = true;
    rvh->UpdateWebkitPreferences(webkit_prefs);
  } else {
    DCHECK(false);
  }

  task_manager_->OpenAboutMemory();
}

void TaskManagerHandler::HandleSetUpdateColumn(const ListValue* args) {
  DCHECK_EQ(2U, args->GetSize());

  bool ret = true;
  std::string column_id;
  ret &= args->GetString(0, &column_id);
  bool is_enabled;
  ret &= args->GetBoolean(1, &is_enabled);
  DCHECK(ret);

  if (is_enabled)
    enabled_columns_.insert(column_id);
  else
    enabled_columns_.erase(column_id);
}

// TaskManagerHandler, private: -----------------------------------------------

bool TaskManagerHandler::is_alive() {
  return web_ui()->GetWebContents()->GetRenderViewHost() != NULL;
}

void TaskManagerHandler::OnGroupChanged(const int group_start,
                                        const int group_length) {
  base::FundamentalValue start_value(group_start);
  base::FundamentalValue length_value(group_length);
  base::ListValue tasks_value;

  for (int i = 0; i < group_length; ++i)
    tasks_value.Append(
        CreateTaskGroupValue(model_, group_start + i, enabled_columns_));

  if (is_enabled_ && is_alive()) {
    web_ui()->CallJavascriptFunction("taskChanged",
                                     start_value, length_value, tasks_value);
  }
}

void TaskManagerHandler::OnGroupAdded(const int group_start,
                                      const int group_length) {
}

void TaskManagerHandler::OnGroupRemoved(const int group_start,
                                        const int group_length) {
}

void TaskManagerHandler::OnReadyPeriodicalUpdate() {
}
<|endoftext|>


<commit_before>#pragma once

namespace rc {
namespace seq {

template<typename T>
std::size_t length(Seq<T> seq)
{
    std::size_t l = 0;
    while (seq.next())
        l++;

    return l;
}

template<typename T, typename Callable>
void forEach(Seq<T> seq, Callable callable)
{
    Maybe<T> value;
    while ((value = seq.next()))
        callable(*value);
}

} // namespace seq
} // namespace rc
<commit_msg>Move value in seq::forEach<commit_after>#pragma once

namespace rc {
namespace seq {

template<typename T>
std::size_t length(Seq<T> seq)
{
    std::size_t l = 0;
    while (seq.next())
        l++;

    return l;
}

template<typename T, typename Callable>
void forEach(Seq<T> seq, Callable callable)
{
    Maybe<T> value;
    while ((value = seq.next()))
        callable(std::move(*value));
}

} // namespace seq
} // namespace rc
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2016 ScyllaDB
 */

#pragma once

#include <seastar/core/future.hh>
#include <seastar/core/chunked_fifo.hh>
#include <stdexcept>
#include <exception>
#include <seastar/core/timer.hh>
#include <seastar/core/future-util.hh>
#include <seastar/core/lowres_clock.hh>

namespace seastar {

template<typename T>
struct dummy_expiry {
    void operator()(T&) noexcept {};
};

template<typename... T>
struct promise_expiry {
    void operator()(promise<T...>& pr) noexcept {
        pr.set_exception(std::make_exception_ptr(timed_out_error()));
    };
};

/// Container for elements with support for expiration of entries.
///
/// OnExpiry is a functor which will be called with a reference to T right before it expires.
/// T is removed and destroyed from the container immediately after OnExpiry returns.
/// OnExpiry callback must not modify the container, it can only modify its argument.
///
/// The container can only be moved before any elements are pushed.
///
template <typename T, typename OnExpiry = dummy_expiry<T>, typename Clock = lowres_clock>
class expiring_fifo {
public:
    using clock = Clock;
    using time_point = typename Clock::time_point;
private:
    struct entry {
        compat::optional<T> payload; // disengaged means that it's expired
        timer<Clock> tr;
        entry(T&& payload_) : payload(std::move(payload_)) {}
        entry(const T& payload_) : payload(payload_) {}
        entry(T payload_, expiring_fifo& ef, time_point timeout)
                : payload(std::move(payload_))
                , tr([this, &ef] {
                    ef._on_expiry(*payload);
                    payload = compat::nullopt;
                    --ef._size;
                    ef.drop_expired_front();
                })
        {
            tr.arm(timeout);
        }
        entry(entry&& x) = delete;
        entry(const entry& x) = delete;
    };

    // There is an invariant that the front element is never expired.
    chunked_fifo<entry> _list;
    OnExpiry _on_expiry;
    size_t _size = 0;

    // Ensures that front() is not expired by dropping expired elements from the front.
    void drop_expired_front() {
        while (!_list.empty() && !_list.front().payload) {
            _list.pop_front();
        }
    }
public:
    expiring_fifo() = default;
    expiring_fifo(OnExpiry on_expiry) : _on_expiry(std::move(on_expiry)) {}

    /// Checks if container contains any elements
    ///
    /// \note Inside OnExpiry callback, the expired element is still contained.
    ///
    /// \return true if and only if there are any elements contained.
    bool empty() const {
        return _size == 0;
    }

    /// Equivalent to !empty()
    explicit operator bool() const {
        return !empty();
    }

    /// Returns a reference to the element in the front.
    /// Valid only when !empty().
    T& front() {
        return *_list.front().payload;
    }

    /// Returns a reference to the element in the front.
    /// Valid only when !empty().
    const T& front() const {
        return *_list.front().payload;
    }

    /// Returns the number of elements contained.
    ///
    /// \note Expired elements are not contained. Expiring element is still contained when OnExpiry is called.
    size_t size() const {
        return _size;
    }

    /// Reserves storage in the container for at least 'size' elements.
    /// Note that expired elements may also take space when they are not in the front of the queue.
    ///
    /// Doesn't give any guarantees about exception safety of subsequent push_back().
    void reserve(size_t size) {
        return _list.reserve(size);
    }

    /// Adds element to the back of the queue.
    /// The element will never expire.
    void push_back(const T& payload) {
        _list.emplace_back(payload);
        ++_size;
    }

    /// Adds element to the back of the queue.
    /// The element will never expire.
    void push_back(T&& payload) {
        _list.emplace_back(std::move(payload));
        ++_size;
    }

    /// Adds element to the back of the queue.
    /// The element will expire when timeout is reached, unless it is time_point::max(), in which
    /// case it never expires.
    void push_back(T payload, time_point timeout) {
        if (timeout < time_point::max()) {
            _list.emplace_back(std::move(payload), *this, timeout);
        } else {
            _list.emplace_back(std::move(payload));
        }
        ++_size;
    }

    /// Removes the element at the front.
    /// Can be called only if !empty().
    void pop_front() {
        _list.pop_front();
        --_size;
        drop_expired_front();
    }
};

}
<commit_msg>expiring_fifo: Optimize memory usage for single-element lists<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2016 ScyllaDB
 */

#pragma once

#include <seastar/core/future.hh>
#include <seastar/core/chunked_fifo.hh>
#include <stdexcept>
#include <exception>
#include <memory>
#include <seastar/core/timer.hh>
#include <seastar/core/future-util.hh>
#include <seastar/core/lowres_clock.hh>

namespace seastar {

template<typename T>
struct dummy_expiry {
    void operator()(T&) noexcept {};
};

template<typename... T>
struct promise_expiry {
    void operator()(promise<T...>& pr) noexcept {
        pr.set_exception(std::make_exception_ptr(timed_out_error()));
    };
};

/// Container for elements with support for expiration of entries.
///
/// OnExpiry is a functor which will be called with a reference to T right before it expires.
/// T is removed and destroyed from the container immediately after OnExpiry returns.
/// OnExpiry callback must not modify the container, it can only modify its argument.
///
/// The container can only be moved before any elements are pushed.
///
template <typename T, typename OnExpiry = dummy_expiry<T>, typename Clock = lowres_clock>
class expiring_fifo {
public:
    using clock = Clock;
    using time_point = typename Clock::time_point;
private:
    struct entry {
        compat::optional<T> payload; // disengaged means that it's expired
        timer<Clock> tr;
        entry(T&& payload_) : payload(std::move(payload_)) {}
        entry(const T& payload_) : payload(payload_) {}
        entry(T payload_, expiring_fifo& ef, time_point timeout)
                : payload(std::move(payload_))
                , tr([this, &ef] {
                    ef._on_expiry(*payload);
                    payload = compat::nullopt;
                    --ef._size;
                    ef.drop_expired_front();
                })
        {
            tr.arm(timeout);
        }
        entry(entry&& x) = delete;
        entry(const entry& x) = delete;
    };

    // If engaged, represents the first element.
    // This is to avoid large allocations done by chunked_fifo for single-element cases.
    // expiring_fifo is used to implement wait lists in synchronization primitives
    // and in some uses it's common to have at most one waiter.
    std::unique_ptr<entry> _front;

    // There is an invariant that the front element is never expired.
    chunked_fifo<entry> _list;
    OnExpiry _on_expiry;
    size_t _size = 0;

    // Ensures that front() is not expired by dropping expired elements from the front.
    void drop_expired_front() {
        while (!_list.empty() && !_list.front().payload) {
            _list.pop_front();
        }
        if (_front && !_front->payload) {
            _front.reset();
        }
    }
public:
    expiring_fifo() = default;
    expiring_fifo(OnExpiry on_expiry) : _on_expiry(std::move(on_expiry)) {}

    expiring_fifo(expiring_fifo&& o) noexcept
            : expiring_fifo() {
        // entry objects hold a reference to this so non-empty containers cannot be moved.
        assert(o._size == 0);
    }

    /// Checks if container contains any elements
    ///
    /// \note Inside OnExpiry callback, the expired element is still contained.
    ///
    /// \return true if and only if there are any elements contained.
    bool empty() const {
        return _size == 0;
    }

    /// Equivalent to !empty()
    explicit operator bool() const {
        return !empty();
    }

    /// Returns a reference to the element in the front.
    /// Valid only when !empty().
    T& front() {
        if (_front) {
            return *_front->payload;
        }
        return *_list.front().payload;
    }

    /// Returns a reference to the element in the front.
    /// Valid only when !empty().
    const T& front() const {
        if (_front) {
            return *_front->payload;
        }
        return *_list.front().payload;
    }

    /// Returns the number of elements contained.
    ///
    /// \note Expired elements are not contained. Expiring element is still contained when OnExpiry is called.
    size_t size() const {
        return _size;
    }

    /// Reserves storage in the container for at least 'size' elements.
    /// Note that expired elements may also take space when they are not in the front of the queue.
    ///
    /// Doesn't give any guarantees about exception safety of subsequent push_back().
    void reserve(size_t size) {
        return _list.reserve(size);
    }

    /// Adds element to the back of the queue.
    /// The element will never expire.
    void push_back(const T& payload) {
        if (_size == 0) {
            _front = std::make_unique<entry>(payload);
        } else {
            _list.emplace_back(payload);
        }
        ++_size;
    }

    /// Adds element to the back of the queue.
    /// The element will never expire.
    void push_back(T&& payload) {
        if (_size == 0) {
            _front = std::make_unique<entry>(std::move(payload));
        } else {
            _list.emplace_back(std::move(payload));
        }
        ++_size;
    }

    /// Adds element to the back of the queue.
    /// The element will expire when timeout is reached, unless it is time_point::max(), in which
    /// case it never expires.
    void push_back(T payload, time_point timeout) {
        if (timeout == time_point::max()) {
            push_back(std::move(payload));
            return;
        }
        if (_size == 0) {
            _front = std::make_unique<entry>(std::move(payload), *this, timeout);
        } else {
            _list.emplace_back(std::move(payload), *this, timeout);
        }
        ++_size;
    }

    /// Removes the element at the front.
    /// Can be called only if !empty().
    void pop_front() {
        if (_front) {
            _front.reset();
        } else {
            _list.pop_front();
        }
        --_size;
        drop_expired_front();
    }
};

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

#include <string>

#include "arch/x86/isa_traits.hh"
#include "arch/x86/stacktrace.hh"
#include "arch/x86/vtophys.hh"
#include "base/bitfield.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "sim/system.hh"

using namespace std;
namespace X86ISA
{
    ProcessInfo::ProcessInfo(ThreadContext *_tc)
        : tc(_tc)
    {
        Addr addr = 0;

        VirtualPort *vp;

        vp = tc->getVirtPort();

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
            panic("thread info not compiled into kernel\n");
        thread_info_size = vp->readGtoH<int32_t>(addr);

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
            panic("thread info not compiled into kernel\n");
        task_struct_size = vp->readGtoH<int32_t>(addr);

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
            panic("thread info not compiled into kernel\n");
        task_off = vp->readGtoH<int32_t>(addr);

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
            panic("thread info not compiled into kernel\n");
        pid_off = vp->readGtoH<int32_t>(addr);

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
            panic("thread info not compiled into kernel\n");
        name_off = vp->readGtoH<int32_t>(addr);

        tc->delVirtPort(vp);
    }

    Addr
    ProcessInfo::task(Addr ksp) const
    {
        Addr base = ksp & ~0x3fff;
        if (base == ULL(0xfffffc0000000000))
            return 0;

        Addr tsk;

        VirtualPort *vp;

        vp = tc->getVirtPort();
        tsk = vp->readGtoH<Addr>(base + task_off);
        tc->delVirtPort(vp);

        return tsk;
    }

    int
    ProcessInfo::pid(Addr ksp) const
    {
        Addr task = this->task(ksp);
        if (!task)
            return -1;

        uint16_t pd;

        VirtualPort *vp;

        vp = tc->getVirtPort();
        pd = vp->readGtoH<uint16_t>(task + pid_off);
        tc->delVirtPort(vp);

        return pd;
    }

    string
    ProcessInfo::name(Addr ksp) const
    {
        Addr task = this->task(ksp);
        if (!task)
            return "console";

        char comm[256];
        CopyStringOut(tc, comm, task + name_off, sizeof(comm));
        if (!comm[0])
            return "startup";

        return comm;
    }

    StackTrace::StackTrace()
        : tc(0), stack(64)
    {
    }

    StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
        : tc(0), stack(64)
    {
        trace(_tc, inst);
    }

    StackTrace::~StackTrace()
    {
    }

    void
    StackTrace::trace(ThreadContext *_tc, bool is_call)
    {
    }

    bool
    StackTrace::isEntry(Addr addr)
    {
        return false;
    }

    bool
    StackTrace::decodeStack(MachInst inst, int &disp)
    {
        return true;
    }

    bool
    StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
    {
        return true;
    }

    /*
     * Decode the function prologue for the function we're in, and note
     * which registers are stored where, and how large the stack frame is.
     */
    bool
    StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
                               int &size, Addr &ra)
    {
        size = 0;
        ra = 0;

        for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
            MachInst inst;
            CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));

            int reg, disp;
            if (decodeStack(inst, disp)) {
                if (size) {
                    // panic("decoding frame size again");
                    return true;
                }
                size += disp;
            } else if (decodeSave(inst, reg, disp)) {
                if (!ra && reg == ReturnAddressReg) {
                    CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
                    if (!ra) {
                        // panic("no return address value pc=%#x\n", pc);
                        return false;
                    }
                }
            }
        }

        return true;
    }

#if TRACING_ON
    void
    StackTrace::dump()
    {
        StringWrap name(tc->getCpuPtr()->name());
        SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;

        DPRINTFN("------ Stack ------\n");

        string symbol;
        for (int i = 0, size = stack.size(); i < size; ++i) {
            Addr addr = stack[size - i - 1];
            if (addr == user)
                symbol = "user";
            else if (addr == console)
                symbol = "console";
            else if (addr == unknown)
                symbol = "unknown";
            else
                symtab->findSymbol(addr, symbol);

            DPRINTFN("%#x: %s\n", addr, symbol);
        }
    }
#endif
}
<commit_msg>X86: Fix for uninitialized variables in stacktrace code.<commit_after>/*
 * Copyright (c) 2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

#include <string>

#include "arch/x86/isa_traits.hh"
#include "arch/x86/stacktrace.hh"
#include "arch/x86/vtophys.hh"
#include "base/bitfield.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "sim/system.hh"

using namespace std;
namespace X86ISA
{
    ProcessInfo::ProcessInfo(ThreadContext *_tc)
        : tc(_tc)
    {
        Addr addr = 0;

        VirtualPort *vp;

        vp = tc->getVirtPort();

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
            panic("thread info not compiled into kernel\n");
        thread_info_size = vp->readGtoH<int32_t>(addr);

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
            panic("thread info not compiled into kernel\n");
        task_struct_size = vp->readGtoH<int32_t>(addr);

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
            panic("thread info not compiled into kernel\n");
        task_off = vp->readGtoH<int32_t>(addr);

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
            panic("thread info not compiled into kernel\n");
        pid_off = vp->readGtoH<int32_t>(addr);

        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
            panic("thread info not compiled into kernel\n");
        name_off = vp->readGtoH<int32_t>(addr);

        tc->delVirtPort(vp);
    }

    Addr
    ProcessInfo::task(Addr ksp) const
    {
        Addr base = ksp & ~0x3fff;
        if (base == ULL(0xfffffc0000000000))
            return 0;

        Addr tsk;

        VirtualPort *vp;

        vp = tc->getVirtPort();
        tsk = vp->readGtoH<Addr>(base + task_off);
        tc->delVirtPort(vp);

        return tsk;
    }

    int
    ProcessInfo::pid(Addr ksp) const
    {
        Addr task = this->task(ksp);
        if (!task)
            return -1;

        uint16_t pd;

        VirtualPort *vp;

        vp = tc->getVirtPort();
        pd = vp->readGtoH<uint16_t>(task + pid_off);
        tc->delVirtPort(vp);

        return pd;
    }

    string
    ProcessInfo::name(Addr ksp) const
    {
        Addr task = this->task(ksp);
        if (!task)
            return "console";

        char comm[256];
        CopyStringOut(tc, comm, task + name_off, sizeof(comm));
        if (!comm[0])
            return "startup";

        return comm;
    }

    StackTrace::StackTrace()
        : tc(0), stack(64)
    {
    }

    StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
        : tc(0), stack(64)
    {
        trace(_tc, inst);
    }

    StackTrace::~StackTrace()
    {
    }

    void
    StackTrace::trace(ThreadContext *_tc, bool is_call)
    {
    }

    bool
    StackTrace::isEntry(Addr addr)
    {
        return false;
    }

    bool
    StackTrace::decodeStack(MachInst inst, int &disp)
    {
        disp = 0;
        return true;
    }

    bool
    StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
    {
        reg = 0;
        disp = 0;
        return true;
    }

    /*
     * Decode the function prologue for the function we're in, and note
     * which registers are stored where, and how large the stack frame is.
     */
    bool
    StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
                               int &size, Addr &ra)
    {
        size = 0;
        ra = 0;

        for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
            MachInst inst;
            CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));

            int reg, disp;
            if (decodeStack(inst, disp)) {
                if (size) {
                    // panic("decoding frame size again");
                    return true;
                }
                size += disp;
            } else if (decodeSave(inst, reg, disp)) {
                if (!ra && reg == ReturnAddressReg) {
                    CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
                    if (!ra) {
                        // panic("no return address value pc=%#x\n", pc);
                        return false;
                    }
                }
            }
        }

        return true;
    }

#if TRACING_ON
    void
    StackTrace::dump()
    {
        StringWrap name(tc->getCpuPtr()->name());
        SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;

        DPRINTFN("------ Stack ------\n");

        string symbol;
        for (int i = 0, size = stack.size(); i < size; ++i) {
            Addr addr = stack[size - i - 1];
            if (addr == user)
                symbol = "user";
            else if (addr == console)
                symbol = "console";
            else if (addr == unknown)
                symbol = "unknown";
            else
                symtab->findSymbol(addr, symbol);

            DPRINTFN("%#x: %s\n", addr, symbol);
        }
    }
#endif
}
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XSIMD_CONFIG_HPP
#define XSIMD_CONFIG_HPP

#include "xsimd_align.hpp"

#define XSIMD_VERSION_MAJOR 7
#define XSIMD_VERSION_MINOR 2
#define XSIMD_VERSION_PATCH 4

#ifndef XSIMD_DEFAULT_ALLOCATOR
    #if XSIMD_X86_INSTR_SET_AVAILABLE
        #define XSIMD_DEFAULT_ALLOCATOR(T) xsimd::aligned_allocator<T, XSIMD_DEFAULT_ALIGNMENT>
    #else
        #define XSIMD_DEFAULT_ALLOCATOR(T) std::allocator<T>
    #endif
#endif

#ifndef XSIMD_STACK_ALLOCATION_LIMIT
    #define XSIMD_STACK_ALLOCATION_LIMIT 20000
#endif

#if defined(__LP64__) || defined(_WIN64)
    #define XSIMD_64_BIT_ABI
#else
    #define XSIMD_32_BIT_ABI
#endif

#endif
<commit_msg>Release 7.2.5<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XSIMD_CONFIG_HPP
#define XSIMD_CONFIG_HPP

#include "xsimd_align.hpp"

#define XSIMD_VERSION_MAJOR 7
#define XSIMD_VERSION_MINOR 2
#define XSIMD_VERSION_PATCH 5

#ifndef XSIMD_DEFAULT_ALLOCATOR
    #if XSIMD_X86_INSTR_SET_AVAILABLE
        #define XSIMD_DEFAULT_ALLOCATOR(T) xsimd::aligned_allocator<T, XSIMD_DEFAULT_ALIGNMENT>
    #else
        #define XSIMD_DEFAULT_ALLOCATOR(T) std::allocator<T>
    #endif
#endif

#ifndef XSIMD_STACK_ALLOCATION_LIMIT
    #define XSIMD_STACK_ALLOCATION_LIMIT 20000
#endif

#if defined(__LP64__) || defined(_WIN64)
    #define XSIMD_64_BIT_ABI
#else
    #define XSIMD_32_BIT_ABI
#endif

#endif
<|endoftext|>


<commit_before>// Includes
#include <cstring>
#include "Sound.h"
#include "System.h"
#include "fmod/fmod.h"

// Globals
static SoundManager *gSoundManager = 0;
SoundManager *sound_manager() {return system()->sound_manager();}

// SoundSource
// ===========

void SoundSource::Play() {
  if (channel_ != 0)
    FMOD_Channel_SetPaused(channel_, false);
}

void SoundSource::Pause() {
  if (channel_ != 0)
    FMOD_Channel_SetPaused(channel_, true);
}

bool SoundSource::IsPaused() const {
  FMOD_BOOL is_paused = false;
  if (channel_ != 0)
    FMOD_Channel_GetPaused(channel_, &is_paused);
  return is_paused;
}

void SoundSource::Stop() {
  LOGF("stopped");
  if (channel_ != 0)
    FMOD_Channel_Stop(channel_);
}

bool SoundSource::IsStopped() const {
  FMOD_BOOL is_playing = false;
  if (channel_ != 0)
    FMOD_Channel_IsPlaying(channel_, &is_playing);
  return !is_playing;
}

// SoundSample
// ===========

SoundSample *SoundSample::Load(InputStream in, bool store_compressed, float base_volume) {
  // Load the data into memory - we could eventually switch to using extra_info.fileoffset or
  // FMOD_OPENUSER mode instead but this is good for now.
  if (!in.IsValid() || !sound_manager()->IsInitialized())
    return 0;
  char *data;
  int length = in.ReadAllData((void**)&data);

  // Attempt to create the sound
  FMOD_SOUND *sound;
  FMOD_RESULT result;
  FMOD_CREATESOUNDEXINFO extra_info;
  memset(&extra_info, 0, sizeof(extra_info));
  extra_info.cbsize = sizeof(extra_info);
  extra_info.length = length;
  if (store_compressed) {
    result = FMOD_System_CreateSound(sound_manager()->GetSystem(),
      data, FMOD_CREATECOMPRESSEDSAMPLE | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_LOOP_NORMAL, &extra_info, &sound);
  } else {
    result = FMOD_System_CreateSound(sound_manager()->GetSystem(),
      data, FMOD_DEFAULT | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_LOOP_NORMAL, &extra_info, &sound);
  }

  // Store the result or return error
  delete[] data;
  if (result != FMOD_OK)
    return 0;
  return new SoundSample(sound, base_volume);
}

SoundSample::~SoundSample() {
  FMOD_Sound_Release(sound_);
}

SoundSource SoundSample::Play(bool looped, bool start_paused) const {
  FMOD_CHANNEL *channel;
  FMOD_Sound_SetLoopCount(sound_, looped? -1 : 0);
  FMOD_System_PlaySound(sound_manager()->GetSystem(), FMOD_CHANNEL_FREE, sound_, start_paused, &channel);
  FMOD_Channel_SetVolume(channel, base_volume_);
  return SoundSource(channel);
}

// SoundManager
// ============

void SoundManager::SetVolume(float volume) {
  volume_ = volume;
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetVolume(master_channel_group, volume);
  }
}

SoundManager::SoundManager()
: system_(0), volume_(1) {
  // Create the system object and check versions
  const int kNumChannels = 128;
  if (FMOD_System_Create(&system_) != FMOD_OK)
    return;
  unsigned int version;
  if (FMOD_System_GetVersion(system_, &version) != FMOD_OK || version < FMOD_VERSION)
    goto error;

  // Fix bad initialization options. FMOD documentation strongly recommends doing this for Windows.
  FMOD_CAPS caps;
  FMOD_SPEAKERMODE speaker_mode;
  if (FMOD_System_GetDriverCaps(system_, 0, &caps, 0, 0, &speaker_mode) != FMOD_OK)
    goto error;
  if (FMOD_System_SetSpeakerMode(system_, speaker_mode) != FMOD_OK)
    goto error;
  if (caps & FMOD_CAPS_HARDWARE_EMULATED) {
    if (FMOD_System_SetDSPBufferSize(system_, 1024, 10) != FMOD_OK)
      goto error;
  }

  // Initialize
  if (FMOD_System_Init(system_, kNumChannels, FMOD_INIT_NORMAL, 0) != FMOD_OK) {
    if (FMOD_System_SetSpeakerMode(system_, FMOD_SPEAKERMODE_STEREO) != FMOD_OK)
      goto error;
    if (FMOD_System_Init(system_, kNumChannels, FMOD_INIT_NORMAL, 0) != FMOD_OK)
      goto error;
  }

  // Success
  SetVolume(volume_);
  return;

  // Failure
error:;
  system_ = 0;
}

SoundManager::~SoundManager() {
  if (IsInitialized())
    FMOD_System_Release(system_);
}

void SoundManager::Think() {
  if (IsInitialized())
    FMOD_System_Update(system_);
}

void SoundManager::PlayAllSources() {
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetPaused(master_channel_group, false);
  }
}

void SoundManager::PauseAllSources() {
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetPaused(master_channel_group, true);
  }
}

void SoundManager::StopAllSources() {
  if (IsInitialized()) {
    int num_channels;
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_GetNumChannels(master_channel_group, &num_channels);
    for (int i = 0; i < num_channels; i++) {
      FMOD_CHANNEL *channel;
      FMOD_ChannelGroup_GetChannel(master_channel_group, i, &channel);
      FMOD_Channel_Stop(channel);
    }
  }
}
<commit_msg>still think something kind of wacky is going on here<commit_after>// Includes
#include <cstring>
#include "Sound.h"
#include "System.h"
#include "fmod/fmod.h"

// Globals
static SoundManager *gSoundManager = 0;
SoundManager *sound_manager() {return system()->sound_manager();}

// SoundSource
// ===========

void SoundSource::Play() {
  if (channel_ != 0)
    FMOD_Channel_SetPaused(channel_, false);
}

void SoundSource::Pause() {
  if (channel_ != 0)
    FMOD_Channel_SetPaused(channel_, true);
}

bool SoundSource::IsPaused() const {
  FMOD_BOOL is_paused = false;
  if (channel_ != 0)
    FMOD_Channel_GetPaused(channel_, &is_paused);
  return is_paused;
}

void SoundSource::Stop() {
  LOGF("stopped");
  if (channel_ != 0)
    FMOD_Channel_Stop(channel_);
}

bool SoundSource::IsStopped() const {
  FMOD_BOOL is_playing = false;
  if (channel_ != 0)
    FMOD_Channel_IsPlaying(channel_, &is_playing);
  return !is_playing;
}

// SoundSample
// ===========

SoundSample *SoundSample::Load(InputStream in, bool store_compressed, float base_volume) {
  // Load the data into memory - we could eventually switch to using extra_info.fileoffset or
  // FMOD_OPENUSER mode instead but this is good for now.
  LOGF("SSLA %d, %d\n", in.IsValid(), sound_manager()->IsInitialized());
  if (!in.IsValid() || !sound_manager()->IsInitialized())
    return 0;
  char *data;
  int length = in.ReadAllData((void**)&data);

  // Attempt to create the sound
  FMOD_SOUND *sound;
  FMOD_RESULT result;
  FMOD_CREATESOUNDEXINFO extra_info;
  memset(&extra_info, 0, sizeof(extra_info));
  extra_info.cbsize = sizeof(extra_info);
  extra_info.length = length;
  if (store_compressed) {
    result = FMOD_System_CreateSound(sound_manager()->GetSystem(),
      data, FMOD_CREATECOMPRESSEDSAMPLE | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_LOOP_NORMAL, &extra_info, &sound);
  } else {
    result = FMOD_System_CreateSound(sound_manager()->GetSystem(),
      data, FMOD_DEFAULT | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_LOOP_NORMAL, &extra_info, &sound);
  }
  LOGF("SSLB %d, %d\n", result, FMOD_OK);

  // Store the result or return error
  delete[] data;
  if (result != FMOD_OK)
    return 0;
  return new SoundSample(sound, base_volume);
}

SoundSample::~SoundSample() {
  FMOD_Sound_Release(sound_);
}

SoundSource SoundSample::Play(bool looped, bool start_paused) const {
  FMOD_CHANNEL *channel;
  FMOD_Sound_SetLoopCount(sound_, looped? -1 : 0);
  FMOD_System_PlaySound(sound_manager()->GetSystem(), FMOD_CHANNEL_FREE, sound_, start_paused, &channel);
  FMOD_Channel_SetVolume(channel, base_volume_);
  return SoundSource(channel);
}

// SoundManager
// ============

void SoundManager::SetVolume(float volume) {
  volume_ = volume;
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetVolume(master_channel_group, volume);
  }
}

SoundManager::SoundManager()
: system_(0), volume_(1) {
  // Create the system object and check versions
  const int kNumChannels = 128;
  if (FMOD_System_Create(&system_) != FMOD_OK)
    return;
  unsigned int version;
  if (FMOD_System_GetVersion(system_, &version) != FMOD_OK || version < FMOD_VERSION)
    goto error;

  // Fix bad initialization options. FMOD documentation strongly recommends doing this for Windows.
  FMOD_CAPS caps;
  FMOD_SPEAKERMODE speaker_mode;
  if (FMOD_System_GetDriverCaps(system_, 0, &caps, 0, 0, &speaker_mode) != FMOD_OK)
    goto error;
  if (FMOD_System_SetSpeakerMode(system_, speaker_mode) != FMOD_OK)
    goto error;
  if (caps & FMOD_CAPS_HARDWARE_EMULATED) {
    if (FMOD_System_SetDSPBufferSize(system_, 1024, 10) != FMOD_OK)
      goto error;
  }

  // Initialize
  if (FMOD_System_Init(system_, kNumChannels, FMOD_INIT_NORMAL, 0) != FMOD_OK) {
    if (FMOD_System_SetSpeakerMode(system_, FMOD_SPEAKERMODE_STEREO) != FMOD_OK)
      goto error;
    if (FMOD_System_Init(system_, kNumChannels, FMOD_INIT_NORMAL, 0) != FMOD_OK)
      goto error;
  }

  // Success
  SetVolume(volume_);
  return;

  // Failure
error:;
  system_ = 0;
}

SoundManager::~SoundManager() {
  if (IsInitialized())
    FMOD_System_Release(system_);
}

void SoundManager::Think() {
  if (IsInitialized())
    FMOD_System_Update(system_);
}

void SoundManager::PlayAllSources() {
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetPaused(master_channel_group, false);
  }
}

void SoundManager::PauseAllSources() {
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetPaused(master_channel_group, true);
  }
}

void SoundManager::StopAllSources() {
  if (IsInitialized()) {
    int num_channels;
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_GetNumChannels(master_channel_group, &num_channels);
    for (int i = 0; i < num_channels; i++) {
      FMOD_CHANNEL *channel;
      FMOD_ChannelGroup_GetChannel(master_channel_group, i, &channel);
      FMOD_Channel_Stop(channel);
    }
  }
}
<|endoftext|>


<commit_before>// Includes
#include <cstring>
#include "Sound.h"
#include "System.h"
#include "fmod/fmod.h"

// Globals
static SoundManager *gSoundManager = 0;
SoundManager *sound_manager() {return system()->sound_manager();}

// SoundSource
// ===========

void SoundSource::Play() {
  if (channel_ != 0)
    FMOD_Channel_SetPaused(channel_, false);
}

void SoundSource::Pause() {
  if (channel_ != 0)
    FMOD_Channel_SetPaused(channel_, true);
}

bool SoundSource::IsPaused() const {
  FMOD_BOOL is_paused = false;
  if (channel_ != 0)
    FMOD_Channel_GetPaused(channel_, &is_paused);
  return is_paused;
}

void SoundSource::Stop() {
  LOGF("stopped");
  if (channel_ != 0)
    FMOD_Channel_Stop(channel_);
}

bool SoundSource::IsStopped() const {
  FMOD_BOOL is_playing = false;
  if (channel_ != 0)
    FMOD_Channel_IsPlaying(channel_, &is_playing);
  return !is_playing;
}

// SoundSample
// ===========

SoundSample *SoundSample::Load(InputStream in, bool store_compressed, float base_volume) {
  // Load the data into memory - we could eventually switch to using extra_info.fileoffset or
  // FMOD_OPENUSER mode instead but this is good for now.
  if (!in.IsValid() || !sound_manager()->IsInitialized())
    return 0;
  char *data;
  int length = in.ReadAllData((void**)&data);

  // Attempt to create the sound
  FMOD_SOUND *sound;
  FMOD_RESULT result;
  FMOD_CREATESOUNDEXINFO extra_info;
  memset(&extra_info, 0, sizeof(extra_info));
  extra_info.cbsize = sizeof(extra_info);
  extra_info.length = length;
  if (store_compressed) {
    result = FMOD_System_CreateSound(sound_manager()->GetSystem(),
      data, FMOD_CREATECOMPRESSEDSAMPLE | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_LOOP_NORMAL, &extra_info, &sound);
  } else {
    result = FMOD_System_CreateSound(sound_manager()->GetSystem(),
      data, FMOD_DEFAULT | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_LOOP_NORMAL, &extra_info, &sound);
  }

  // Store the result or return error
  delete[] data;
  if (result != FMOD_OK)
    return 0;
  return new SoundSample(sound, base_volume);
}

SoundSample::~SoundSample() {
  FMOD_Sound_Release(sound_);
}

SoundSource SoundSample::Play(bool looped, bool start_paused) const {
  FMOD_CHANNEL *channel;
  FMOD_Sound_SetLoopCount(sound_, looped? -1 : 0);
  FMOD_System_PlaySound(sound_manager()->GetSystem(), FMOD_CHANNEL_FREE, sound_, start_paused, &channel);
  FMOD_Channel_SetVolume(channel, base_volume_);
  return SoundSource(channel);
}

// SoundManager
// ============

void SoundManager::SetVolume(float volume) {
  volume_ = volume;
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetVolume(master_channel_group, volume);
  }
}

SoundManager::SoundManager()
: system_(0), volume_(1) {
  // Create the system object and check versions
  const int kNumChannels = 128;
  if (FMOD_System_Create(&system_) != FMOD_OK)
    return;
  unsigned int version;
  if (FMOD_System_GetVersion(system_, &version) != FMOD_OK || version < FMOD_VERSION)
    goto error;

  // Fix bad initialization options. FMOD documentation strongly recommends doing this for Windows.
  FMOD_CAPS caps;
  FMOD_SPEAKERMODE speaker_mode;
  if (FMOD_System_GetDriverCaps(system_, 0, &caps, 0, 0, &speaker_mode) != FMOD_OK)
    goto error;
  if (FMOD_System_SetSpeakerMode(system_, speaker_mode) != FMOD_OK)
    goto error;
  if (caps & FMOD_CAPS_HARDWARE_EMULATED) {
    if (FMOD_System_SetDSPBufferSize(system_, 1024, 10) != FMOD_OK)
      goto error;
  }

  // Initialize
  if (FMOD_System_Init(system_, kNumChannels, FMOD_INIT_NORMAL, 0) != FMOD_OK) {
    if (FMOD_System_SetSpeakerMode(system_, FMOD_SPEAKERMODE_STEREO) != FMOD_OK)
      goto error;
    if (FMOD_System_Init(system_, kNumChannels, FMOD_INIT_NORMAL, 0) != FMOD_OK)
      goto error;
  }

  // Success
  SetVolume(volume_);
  return;

  // Failure
error:;
  system_ = 0;
}

SoundManager::~SoundManager() {
  if (IsInitialized())
    FMOD_System_Release(system_);
}

void SoundManager::Think() {
  if (IsInitialized())
    FMOD_System_Update(system_);
}

void SoundManager::PlayAllSources() {
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetPaused(master_channel_group, false);
  }
}

void SoundManager::PauseAllSources() {
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetPaused(master_channel_group, true);
  }
}

void SoundManager::StopAllSources() {
  if (IsInitialized()) {
    int num_channels;
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_GetNumChannels(master_channel_group, &num_channels);
    for (int i = 0; i < num_channels; i++) {
      FMOD_CHANNEL *channel;
      FMOD_ChannelGroup_GetChannel(master_channel_group, i, &channel);
      FMOD_Channel_Stop(channel);
    }
  }
}
<commit_msg>lots of sound effects, a few tweaks<commit_after>// Includes
#include <cstring>
#include "Sound.h"
#include "System.h"
#include "fmod/fmod.h"

// Globals
static SoundManager *gSoundManager = 0;
SoundManager *sound_manager() {return system()->sound_manager();}

// SoundSource
// ===========

void SoundSource::Play() {
  if (channel_ != 0)
    FMOD_Channel_SetPaused(channel_, false);
}

void SoundSource::Pause() {
  if (channel_ != 0)
    FMOD_Channel_SetPaused(channel_, true);
}

bool SoundSource::IsPaused() const {
  FMOD_BOOL is_paused = false;
  if (channel_ != 0)
    FMOD_Channel_GetPaused(channel_, &is_paused);
  return is_paused;
}

void SoundSource::Stop() {
  if (channel_ != 0)
    FMOD_Channel_Stop(channel_);
}

bool SoundSource::IsStopped() const {
  FMOD_BOOL is_playing = false;
  if (channel_ != 0)
    FMOD_Channel_IsPlaying(channel_, &is_playing);
  return !is_playing;
}

// SoundSample
// ===========

SoundSample *SoundSample::Load(InputStream in, bool store_compressed, float base_volume) {
  // Load the data into memory - we could eventually switch to using extra_info.fileoffset or
  // FMOD_OPENUSER mode instead but this is good for now.
  if (!in.IsValid() || !sound_manager()->IsInitialized())
    return 0;
  char *data;
  int length = in.ReadAllData((void**)&data);

  // Attempt to create the sound
  FMOD_SOUND *sound;
  FMOD_RESULT result;
  FMOD_CREATESOUNDEXINFO extra_info;
  memset(&extra_info, 0, sizeof(extra_info));
  extra_info.cbsize = sizeof(extra_info);
  extra_info.length = length;
  if (store_compressed) {
    result = FMOD_System_CreateSound(sound_manager()->GetSystem(),
      data, FMOD_CREATECOMPRESSEDSAMPLE | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_LOOP_NORMAL, &extra_info, &sound);
  } else {
    result = FMOD_System_CreateSound(sound_manager()->GetSystem(),
      data, FMOD_DEFAULT | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_LOOP_NORMAL, &extra_info, &sound);
  }

  // Store the result or return error
  delete[] data;
  if (result != FMOD_OK)
    return 0;
  return new SoundSample(sound, base_volume);
}

SoundSample::~SoundSample() {
  FMOD_Sound_Release(sound_);
}

SoundSource SoundSample::Play(bool looped, bool start_paused) const {
  FMOD_CHANNEL *channel;
  FMOD_Sound_SetLoopCount(sound_, looped? -1 : 0);
  FMOD_System_PlaySound(sound_manager()->GetSystem(), FMOD_CHANNEL_FREE, sound_, start_paused, &channel);
  FMOD_Channel_SetVolume(channel, base_volume_);
  return SoundSource(channel);
}

// SoundManager
// ============

void SoundManager::SetVolume(float volume) {
  volume_ = volume;
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetVolume(master_channel_group, volume);
  }
}

SoundManager::SoundManager()
: system_(0), volume_(1) {
  // Create the system object and check versions
  const int kNumChannels = 128;
  if (FMOD_System_Create(&system_) != FMOD_OK)
    return;
  unsigned int version;
  if (FMOD_System_GetVersion(system_, &version) != FMOD_OK || version < FMOD_VERSION)
    goto error;

  // Fix bad initialization options. FMOD documentation strongly recommends doing this for Windows.
  FMOD_CAPS caps;
  FMOD_SPEAKERMODE speaker_mode;
  if (FMOD_System_GetDriverCaps(system_, 0, &caps, 0, 0, &speaker_mode) != FMOD_OK)
    goto error;
  if (FMOD_System_SetSpeakerMode(system_, speaker_mode) != FMOD_OK)
    goto error;
  if (caps & FMOD_CAPS_HARDWARE_EMULATED) {
    if (FMOD_System_SetDSPBufferSize(system_, 1024, 10) != FMOD_OK)
      goto error;
  }

  // Initialize
  if (FMOD_System_Init(system_, kNumChannels, FMOD_INIT_NORMAL, 0) != FMOD_OK) {
    if (FMOD_System_SetSpeakerMode(system_, FMOD_SPEAKERMODE_STEREO) != FMOD_OK)
      goto error;
    if (FMOD_System_Init(system_, kNumChannels, FMOD_INIT_NORMAL, 0) != FMOD_OK)
      goto error;
  }

  // Success
  SetVolume(volume_);
  return;

  // Failure
error:;
  system_ = 0;
}

SoundManager::~SoundManager() {
  if (IsInitialized())
    FMOD_System_Release(system_);
}

void SoundManager::Think() {
  if (IsInitialized())
    FMOD_System_Update(system_);
}

void SoundManager::PlayAllSources() {
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetPaused(master_channel_group, false);
  }
}

void SoundManager::PauseAllSources() {
  if (IsInitialized()) {
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_SetPaused(master_channel_group, true);
  }
}

void SoundManager::StopAllSources() {
  if (IsInitialized()) {
    int num_channels;
    FMOD_CHANNELGROUP *master_channel_group;
    FMOD_System_GetMasterChannelGroup(system_, &master_channel_group);
    FMOD_ChannelGroup_GetNumChannels(master_channel_group, &num_channels);
    for (int i = 0; i < num_channels; i++) {
      FMOD_CHANNEL *channel;
      FMOD_ChannelGroup_GetChannel(master_channel_group, i, &channel);
      FMOD_Channel_Stop(channel);
    }
  }
}
<|endoftext|>


<commit_before>#include <algorithm>

#include "RCIFile.h"

#include "../Utilities/Debug.h"

#include "components/vfs/manager.hpp"

const int RCIFile::FRAME_WIDTH = 320;
const int RCIFile::FRAME_HEIGHT = 100;
const int RCIFile::FRAME_SIZE = RCIFile::FRAME_WIDTH * RCIFile::FRAME_HEIGHT;

RCIFile::RCIFile(const std::string &filename, const Palette &palette)
{
	VFS::IStreamPtr stream = VFS::Manager::get().open(filename.c_str());
	Debug::check(stream != nullptr, "RCIFile", "Could not open \"" + filename + "\".");

	stream->seekg(0, std::ios::end);
	const auto fileSize = stream->tellg();
	stream->seekg(0, std::ios::beg);

	std::vector<uint8_t> srcData(fileSize);
	stream->read(reinterpret_cast<char*>(srcData.data()), srcData.size());

	// Number of uncompressed frames packed in the RCI.
	const int frameCount = static_cast<int>(fileSize) / RCIFile::FRAME_SIZE;

	// Create an image for each uncompressed frame using the given palette.
	for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex)
	{
		this->frames.push_back(std::unique_ptr<uint32_t>(
			new uint32_t[RCIFile::FRAME_SIZE]));

		const int byteOffset = RCIFile::FRAME_SIZE * frameIndex;

		std::transform(srcData.begin() + byteOffset,
			srcData.begin() + byteOffset + RCIFile::FRAME_SIZE,
			this->frames.at(frameIndex).get(),
			[&palette](uint8_t col) -> uint32_t
		{
			return palette[col].toARGB();
		});
	}
}

RCIFile::~RCIFile()
{

}

int RCIFile::getCount() const
{
	return static_cast<int>(this->frames.size());
}

uint32_t *RCIFile::getPixels(int index) const
{
	// No need for this object to store its filename; it can be found somewhere
	// in the texture manager stack in debug mode.
	Debug::check((index >= 0) && (index < this->getCount()), "RCIFile",
		"Frame index (" + std::to_string(index) + ") out of range.");

	return this->frames[index].get();
}
<commit_msg>Removed unnecessary debug code from RCIFile.<commit_after>#include <algorithm>

#include "RCIFile.h"

#include "../Utilities/Debug.h"

#include "components/vfs/manager.hpp"

const int RCIFile::FRAME_WIDTH = 320;
const int RCIFile::FRAME_HEIGHT = 100;
const int RCIFile::FRAME_SIZE = RCIFile::FRAME_WIDTH * RCIFile::FRAME_HEIGHT;

RCIFile::RCIFile(const std::string &filename, const Palette &palette)
{
	VFS::IStreamPtr stream = VFS::Manager::get().open(filename.c_str());
	Debug::check(stream != nullptr, "RCIFile", "Could not open \"" + filename + "\".");

	stream->seekg(0, std::ios::end);
	const auto fileSize = stream->tellg();
	stream->seekg(0, std::ios::beg);

	std::vector<uint8_t> srcData(fileSize);
	stream->read(reinterpret_cast<char*>(srcData.data()), srcData.size());

	// Number of uncompressed frames packed in the RCI.
	const int frameCount = static_cast<int>(fileSize) / RCIFile::FRAME_SIZE;

	// Create an image for each uncompressed frame using the given palette.
	for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex)
	{
		this->frames.push_back(std::unique_ptr<uint32_t>(
			new uint32_t[RCIFile::FRAME_SIZE]));

		const int byteOffset = RCIFile::FRAME_SIZE * frameIndex;

		std::transform(srcData.begin() + byteOffset,
			srcData.begin() + byteOffset + RCIFile::FRAME_SIZE,
			this->frames.at(frameIndex).get(),
			[&palette](uint8_t col) -> uint32_t
		{
			return palette[col].toARGB();
		});
	}
}

RCIFile::~RCIFile()
{

}

int RCIFile::getCount() const
{
	return static_cast<int>(this->frames.size());
}

uint32_t *RCIFile::getPixels(int index) const
{
	return this->frames.at(index).get();
}
<|endoftext|>


<commit_before>/*
vc_crt_fix_ulink.cpp

Workaround for Visual C++ CRT incompatibility with old Windows versions (ulink version)
*/
/*
Copyright © 2010 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <windows.h>
#include <delayimp.h>

//----------------------------------------------------------------------------
static LPVOID WINAPI no_recode_pointer(LPVOID p)
{
    return p;
}

//----------------------------------------------------------------------------
static FARPROC WINAPI delayFailureHook(/*dliNotification*/unsigned dliNotify,
                                       PDelayLoadInfo pdli)
{
    if(   dliNotify == /*dliFailGetProcAddress*/dliFailGetProc
       && pdli && pdli->cb == sizeof(*pdli)
       && pdli->hmodCur == GetModuleHandleA("kernel32")
       && pdli->dlp.fImportByName && pdli->dlp.szProcName
       && (   !lstrcmpA(pdli->dlp.szProcName, "EncodePointer")
           || !lstrcmpA(pdli->dlp.szProcName, "DecodePointer")))
    {
      return (FARPROC)no_recode_pointer;
    }
    return nullptr;
}

//----------------------------------------------------------------------------
PfnDliHook __pfnDliFailureHook2 = (PfnDliHook)delayFailureHook;

//----------------------------------------------------------------------------

// TODO: Add GetModuleHandleExW
<commit_msg>adopt Unilink helper to VS2015sp3 headers<commit_after>/*
vc_crt_fix_ulink.cpp

Workaround for Visual C++ CRT incompatibility with old Windows versions (ulink version)
*/
/*
Copyright © 2010 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "disable_warnings_in_std_begin.hpp"
#include <windows.h>
#include "disable_warnings_in_std_end.hpp"
#include <delayimp.h>

//----------------------------------------------------------------------------
static LPVOID WINAPI no_recode_pointer(LPVOID p)
{
    return p;
}

//----------------------------------------------------------------------------
static FARPROC WINAPI delayFailureHook(/*dliNotification*/unsigned dliNotify,
                                       PDelayLoadInfo pdli)
{
    if(   dliNotify == /*dliFailGetProcAddress*/dliFailGetProc
       && pdli && pdli->cb == sizeof(*pdli)
       && pdli->hmodCur == GetModuleHandleA("kernel32")
       && pdli->dlp.fImportByName && pdli->dlp.szProcName
       && (   !lstrcmpA(pdli->dlp.szProcName, "EncodePointer")
           || !lstrcmpA(pdli->dlp.szProcName, "DecodePointer")))
    {
      return (FARPROC)no_recode_pointer;
    }
    return nullptr;
}

//----------------------------------------------------------------------------
#if _MSC_FULL_VER >= 190024215 // VS2015sp3
const
#endif
PfnDliHook __pfnDliFailureHook2 = (PfnDliHook)delayFailureHook;

//----------------------------------------------------------------------------

// TODO: Add GetModuleHandleExW
<|endoftext|>