10f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
20f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
30f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// found in the LICENSE file.
40f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
50f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "media/audio/sounds/sounds_manager.h"
60f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
70f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/compiler_specific.h"
80f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/logging.h"
90f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/memory/linked_ptr.h"
100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/memory/ref_counted.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/single_thread_task_runner.h"
120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "media/audio/audio_manager.h"
130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "media/audio/sounds/audio_stream_handler.h"
140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace media {
160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace {
180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)SoundsManager* g_instance = NULL;
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool g_initialized_for_testing = false;
210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// SoundsManagerImpl ---------------------------------------------------
230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class SoundsManagerImpl : public SoundsManager {
250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public:
260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  SoundsManagerImpl();
270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  virtual ~SoundsManagerImpl();
280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // SoundsManager implementation:
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool Initialize(SoundKey key,
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const base::StringPiece& data) OVERRIDE;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool Play(SoundKey key) OVERRIDE;
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual base::TimeDelta GetDuration(SoundKey key) OVERRIDE;
340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private:
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::hash_map<SoundKey, linked_ptr<AudioStreamHandler> > handlers_;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SoundsManagerImpl);
400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)};
410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)SoundsManagerImpl::SoundsManagerImpl()
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : task_runner_(AudioManager::Get()->GetTaskRunner()) {
440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SoundsManagerImpl::~SoundsManagerImpl() { DCHECK(CalledOnValidThread()); }
470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SoundsManagerImpl::Initialize(SoundKey key,
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   const base::StringPiece& data) {
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (handlers_.find(key) != handlers_.end() && handlers_[key]->IsInitialized())
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  linked_ptr<AudioStreamHandler> handler(new AudioStreamHandler(data));
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!handler->IsInitialized()) {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(WARNING) << "Can't initialize AudioStreamHandler for key=" << key;
550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return false;
560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  handlers_[key] = handler;
580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return true;
590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SoundsManagerImpl::Play(SoundKey key) {
620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(CalledOnValidThread());
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (handlers_.find(key) == handlers_.end() ||
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !handlers_[key]->IsInitialized()) {
650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return false;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return handlers_[key]->Play();
680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::TimeDelta SoundsManagerImpl::GetDuration(SoundKey key) {
710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(CalledOnValidThread());
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (handlers_.find(key) == handlers_.end() ||
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !handlers_[key]->IsInitialized()) {
740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return base::TimeDelta();
750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const WavAudioHandler& wav_audio = handlers_[key]->wav_audio_handler();
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return wav_audio.params().GetBufferDuration();
780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}  // namespace
810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SoundsManager::SoundsManager() {}
830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SoundsManager::~SoundsManager() { DCHECK(CalledOnValidThread()); }
850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// static
870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void SoundsManager::Create() {
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(!g_instance || g_initialized_for_testing)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      << "SoundsManager::Create() is called twice";
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (g_initialized_for_testing)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  g_instance = new SoundsManagerImpl();
930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// static
960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void SoundsManager::Shutdown() {
970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  CHECK(g_instance) << "SoundsManager::Shutdown() is called "
980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                    << "without previous call to Create()";
990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  delete g_instance;
1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  g_instance = NULL;
1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// static
1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)SoundsManager* SoundsManager::Get() {
1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  CHECK(g_instance) << "SoundsManager::Get() is called before Create()";
1060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return g_instance;
1070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoundsManager::InitializeForTesting(SoundsManager* manager) {
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(!g_instance) << "SoundsManager is already initialized.";
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(manager);
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  g_instance = manager;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  g_initialized_for_testing = true;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}  // namespace media
118