1// Copyright (C) 2022 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {produce} from 'immer'; 16import m from 'mithril'; 17 18import {Actions} from '../../common/actions'; 19import {RecordMode} from '../../common/state'; 20import {globals} from '../globals'; 21import {Slider, SliderAttrs} from '../record_widgets'; 22 23import {RecordingSectionAttrs} from './recording_sections'; 24 25export class RecordingSettings implements 26 m.ClassComponent<RecordingSectionAttrs> { 27 view({attrs}: m.CVnode<RecordingSectionAttrs>) { 28 const S = (x: number) => x * 1000; 29 const M = (x: number) => x * 1000 * 60; 30 const H = (x: number) => x * 1000 * 60 * 60; 31 32 const cfg = globals.state.recordConfig; 33 34 const recButton = (mode: RecordMode, title: string, img: string) => { 35 const checkboxArgs = { 36 checked: cfg.mode === mode, 37 onchange: (e: InputEvent) => { 38 const checked = (e.target as HTMLInputElement).checked; 39 if (!checked) return; 40 const traceCfg = produce(globals.state.recordConfig, (draft) => { 41 draft.mode = mode; 42 }); 43 globals.dispatch(Actions.setRecordConfig({config: traceCfg})); 44 }, 45 }; 46 return m( 47 `label${cfg.mode === mode ? '.selected' : ''}`, 48 m(`input[type=radio][name=rec_mode]`, checkboxArgs), 49 m(`img[src=${globals.root}assets/${img}]`), 50 m('span', title)); 51 }; 52 53 return m( 54 `.record-section${attrs.cssClass}`, 55 m('header', 'Recording mode'), 56 m('.record-mode', 57 recButton('STOP_WHEN_FULL', 'Stop when full', 'rec_one_shot.png'), 58 recButton('RING_BUFFER', 'Ring buffer', 'rec_ring_buf.png'), 59 recButton('LONG_TRACE', 'Long trace', 'rec_long_trace.png')), 60 61 m(Slider, { 62 title: 'In-memory buffer size', 63 icon: '360', 64 values: [4, 8, 16, 32, 64, 128, 256, 512], 65 unit: 'MB', 66 set: (cfg, val) => cfg.bufferSizeMb = val, 67 get: (cfg) => cfg.bufferSizeMb, 68 } as SliderAttrs), 69 70 m(Slider, { 71 title: 'Max duration', 72 icon: 'timer', 73 values: [S(10), S(15), S(30), S(60), M(5), M(30), H(1), H(6), H(12)], 74 isTime: true, 75 unit: 'h:m:s', 76 set: (cfg, val) => cfg.durationMs = val, 77 get: (cfg) => cfg.durationMs, 78 } as SliderAttrs), 79 m(Slider, { 80 title: 'Max file size', 81 icon: 'save', 82 cssClass: cfg.mode !== 'LONG_TRACE' ? '.hide' : '', 83 values: [5, 25, 50, 100, 500, 1000, 1000 * 5, 1000 * 10], 84 unit: 'MB', 85 set: (cfg, val) => cfg.maxFileSizeMb = val, 86 get: (cfg) => cfg.maxFileSizeMb, 87 } as SliderAttrs), 88 m(Slider, { 89 title: 'Flush on disk every', 90 cssClass: cfg.mode !== 'LONG_TRACE' ? '.hide' : '', 91 icon: 'av_timer', 92 values: [100, 250, 500, 1000, 2500, 5000], 93 unit: 'ms', 94 set: (cfg, val) => cfg.fileWritePeriodMs = val, 95 get: (cfg) => cfg.fileWritePeriodMs || 0, 96 } as SliderAttrs)); 97 } 98} 99