blob: b1fd7612a4a52922d9539840160d015084f0f6fc [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_BIN_MEDIA_AUDIO_CORE_AUDIO_OBJECT_H_
#define GARNET_BIN_MEDIA_AUDIO_CORE_AUDIO_OBJECT_H_
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include "garnet/bin/media/audio_core/fwd_decls.h"
#include "lib/fxl/synchronization/thread_annotations.h"
namespace media {
namespace audio {
// An audio object is the simple base class for 4 major types of audio objects
// in the mixer; Outputs, Inputs, AudioRenderers and AudioCapturers. It ensures
// that each of these objects is intrusively ref-counted, and remembers its type
// so that it may be safely downcast from a generic audio object to something
// more specific.
class AudioObject : public fbl::RefCounted<AudioObject> {
public:
enum class Type {
Output,
Input,
AudioRenderer,
AudioCapturer,
};
static std::shared_ptr<AudioLink> LinkObjects(
const fbl::RefPtr<AudioObject>& source,
const fbl::RefPtr<AudioObject>& dest);
static void RemoveLink(const AudioLinkPtr& link);
void UnlinkSources();
void UnlinkDestinations();
void Unlink() {
UnlinkSources();
UnlinkDestinations();
}
// PreventNewLinks
//
// Clears the new_links_allowed flag from within the context of the
// links_lock. This ensures that no new links may be added to this object
// anymore. Calling PreventNewLinks is one of the first steps in the process
// of shutting down an AudioObject.
//
// TODO(johngro) : Consider eliminating this; given the way that links are
// created and destroyed, it is not clear if it is needed anymore.
void PreventNewLinks() {
fbl::AutoLock lock(&links_lock_);
new_links_allowed_ = false;
}
Type type() const { return type_; }
bool is_output() const { return type() == Type::Output; }
bool is_input() const { return type() == Type::Input; }
bool is_audio_renderer() const { return type() == Type::AudioRenderer; }
bool is_audio_capturer() const { return type() == Type::AudioCapturer; }
protected:
friend class fbl::RefPtr<AudioObject>;
explicit AudioObject(Type type) : type_(type) {}
virtual ~AudioObject() {}
// Initialize(Source|Dest)Link
//
// Called on the AudioCore's main message loop any time a source and a
// destination are being linked via AudioObject::LinkObjects. By default,
// these hooks do nothing, but AudioObject subclasses may use them to set the
// properties of a link (or reject the link) before the link gets added to the
// source and destination link sets.
//
// For example, Sources like a audio out override InitializeDestLink in order
// to set the source gain and to make a copy of their pending packet
// queue.packet queue. Destinations like an output override
// InitializeSourceLink in order to choose and intialize an appropriate
// resampling filter.
//
// @return MediaResult::OK if initialization succeeded, or an appropriate
// error code otherwise.
virtual zx_status_t InitializeSourceLink(const AudioLinkPtr& link);
virtual zx_status_t InitializeDestLink(const AudioLinkPtr& link);
fbl::Mutex links_lock_;
// The set of links which this audio device is acting as a source for (eg; the
// destinations that this object is sending to). The target of each of these
// links must be a either an Output or a AudioCapturer.
AudioLinkSet dest_links_ FXL_GUARDED_BY(links_lock_);
// The set of links which this audio device is acting as a destination for
// (eg; the sources that that the object is receiving from). The target of
// each of these links must be a either an Output or a AudioCapturer.
//
// TODO(johngro): Order this by priority. Use a fbl::WAVLTree (or some other
// form of ordered intrusive container) so that we can easily remove and
// re-insert a link if/when priority changes.
//
// Right now, we have no priorities, so this is just a set of
// AudioRenderer/output links.
AudioLinkSet source_links_ FXL_GUARDED_BY(links_lock_);
private:
void UnlinkCleanup(AudioLinkSet* links);
const Type type_;
bool new_links_allowed_ FXL_GUARDED_BY(links_lock_) = true;
};
} // namespace audio
} // namespace media
#endif // GARNET_BIN_MEDIA_AUDIO_CORE_AUDIO_OBJECT_H_