15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates an output stream based on the ALSA PCM interface.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On device write failure, the stream will move itself to an invalid state.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// No more data will be pulled from the data source, or written to the device.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All calls to public API functions will either no-op themselves, or return an
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// error if possible.  Specifically, If the stream is in an error state, Open()
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will return false, and Start() will call OnError() immediately on the
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provided callback.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the stream is successfully opened, Close() must be called.  After Close
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// has been called, the object should be regarded as deleted and not touched.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AlsaPcmOutputStream is a single threaded class that should only be used from
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the audio thread. When modifying the code in this class, please read the
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threading assumptions at the top of the implementation.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <alsa/asoundlib.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_parameters.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace base {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MessageLoop;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AlsaWrapper;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioManagerLinux;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChannelMixer;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SeekableBuffer;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MEDIA_EXPORT AlsaPcmOutputStream : public AudioOutputStream {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // String for the generic "default" ALSA device that has the highest
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compatibility and chance of working.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kDefaultDevice[];
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pass this to the AlsaPcmOutputStream if you want to attempt auto-selection
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the audio device.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kAutoSelectDevice[];
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prefix for device names to enable ALSA library resampling.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kPlugPrefix[];
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The minimum latency that is accepted by the device.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const uint32 kMinLatencyMicros;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a PCM Output stream for the ALSA device identified by
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |device_name|.  The AlsaPcmOutputStream uses |wrapper| to communicate with
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the alsa libraries, allowing for dependency injection during testing.  All
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // requesting of data, and writing to the alsa device will be done on
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |message_loop|.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If unsure of what to use for |device_name|, use |kAutoSelectDevice|.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AlsaPcmOutputStream(const std::string& device_name,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const AudioParameters& params,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      AlsaWrapper* wrapper,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      AudioManagerLinux* manager);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AlsaPcmOutputStream();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation of AudioOutputStream.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Open() OVERRIDE;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Close() OVERRIDE;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Start(AudioSourceCallback* callback) OVERRIDE;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Stop() OVERRIDE;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetVolume(double volume) OVERRIDE;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetVolume(double* volume) OVERRIDE;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class AlsaPcmOutputStreamTest;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           AutoSelectDevice_DeviceSelect);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           AutoSelectDevice_FallbackDevices);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_Negative);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_StopStream);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_Underrun);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_FullBuffer);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, ConstructedState);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, LatencyFloor);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, OpenClose);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, PcmOpenFailed);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, PcmSetParamsFailed);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, ScheduleNextWrite);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ScheduleNextWrite_StopStream);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, StartStop);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_FinishedPacket);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_NormalPacket);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_StopStream);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_WriteFails);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flags indicating the state of the stream.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum InternalState {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kInError = 0,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kCreated,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kIsOpened,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kIsPlaying,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kIsStopped,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kIsClosed
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend std::ostream& operator<<(std::ostream& os, InternalState);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Functions to get another packet from the data source and write it into the
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ALSA device.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BufferPacket(bool* source_exhausted);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WritePacket();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WriteTask();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ScheduleNextWrite(bool source_exhausted);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Utility functions for talking with the ALSA API.
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static base::TimeDelta FramesToTimeDelta(int frames, double sample_rate);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string FindDeviceForChannels(uint32 channels);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snd_pcm_sframes_t GetAvailableFrames();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snd_pcm_sframes_t GetCurrentDelay();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempts to find the best matching linux audio device for the given number
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of channels.  This function will set |device_name_| and |channel_mixer_|.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snd_pcm_t* AutoSelectDevice(uint32 latency);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Functions to safeguard state transitions.  All changes to the object state
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should go through these functions.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CanTransitionTo(InternalState to);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InternalState TransitionTo(InternalState to);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InternalState state();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true when we're on the audio thread or if the audio thread's
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message loop is NULL (which will happen during shutdown).
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsOnAudioThread() const;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // API for Proxying calls to the AudioSourceCallback provided during
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start().
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(ajwong): This is necessary because the ownership semantics for the
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |source_callback_| object are incorrect in AudioRenderHost. The callback
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is passed into the output stream, but ownership is not transfered which
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // requires a synchronization on access of the |source_callback_| to avoid
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using a deleted callback.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int RunDataCallback(AudioBus* audio_bus, AudioBuffersState buffers_state);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunErrorCallback(int code);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Changes the AudioSourceCallback to proxy calls to.  Pass in NULL to
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // release ownership of the currently registered callback.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_source_callback(AudioSourceCallback* callback);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Configuration constants from the constructor.  Referenceable by all threads
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since they are constants.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string requested_device_name_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const snd_pcm_format_t pcm_format_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 channels_;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ChannelLayout channel_layout_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 sample_rate_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 bytes_per_sample_;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 bytes_per_frame_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Device configuration data. Populated after OpenTask() completes.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string device_name_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 packet_size_;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta latency_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bytes_per_output_frame_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 alsa_buffer_frames_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flag indicating the code should stop reading from the data source or
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // writing to the ALSA device.  This is set because the device has entered
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an unrecoverable error state, or the ClosedTask() has executed.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool stop_stream_;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wrapper class to invoke all the ALSA functions.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AlsaWrapper* wrapper_;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Audio manager that created us.  Used to report that we've been closed.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioManagerLinux* manager_;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Message loop to use for polling. The object is owned by the AudioManager.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hold a reference to the audio thread message loop since
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AudioManagerBase::ShutDown() can invalidate the message loop pointer
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before the stream gets deleted.
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop* message_loop_;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle to the actual PCM playback device.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snd_pcm_t* playback_handle_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<media::SeekableBuffer> buffer_;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 frames_per_packet_;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allows us to run tasks on the AlsaPcmOutputStream instance which are
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bound by its lifetime.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<AlsaPcmOutputStream> weak_factory_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InternalState state_;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float volume_;  // Volume level from 0.0 to 1.0.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioSourceCallback* source_callback_;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Container for retrieving data from AudioSourceCallback::OnMoreData().
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> audio_bus_;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Channel mixer and temporary bus for the final mixed channel data.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ChannelMixer> channel_mixer_;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> mixed_audio_bus_;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStream);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MEDIA_EXPORT std::ostream& operator<<(std::ostream& os,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      AlsaPcmOutputStream::InternalState);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};  // namespace media
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
229