Home | History | Annotate | Download | only in pulse
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 // Creates an audio output stream based on the PulseAudio asynchronous API;
      6 // specifically using the pa_threaded_mainloop model.
      7 //
      8 // If the stream is successfully opened, Close() must be called before the
      9 // stream is deleted as Close() is responsible for ensuring resource cleanup
     10 // occurs.
     11 //
     12 // This object is designed so that all AudioOutputStream methods will be called
     13 // on the same thread that created the object.
     14 //
     15 // WARNING: This object blocks on internal PulseAudio calls in Open() while
     16 // waiting for PulseAudio's context structure to be ready.  It also blocks in
     17 // inside PulseAudio in Start() and repeated during playback, waiting for
     18 // PulseAudio write callbacks to occur.
     19 
     20 #ifndef MEDIA_AUDIO_PULSE_PULSE_OUTPUT_H_
     21 #define MEDIA_AUDIO_PULSE_PULSE_OUTPUT_H_
     22 
     23 #include <string>
     24 
     25 #include "base/memory/scoped_ptr.h"
     26 #include "base/threading/thread_checker.h"
     27 #include "media/audio/audio_io.h"
     28 #include "media/audio/audio_parameters.h"
     29 
     30 struct pa_context;
     31 struct pa_operation;
     32 struct pa_stream;
     33 struct pa_threaded_mainloop;
     34 
     35 namespace media {
     36 class AudioManagerBase;
     37 
     38 class PulseAudioOutputStream : public AudioOutputStream {
     39  public:
     40   PulseAudioOutputStream(const AudioParameters& params,
     41                          const std::string& device_id,
     42                          AudioManagerBase* manager);
     43 
     44   virtual ~PulseAudioOutputStream();
     45 
     46   // Implementation of AudioOutputStream.
     47   virtual bool Open() OVERRIDE;
     48   virtual void Close() OVERRIDE;
     49   virtual void Start(AudioSourceCallback* callback) OVERRIDE;
     50   virtual void Stop() OVERRIDE;
     51   virtual void SetVolume(double volume) OVERRIDE;
     52   virtual void GetVolume(double* volume) OVERRIDE;
     53 
     54  private:
     55   // Called by PulseAudio when |pa_stream_| change state.  If an unexpected
     56   // failure state change happens and |source_callback_| is set
     57   // this method will forward the error via OnError().
     58   static void StreamNotifyCallback(pa_stream* s, void* p_this);
     59 
     60   // Called by PulseAudio when it needs more audio data.
     61   static void StreamRequestCallback(pa_stream* s, size_t len, void* p_this);
     62 
     63   // Fulfill a write request from the write request callback.  Outputs silence
     64   // if the request could not be fulfilled.
     65   void FulfillWriteRequest(size_t requested_bytes);
     66 
     67   // Close() helper function to free internal structs.
     68   void Reset();
     69 
     70   // AudioParameters from the constructor.
     71   const AudioParameters params_;
     72 
     73   // The device ID for the device to open.
     74   const std::string device_id_;
     75 
     76   // Audio manager that created us.  Used to report that we've closed.
     77   AudioManagerBase* manager_;
     78 
     79   // PulseAudio API structs.
     80   pa_context* pa_context_;
     81   pa_threaded_mainloop* pa_mainloop_;
     82   pa_stream* pa_stream_;
     83 
     84   // Float representation of volume from 0.0 to 1.0.
     85   float volume_;
     86 
     87   // Callback to audio data source.  Must only be modified while holding a lock
     88   // on |pa_mainloop_| via pa_threaded_mainloop_lock().
     89   AudioSourceCallback* source_callback_;
     90 
     91   // Container for retrieving data from AudioSourceCallback::OnMoreData().
     92   scoped_ptr<AudioBus> audio_bus_;
     93 
     94   base::ThreadChecker thread_checker_;
     95 
     96   DISALLOW_COPY_AND_ASSIGN(PulseAudioOutputStream);
     97 };
     98 
     99 }  // namespace media
    100 
    101 #endif  // MEDIA_AUDIO_PULSE_PULSE_OUTPUT_H_
    102