diff options
author | Max Kellermann <max@duempel.org> | 2016-06-22 11:15:49 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2016-07-01 21:04:24 +0200 |
commit | 3a212412487e8868946e7c845b6830f880790f91 (patch) | |
tree | 5a6120b77a34e1c24da340a66fe5a8e56666333b /src/filter/Observer.cxx | |
parent | 5c75096bcd21f2780e469e06bc4fc7bddf75684c (diff) |
filter/FilterInternal: split class Filter, add class PreparedFilter
For easier state management inside filter plugins.
Diffstat (limited to 'src/filter/Observer.cxx')
-rw-r--r-- | src/filter/Observer.cxx | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/filter/Observer.cxx b/src/filter/Observer.cxx new file mode 100644 index 000000000..b3cadfb30 --- /dev/null +++ b/src/filter/Observer.cxx @@ -0,0 +1,115 @@ +/* + * Copyright 2003-2016 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Observer.hxx" +#include "FilterInternal.hxx" +#include "util/ConstBuffer.hxx" + +#include <assert.h> + +class FilterObserver::PreparedProxy final : public PreparedFilter { + FilterObserver &observer; + + PreparedFilter *const prepared_filter; + Proxy *child = nullptr; + +public: + PreparedProxy(FilterObserver &_observer, + PreparedFilter *_prepared_filter) + :observer(_observer), + prepared_filter(_prepared_filter) {} + + ~PreparedProxy() { + assert(child == nullptr); + assert(observer.proxy == this); + + observer.proxy = nullptr; + } + + void Clear(gcc_unused Proxy *_child) { + assert(child == _child); + child = nullptr; + } + + Filter *Get(); + + Filter *Open(AudioFormat &af, Error &error) override; +}; + +class FilterObserver::Proxy final : public Filter { + PreparedProxy &parent; + + Filter *const filter; + +public: + Proxy(PreparedProxy &_parent, Filter *_filter) + :Filter(_filter->GetOutAudioFormat()), + parent(_parent), filter(_filter) {} + + ~Proxy() { + parent.Clear(this); + delete filter; + } + + Filter *Get() { + return filter; + } + + ConstBuffer<void> FilterPCM(ConstBuffer<void> src, + Error &error) override { + return filter->FilterPCM(src, error); + } +}; + +Filter * +FilterObserver::PreparedProxy::Get() +{ + return child != nullptr + ? child->Get() + : nullptr; +} + +Filter * +FilterObserver::PreparedProxy::Open(AudioFormat &af, Error &error) +{ + assert(child == nullptr); + + Filter *f = prepared_filter->Open(af, error); + if (f == nullptr) + return f; + + return child = new Proxy(*this, f); +} + +PreparedFilter * +FilterObserver::Set(PreparedFilter *pf) +{ + assert(proxy == nullptr); + + return proxy = new PreparedProxy(*this, pf); +} + +Filter * +FilterObserver::Get() +{ + return proxy != nullptr + ? proxy->Get() + : nullptr; +} |