1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_PATCH_BUILDER_H
18 #define ANDROID_PATCH_BUILDER_H
19 
20 #include <functional>
21 #include <utility>
22 
23 #include <system/audio.h>
24 #include <utils/StrongPointer.h>
25 
26 // This is a header-only utility.
27 
28 namespace android {
29 
30 class PatchBuilder {
31   public:
32     using mix_usecase_t = decltype(audio_port_config_mix_ext::usecase);
33 
34     PatchBuilder() = default;
35 
36     // All existing methods operating on audio patches take a pointer to const.
37     // It's OK to construct a temporary PatchBuilder while preparing a parameter
38     // to such a function because the Builder will be kept alive until the code
39     // execution reaches the function call statement semicolon.
patch()40     const struct audio_patch* patch() const { return &mPatch; }
41 
42     template<typename T, typename... S>
addSink(T && t,S &&...s)43     PatchBuilder& addSink(T&& t, S&&... s) {
44         sinks().add(std::forward<T>(t), std::forward<S>(s)...);
45         return *this;
46     }
47     // Explicit type of the second parameter allows clients to provide the struct inline.
48     template<typename T>
addSink(T && t,const mix_usecase_t & update)49     PatchBuilder& addSink(T&& t, const mix_usecase_t& update) {
50         sinks().add(std::forward<T>(t), update);
51         return *this;
52     }
53     template<typename T, typename... S>
addSource(T && t,S &&...s)54     PatchBuilder& addSource(T&& t, S&&... s) {
55         sources().add(std::forward<T>(t), std::forward<S>(s)...);
56         return *this;
57     }
58     // Explicit type of the second parameter allows clients to provide the struct inline.
59     template<typename T>
addSource(T && t,const mix_usecase_t & update)60     PatchBuilder& addSource(T&& t, const mix_usecase_t& update) {
61         sources().add(std::forward<T>(t), update);
62         return *this;
63     }
64 
65   private:
66     struct PortCfgs {
PortCfgsPortCfgs67         PortCfgs(unsigned int *countPtr, struct audio_port_config *portCfgs)
68                 : mCountPtr(countPtr), mPortCfgs(portCfgs) {}
addPortCfgs69         audio_port_config& add(const audio_port_config& portCfg) {
70             return *advance() = portCfg;
71         }
72         template<typename T>
addPortCfgs73         audio_port_config& add(const sp<T>& entity) {
74             audio_port_config* added = advance();
75             entity->toAudioPortConfig(added);
76             return *added;
77         }
78         template<typename T>
addPortCfgs79         void add(const sp<T>& entity, const mix_usecase_t& usecaseUpdate) {
80             add(entity).ext.mix.usecase = usecaseUpdate;
81         }
82         template<typename T>
addPortCfgs83         void add(const sp<T>& entity,
84                 std::function<mix_usecase_t(const mix_usecase_t&)> usecaseUpdater) {
85             mix_usecase_t* usecase = &add(entity).ext.mix.usecase;
86             *usecase = usecaseUpdater(*usecase);
87         }
advancePortCfgs88         struct audio_port_config* advance() {
89             return &mPortCfgs[(*mCountPtr)++];
90         }
91         unsigned int *mCountPtr;
92         struct audio_port_config *mPortCfgs;
93     };
94 
sinks()95     PortCfgs sinks() { return PortCfgs(&mPatch.num_sinks, mPatch.sinks); }
sources()96     PortCfgs sources() { return PortCfgs(&mPatch.num_sources, mPatch.sources); }
97 
98     struct audio_patch mPatch = {};
99 };
100 
101 }  // namespace android
102 
103 #endif  // ANDROID_PATCH_BUILDER_H
104