blob: 6692ebac611de7a8e29461fcaa0cabea60732185 [file] [log] [blame]
/*
* Copyright 2014 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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.
*/
#ifndef MEDIA_AUDIO_SHELL_PULSE_AUDIO_H_
#define MEDIA_AUDIO_SHELL_PULSE_AUDIO_H_
#include <pulse/pulseaudio.h>
#include <set>
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
namespace media {
class ShellPulseAudioContext;
class ShellPulseAudioStream {
public:
class Host {
public:
typedef base::Callback<void(const uint8*, size_t)> WriteFunc;
virtual ~Host() {}
virtual void RequestFrame(size_t length, WriteFunc write) = 0;
};
ShellPulseAudioStream();
~ShellPulseAudioStream();
bool Initialize(ShellPulseAudioContext* context, Host* host, int rate,
int channel);
bool Play();
bool Pause();
uint64 GetPlaybackCursorInMicroSeconds();
void RequestFrame();
private:
enum {
kInitial = 0,
kSuccess,
kFailure
};
static const int kMinLatency = 1000000;
static const int kMaxLatency = 4000000;
static void RequestCallback(pa_stream* s, size_t length, void* userdata);
void HandleRequest(size_t length);
static void UnderflowCallback(pa_stream* s, void* userdata);
void HandleUnderflow();
static void SuccessCallback(pa_stream* s, int success, void* userdata);
bool Cork(bool pause);
void WriteFrame(const uint8* data, size_t size);
ShellPulseAudioContext* context_;
int latency_;
pa_buffer_attr buf_attr_;
pa_sample_spec sample_spec_;
pa_stream* stream_;
size_t last_request_size_;
Host* host_;
DISALLOW_COPY_AND_ASSIGN(ShellPulseAudioStream);
};
class ShellPulseAudioContext {
public:
ShellPulseAudioContext();
~ShellPulseAudioContext();
bool Initialize();
pa_context* GetContext();
void Iterate();
ShellPulseAudioStream* CreateStream(ShellPulseAudioStream::Host* host,
int rate, int channel);
void DestroyStream(ShellPulseAudioStream* stream);
base::Lock& lock() { return lock_; }
private:
typedef std::set<ShellPulseAudioStream*> Streams;
enum {
kInitial = 0,
kReady,
kError
};
static void StateCallback(pa_context* c, void* userdata);
pa_mainloop* mainloop_;
pa_context* context_;
base::Thread pulse_thread_;
Streams streams_;
base::Lock lock_;
DISALLOW_COPY_AND_ASSIGN(ShellPulseAudioContext);
};
} // namespace media
#endif // MEDIA_AUDIO_SHELL_PULSE_AUDIO_H_