blob: 47d69d24977597982c209749ed50bd431fdf0f41 [file] [log] [blame]
// Copyright 2017 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 "chromecast/media/cma/backend/cast_audio_json.h"
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/files/file_path_watcher.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/sequenced_task_runner.h"
#include "build/build_config.h"
namespace chromecast {
namespace media {
#if defined(OS_FUCHSIA)
const char kCastAudioJsonFilePath[] = "/system/data/cast_audio.json";
#else
const char kCastAudioJsonFilePath[] = "/etc/cast_audio.json";
#endif
const char kCastAudioJsonFileName[] = "cast_audio.json";
#define ENSURE_OWN_THREAD(method, ...) \
if (!task_runner_->RunsTasksInCurrentSequence()) { \
task_runner_->PostTask( \
FROM_HERE, base::BindOnce(&CastAudioJsonProviderImpl::method, \
base::Unretained(this), ##__VA_ARGS__)); \
return; \
}
// static
base::FilePath CastAudioJson::GetFilePath() {
base::FilePath tuning_path = CastAudioJson::GetFilePathForTuning();
if (base::PathExists(tuning_path)) {
return tuning_path;
}
return CastAudioJson::GetReadOnlyFilePath();
}
// static
base::FilePath CastAudioJson::GetReadOnlyFilePath() {
return base::FilePath(kCastAudioJsonFilePath);
}
// static
base::FilePath CastAudioJson::GetFilePathForTuning() {
return base::GetHomeDir().Append(kCastAudioJsonFileName);
}
CastAudioJsonProviderImpl::CastAudioJsonProviderImpl()
: thread_("cast_audio_json_provider"),
cast_audio_watcher_(std::make_unique<base::FilePathWatcher>()) {
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_IO;
thread_.StartWithOptions(options);
task_runner_ = thread_.task_runner();
}
CastAudioJsonProviderImpl::~CastAudioJsonProviderImpl() {
StopWatchingFileOnThread();
}
std::unique_ptr<base::Value> CastAudioJsonProviderImpl::GetCastAudioConfig() {
std::string contents;
base::ReadFileToString(CastAudioJson::GetFilePath(), &contents);
return base::JSONReader::ReadDeprecated(contents);
}
void CastAudioJsonProviderImpl::SetTuningChangedCallback(
TuningChangedCallback callback) {
ENSURE_OWN_THREAD(SetTuningChangedCallback, std::move(callback));
CHECK(!callback_);
callback_ = callback;
cast_audio_watcher_->Watch(
CastAudioJson::GetFilePathForTuning(), false /* recursive */,
base::BindRepeating(&CastAudioJsonProviderImpl::OnTuningFileChanged,
base::Unretained(this)));
}
void CastAudioJsonProviderImpl::StopWatchingFileOnThread() {
ENSURE_OWN_THREAD(StopWatchingFileOnThread);
cast_audio_watcher_.reset();
}
void CastAudioJsonProviderImpl::OnTuningFileChanged(const base::FilePath& path,
bool error) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK(callback_);
std::string contents;
base::ReadFileToString(path, &contents);
std::unique_ptr<base::Value> value =
base::JSONReader::ReadDeprecated(contents);
if (value) {
callback_.Run(std::move(value));
return;
}
LOG(ERROR) << "Unable to parse JSON in " << path;
}
} // namespace media
} // namespace chromecast