Chromium Code Reviews| Index: components/copresence/handlers/audio/audio_directive_handler.cc |
| diff --git a/components/copresence/handlers/audio/audio_directive_handler.cc b/components/copresence/handlers/audio/audio_directive_handler.cc |
| index 3d2e7c65aac69b8150c564c92550d5f20a486639..04bd9822ac8a392a21c9353d6b8104065234e303 100644 |
| --- a/components/copresence/handlers/audio/audio_directive_handler.cc |
| +++ b/components/copresence/handlers/audio/audio_directive_handler.cc |
| @@ -7,67 +7,27 @@ |
| #include "base/bind.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| -#include "base/strings/string_util.h" |
| #include "base/time/time.h" |
| -#include "components/copresence/mediums/audio/audio_player.h" |
| -#include "components/copresence/mediums/audio/audio_recorder.h" |
| #include "components/copresence/proto/data.pb.h" |
| +#include "components/copresence/public/copresence_constants.h" |
| #include "media/base/audio_bus.h" |
| -namespace { |
| - |
| -// UrlSafe is defined as: |
| -// '/' represented by a '_' and '+' represented by a '-' |
| -// TODO(rkc): Move this processing to the whispernet wrapper. |
| -std::string FromUrlSafe(std::string token) { |
| - base::ReplaceChars(token, "-", "+", &token); |
| - base::ReplaceChars(token, "_", "/", &token); |
| - return token; |
| -} |
| - |
| -const int kSampleExpiryTimeMs = 60 * 60 * 1000; // 60 minutes. |
| -const int kMaxSamples = 10000; |
| - |
| -} // namespace |
| - |
| namespace copresence { |
| // Public methods. |
| -AudioDirectiveHandler::AudioDirectiveHandler( |
| - const AudioRecorder::DecodeSamplesCallback& decode_cb, |
| - const AudioDirectiveHandler::EncodeTokenCallback& encode_cb) |
| - : player_audible_(NULL), |
| - player_inaudible_(NULL), |
| - recorder_(NULL), |
| - decode_cb_(decode_cb), |
| - encode_cb_(encode_cb), |
| - samples_cache_audible_( |
| - base::TimeDelta::FromMilliseconds(kSampleExpiryTimeMs), |
| - kMaxSamples), |
| - samples_cache_inaudible_( |
| - base::TimeDelta::FromMilliseconds(kSampleExpiryTimeMs), |
| - kMaxSamples) { |
| +AudioDirectiveHandler::AudioDirectiveHandler() |
| + : audio_manager_(make_scoped_ptr<AudioManager>(NULL)) { |
|
Daniel Erat
2014/10/17 22:25:59
don't think you need this; scoped_ptr's default c'
rkc
2014/10/18 00:21:54
Done.
|
| } |
| AudioDirectiveHandler::~AudioDirectiveHandler() { |
| - if (player_audible_) |
| - player_audible_->Finalize(); |
| - if (player_inaudible_) |
| - player_inaudible_->Finalize(); |
| - if (recorder_) |
| - recorder_->Finalize(); |
| } |
| -void AudioDirectiveHandler::Initialize() { |
| - player_audible_ = new AudioPlayer(); |
| - player_audible_->Initialize(); |
| - |
| - player_inaudible_ = new AudioPlayer(); |
| - player_inaudible_->Initialize(); |
| - |
| - recorder_ = new AudioRecorder(decode_cb_); |
| - recorder_->Initialize(); |
| +void AudioDirectiveHandler::Initialize( |
| + const AudioManager::DecodeSamplesCallback& decode_cb, |
| + const AudioManager::EncodeTokenCallback& encode_cb) { |
| + audio_manager_ = make_scoped_ptr(new AudioManager()); |
| + audio_manager_->Initialize(decode_cb, encode_cb); |
| } |
| void AudioDirectiveHandler::AddInstruction(const TokenInstruction& instruction, |
| @@ -77,144 +37,124 @@ void AudioDirectiveHandler::AddInstruction(const TokenInstruction& instruction, |
| case TRANSMIT: |
| DVLOG(2) << "Audio Transmit Directive received. Token: " |
| << instruction.token_id() |
| + << " with medium= " << instruction.medium() |
| << " with TTL=" << ttl.InMilliseconds(); |
| switch (instruction.medium()) { |
| case AUDIO_ULTRASOUND_PASSBAND: |
| - transmits_list_inaudible_.AddDirective(op_id, ttl); |
| - PlayToken(instruction.token_id(), false); |
| + transmits_list_[INAUDIBLE].AddDirective(op_id, ttl); |
| + audio_manager_->SetToken(INAUDIBLE, instruction.token_id()); |
| break; |
| case AUDIO_AUDIBLE_DTMF: |
| - transmits_list_audible_.AddDirective(op_id, ttl); |
| - PlayToken(instruction.token_id(), true); |
| + transmits_list_[AUDIBLE].AddDirective(op_id, ttl); |
| + audio_manager_->SetToken(AUDIBLE, instruction.token_id()); |
| break; |
| default: |
| NOTREACHED(); |
| } |
| break; |
| case RECEIVE: |
| - DVLOG(2) << "Audio Receive Directive received. TTL=" |
| - << ttl.InMilliseconds(); |
| - receives_list_.AddDirective(op_id, ttl); |
| - ProcessNextReceive(); |
| + DVLOG(2) << "Audio Receive Directive received." |
| + << " with medium= " << instruction.medium() |
| + << " with TTL=" << ttl.InMilliseconds(); |
| + switch (instruction.medium()) { |
| + case AUDIO_ULTRASOUND_PASSBAND: |
| + receives_list_[INAUDIBLE].AddDirective(op_id, ttl); |
| + break; |
| + case AUDIO_AUDIBLE_DTMF: |
| + receives_list_[AUDIBLE].AddDirective(op_id, ttl); |
| + break; |
| + default: |
| + NOTREACHED(); |
| + } |
| break; |
| case UNKNOWN_TOKEN_INSTRUCTION_TYPE: |
| default: |
| - LOG(WARNING) << "Unknown Audio Transmit Directive received."; |
| + LOG(WARNING) << "Unknown Audio Transmit Directive received. type = " |
| + << instruction.token_instruction_type(); |
| } |
| + ProcessNextInstruction(); |
| } |
| void AudioDirectiveHandler::RemoveInstructions(const std::string& op_id) { |
| - transmits_list_audible_.RemoveDirective(op_id); |
| - transmits_list_inaudible_.RemoveDirective(op_id); |
| - receives_list_.RemoveDirective(op_id); |
| + transmits_list_[AUDIBLE].RemoveDirective(op_id); |
| + transmits_list_[INAUDIBLE].RemoveDirective(op_id); |
| + receives_list_[AUDIBLE].RemoveDirective(op_id); |
| + receives_list_[INAUDIBLE].RemoveDirective(op_id); |
| - ProcessNextTransmit(); |
| - ProcessNextReceive(); |
| + ProcessNextInstruction(); |
| } |
| // Private methods. |
| -void AudioDirectiveHandler::ProcessNextTransmit() { |
| - // If we have an active directive for audible or inaudible audio, ensure that |
| - // we are playing our respective token; if we do not have a directive, then |
| - // make sure we aren't playing. This is duplicate code, but for just two |
| - // elements, it has hard to make a case for processing a loop instead. |
| - |
| - scoped_ptr<AudioDirective> audible_transmit( |
| - transmits_list_audible_.GetActiveDirective()); |
| - if (audible_transmit && !player_audible_->IsPlaying() && |
| - samples_cache_audible_.HasKey(current_token_audible_)) { |
| - DVLOG(3) << "Playing audible for op_id: " << audible_transmit->op_id; |
| - player_audible_->Play( |
| - samples_cache_audible_.GetValue(current_token_audible_)); |
| - stop_audible_playback_timer_.Start( |
| - FROM_HERE, |
| - audible_transmit->end_time - base::Time::Now(), |
| - this, |
| - &AudioDirectiveHandler::ProcessNextTransmit); |
| - } else if (!audible_transmit && player_audible_->IsPlaying()) { |
| - DVLOG(3) << "Stopping audible playback."; |
| - current_token_audible_.clear(); |
| - stop_audible_playback_timer_.Stop(); |
| - player_audible_->Stop(); |
| - } |
| +void AudioDirectiveHandler::ProcessNextInstruction() { |
| + if (audio_event_timer_.IsRunning()) |
| + audio_event_timer_.Stop(); |
| - scoped_ptr<AudioDirective> inaudible_transmit( |
| - transmits_list_inaudible_.GetActiveDirective()); |
| - if (inaudible_transmit && !player_inaudible_->IsPlaying() && |
| - samples_cache_inaudible_.HasKey(current_token_inaudible_)) { |
| - DVLOG(3) << "Playing inaudible for op_id: " << inaudible_transmit->op_id; |
| - player_inaudible_->Play( |
| - samples_cache_inaudible_.GetValue(current_token_inaudible_)); |
| - stop_inaudible_playback_timer_.Start( |
| - FROM_HERE, |
| - inaudible_transmit->end_time - base::Time::Now(), |
| - this, |
| - &AudioDirectiveHandler::ProcessNextTransmit); |
| - } else if (!inaudible_transmit && player_inaudible_->IsPlaying()) { |
| - DVLOG(3) << "Stopping inaudible playback."; |
| - current_token_inaudible_.clear(); |
| - stop_inaudible_playback_timer_.Stop(); |
| - player_inaudible_->Stop(); |
| + // Change audio_manager_ state for audible transmits. |
| + if (transmits_list_[AUDIBLE].GetActiveDirective()) { |
|
Daniel Erat
2014/10/17 22:25:59
nit: omit curly brackets here and below
rkc
2014/10/18 00:21:54
Done.
|
| + audio_manager_->StartPlaying(AUDIBLE); |
| + } else { |
| + audio_manager_->StopPlaying(AUDIBLE); |
| } |
| -} |
| -void AudioDirectiveHandler::ProcessNextReceive() { |
| - scoped_ptr<AudioDirective> receive(receives_list_.GetActiveDirective()); |
| - |
| - if (receive && !recorder_->IsRecording()) { |
| - DVLOG(3) << "Recording for op_id: " << receive->op_id; |
| - recorder_->Record(); |
| - stop_recording_timer_.Start(FROM_HERE, |
| - receive->end_time - base::Time::Now(), |
| - this, |
| - &AudioDirectiveHandler::ProcessNextReceive); |
| - } else if (!receive && recorder_->IsRecording()) { |
| - DVLOG(3) << "Stopping Recording"; |
| - stop_recording_timer_.Stop(); |
| - recorder_->Stop(); |
| + // Change audio_manager_ state for inaudible transmits. |
| + if (transmits_list_[INAUDIBLE].GetActiveDirective()) { |
| + audio_manager_->StartPlaying(INAUDIBLE); |
| + } else { |
| + audio_manager_->StopPlaying(INAUDIBLE); |
| } |
| -} |
| -void AudioDirectiveHandler::PlayToken(const std::string token, bool audible) { |
| - std::string valid_token = FromUrlSafe(token); |
| + // Change audio_manager_ state for audible receives. |
| + if (receives_list_[AUDIBLE].GetActiveDirective()) { |
| + audio_manager_->StartRecording(AUDIBLE); |
| + } else { |
| + audio_manager_->StopRecording(AUDIBLE); |
| + } |
| - // If the token has been encoded already, use the cached samples. |
| - if (audible && samples_cache_audible_.HasKey(valid_token)) { |
| - current_token_audible_ = token; |
| - ProcessNextTransmit(); |
| - } else if (!audible && samples_cache_inaudible_.HasKey(valid_token)) { |
| - current_token_inaudible_ = token; |
| - ProcessNextTransmit(); |
| + // Change audio_manager_ state for inaudible receives. |
| + if (receives_list_[INAUDIBLE].GetActiveDirective()) { |
| + audio_manager_->StartRecording(INAUDIBLE); |
| } else { |
| - // Otherwise, encode the token and then play it. |
| - encode_cb_.Run(valid_token, |
| - audible, |
| - base::Bind(&AudioDirectiveHandler::PlayEncodedToken, |
| - base::Unretained(this))); |
| + audio_manager_->StopRecording(INAUDIBLE); |
| + } |
| + |
| + base::TimeDelta next_event_time = NextInstructionExpiry(); |
| + if (next_event_time > base::TimeDelta::FromMilliseconds(0)) { |
| + audio_event_timer_.Start(FROM_HERE, |
| + next_event_time, |
| + this, |
| + &AudioDirectiveHandler::ProcessNextInstruction); |
| } |
| } |
| -void AudioDirectiveHandler::PlayEncodedToken( |
| - const std::string& token, |
| - bool audible, |
| - const scoped_refptr<media::AudioBusRefCounted>& samples) { |
| - DVLOG(3) << "Token " << token << "[audible:" << audible << "] encoded."; |
| - if (audible) { |
| - samples_cache_audible_.Add(token, samples); |
| - current_token_audible_ = token; |
| - // Force process transmits to pick up the new token. |
| - if (player_audible_->IsPlaying()) |
| - player_audible_->Stop(); |
| - } else { |
| - samples_cache_inaudible_.Add(token, samples); |
| - current_token_inaudible_ = token; |
| - // Force process transmits to pick up the new token. |
| - if (player_inaudible_->IsPlaying()) |
| - player_inaudible_->Stop(); |
| +base::TimeDelta AudioDirectiveHandler::NextInstructionExpiry() { |
| + // We cache now, since, calling Now() twice doesn't gaurantee that the time |
|
Daniel Erat
2014/10/17 22:25:59
nit: guarantee
rkc
2014/10/18 00:21:54
Done.
|
| + // will increase (it may even decrease). This ensures that if we have no |
| + // instructions, we return back a 0 time. |
| + base::Time now = base::Time::Now(); |
| + |
| + base::Time closest_event_time = now; |
| + if (transmits_list_[AUDIBLE].GetActiveDirective()) { |
| + closest_event_time = |
| + transmits_list_[AUDIBLE].GetActiveDirective()->end_time; |
| + } |
| + if (transmits_list_[INAUDIBLE].GetActiveDirective()) { |
|
Daniel Erat
2014/10/17 22:25:59
how about moving this into a helper function so it
rkc
2014/10/18 00:21:54
Done.
|
| + closest_event_time = |
| + std::min(transmits_list_[INAUDIBLE].GetActiveDirective()->end_time, |
| + closest_event_time); |
| + } |
| + if (receives_list_[AUDIBLE].GetActiveDirective()) { |
| + closest_event_time = |
| + std::min(receives_list_[AUDIBLE].GetActiveDirective()->end_time, |
| + closest_event_time); |
| + } |
| + if (receives_list_[INAUDIBLE].GetActiveDirective()) { |
| + closest_event_time = |
| + std::min(receives_list_[INAUDIBLE].GetActiveDirective()->end_time, |
| + closest_event_time); |
| } |
| - ProcessNextTransmit(); |
| + return closest_event_time - now; |
| } |
| } // namespace copresence |