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