1 /* 2 * Copyright (C) 2021 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2021 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 7 февр. 2021 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #include <ui/ctl/ctl.h> 23 #include <core/port_data.h> 24 25 namespace lsp 26 { 27 namespace ctl 28 { 29 const ctl_class_t CtlStream::metadata = { "CtlStream", &CtlWidget::metadata }; 30 CtlStream(CtlRegistry * src,LSPMesh * mesh)31 CtlStream::CtlStream(CtlRegistry *src, LSPMesh *mesh): CtlWidget(src, mesh) 32 { 33 pClass = &metadata; 34 pPort = NULL; 35 nMaxDots = -1; 36 fTransparency = 0.0f; 37 pMesh = NULL; 38 } 39 ~CtlStream()40 CtlStream::~CtlStream() 41 { 42 if (pMesh != NULL) 43 { 44 mesh_t::destroy(pMesh); 45 pMesh = NULL; 46 } 47 48 sStrobes.destroy(); 49 sMaxDots.destroy(); 50 } 51 init()52 void CtlStream::init() 53 { 54 CtlWidget::init(); 55 56 LSPMesh *mesh = widget_cast<LSPMesh>(pWidget); 57 if (mesh == NULL) 58 return; 59 60 // Initialize color controllers 61 sColor.init_hsl(pRegistry, mesh, mesh->color(), A_COLOR, A_HUE_ID, A_SAT_ID, A_LIGHT_ID); 62 63 // Initialize expressions 64 sStrobes.init(pRegistry, this); 65 sMaxDots.init(pRegistry, this); 66 } 67 set(widget_attribute_t att,const char * value)68 void CtlStream::set(widget_attribute_t att, const char *value) 69 { 70 LSPMesh *mesh = widget_cast<LSPMesh>(pWidget); 71 72 switch (att) 73 { 74 case A_ID: 75 BIND_PORT(pRegistry, pPort, value); 76 break; 77 case A_WIDTH: 78 if (mesh != NULL) 79 PARSE_INT(value, mesh->set_line_width(__)); 80 break; 81 case A_CENTER: 82 if (mesh != NULL) 83 PARSE_INT(value, mesh->set_center_id(__)); 84 break; 85 case A_FILL: 86 PARSE_FLOAT(value, fTransparency = __); 87 break; 88 case A_X_INDEX: 89 if (mesh != NULL) 90 PARSE_INT(value, mesh->set_x_index(__)); 91 break; 92 case A_Y_INDEX: 93 if (mesh != NULL) 94 PARSE_INT(value, mesh->set_y_index(__)); 95 break; 96 case A_S_INDEX: 97 if (mesh != NULL) 98 PARSE_INT(value, mesh->set_s_index(__)); 99 break; 100 case A_STROBE: 101 if (mesh != NULL) 102 PARSE_BOOL(value, mesh->set_strobes(__)); 103 break; 104 case A_STROBES: 105 BIND_EXPR(sStrobes, value); 106 break; 107 case A_MAX_DOTS: 108 BIND_EXPR(sMaxDots, value); 109 break; 110 default: 111 { 112 bool set = sColor.set(att, value); 113 if (!set) 114 CtlWidget::set(att, value); 115 break; 116 } 117 } 118 } 119 end()120 void CtlStream::end() 121 { 122 sColor.set_alpha(fTransparency); 123 CtlWidget::end(); 124 125 trigger_expr(); 126 } 127 trigger_expr()128 void CtlStream::trigger_expr() 129 { 130 LSPMesh *mesh = widget_cast<LSPMesh>(pWidget); 131 132 if (sMaxDots.valid()) 133 { 134 ssize_t dots = sMaxDots.evaluate(); 135 if (nMaxDots != dots) 136 { 137 nMaxDots = dots; 138 commit_data(); 139 } 140 } 141 142 if ((mesh != NULL) && (sStrobes.valid())) 143 { 144 ssize_t value = sStrobes.evaluate(); 145 mesh->set_num_strobes(value); 146 } 147 } 148 notify(CtlPort * port)149 void CtlStream::notify(CtlPort *port) 150 { 151 CtlWidget::notify(port); 152 153 // Trigger expressions 154 trigger_expr(); 155 156 // Commit stream data 157 if ((port != NULL) && (port == pPort)) 158 commit_data(); 159 } 160 commit_data()161 void CtlStream::commit_data() 162 { 163 LSPMesh *mesh = widget_cast<LSPMesh>(pWidget); 164 if (mesh == NULL) 165 return; 166 167 const port_t *mdata = pPort->metadata(); 168 if ((mdata == NULL) || (mdata->role != R_STREAM)) 169 return; 170 171 stream_t *stream = pPort->get_buffer<stream_t>(); 172 if (stream == NULL) 173 return; 174 175 // Need to create mesh? 176 if (pMesh == NULL) 177 { 178 pMesh = mesh_t::create(stream->channels(), stream->capacity()); 179 if (pMesh == NULL) 180 return; 181 pMesh->nBuffers = stream->channels(); 182 } 183 184 // Perform read from stream to mesh 185 size_t last = stream->frame_id(); 186 ssize_t length = stream->get_length(last); 187 ssize_t dots = (nMaxDots >= 0) ? lsp_min(length, nMaxDots) : length; 188 ssize_t off = length - dots; 189 190 for (size_t i=0, n=stream->channels(); i<n; ++i) 191 stream->read(i, pMesh->pvData[i], off, dots); 192 193 // #ifdef LSP_TRACE 194 // const float *vx = pMesh->pvData[0]; 195 // const float *vy = pMesh->pvData[1]; 196 // const float *vs = pMesh->pvData[2]; 197 // 198 // for (ssize_t i=1; i < dots; ++i) 199 // { 200 // float dx = vx[i] - vx[i-1]; 201 // float dy = vy[i] - vy[i-1]; 202 // float s = dx*dx + dy*dy; 203 // if ((s >= 0.125f) && (vs[i] <= 0.5f)) 204 // { 205 // lsp_trace("debug"); 206 // } 207 // } 208 // #endif 209 210 // Set data to mesh 211 mesh->set_data(pMesh->nBuffers, dots, const_cast<const float **>(pMesh->pvData)); 212 } 213 } /* namespace ctl */ 214 } /* namespace lsp */ 215 216 217