summaryrefslogtreecommitdiff
path: root/src/filter/Observer.cxx
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2016-06-22 11:15:49 +0200
committerMax Kellermann <max@duempel.org>2016-07-01 21:04:24 +0200
commit3a212412487e8868946e7c845b6830f880790f91 (patch)
tree5a6120b77a34e1c24da340a66fe5a8e56666333b /src/filter/Observer.cxx
parent5c75096bcd21f2780e469e06bc4fc7bddf75684c (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.cxx115
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;
+}