diff --git a/src/stream.cpp b/src/stream.cpp new file mode 100644 --- /dev/null +++ b/src/stream.cpp @@ -0,0 +1,200 @@ +/* + Copyright © 2018 Hasan Yavuz Özderya + + This file is part of serialplot. + + serialplot 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 3 of the License, or + (at your option) any later version. + + serialplot 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 serialplot. If not, see . +*/ + +#include "stream.h" +#include "ringbuffer.h" +#include "indexbuffer.h" + +Stream::Stream(unsigned nc, bool x, unsigned ns) : + _infoModel(nc) +{ + _numSamples = ns; + _paused = false; + + // create xdata buffer + _hasx = x; + if (x) + { + xData = new RingBuffer(ns); + } + else + { + xData = new IndexBuffer(ns); + } + + // create channels + for (unsigned i = 0; i < nc; i++) + { + auto c = new StreamChannel(i, xData, new RingBuffer(ns), &_infoModel); + channels.append(c); + } +} + +Stream::~Stream() +{ + for (auto ch : channels) + { + delete ch; + } + delete xData; +} + +bool Stream::hasX() const +{ + return _hasx; +} + +unsigned Stream::numChannels() const +{ + return channels.length(); +} + +unsigned Stream::numSamples() const +{ + return _numSamples; +} + +const StreamChannel* Stream::channel(unsigned index) const +{ + Q_ASSERT(index < numChannels()); + return channels[index]; +} + +StreamChannel* Stream::channel(unsigned index) +{ + return const_cast(static_cast(*this).channel(index)); +} + +const ChannelInfoModel* Stream::infoModel() const +{ + return &_infoModel; +} + +ChannelInfoModel* Stream::infoModel() +{ + return const_cast(static_cast(*this).infoModel()); +} + +void Stream::setNumChannels(unsigned nc, bool x) +{ + unsigned oldNum = numChannels(); + if (oldNum == nc && x == _hasx) return; + + // adjust the number of channels + if (nc > oldNum) + { + for (unsigned i = oldNum; i < nc; i++) + { + auto c = new StreamChannel(i, xData, new RingBuffer(_numSamples), &_infoModel); + channels.append(c); + } + } + else if (nc < oldNum) + { + for (unsigned i = oldNum-1; i > nc-1; i--) + { + delete channels.takeLast(); + } + } + + // change the xdata + if (x != _hasx) + { + if (x) + { + xData = new RingBuffer(_numSamples); + } + else + { + xData = new IndexBuffer(_numSamples); + } + + for (auto c : channels) + { + c->setX(xData); + } + _hasx = x; + } + + if (nc != oldNum) + { + _infoModel.setNumOfChannels(nc); + // TODO: how about X change? + emit numChannelsChanged(nc); + } + + Sink::setNumChannels(nc, x); +} + +void Stream::feedIn(const SamplePack& data) +{ + Q_ASSERT(data.numChannels() == numChannels() && + data.hasX() == hasX()); + + if (_paused) return; + + unsigned ns = data.numSamples(); + if (_hasx) + { + static_cast(xData)->addSamples(data.xData(), ns); + } + for (unsigned i = 0; i < numChannels(); i++) + { + static_cast(channels[i]->yData())->addSamples(data.data(i), ns); + } + + Sink::feedIn(data); + + emit dataAdded(); +} + +void Stream::pause(bool paused) +{ + _paused = paused; +} + +void Stream::clear() +{ + for (auto c : channels) + { + static_cast(c->yData())->clear(); + } +} + +void Stream::setNumSamples(unsigned value) +{ + if (value == _numSamples) return; + _numSamples = value; + + xData->resize(value); + for (auto c : channels) + { + static_cast(c->yData())->resize(value); + } +} + +void Stream::saveSettings(QSettings* settings) const +{ + _infoModel.saveSettings(settings); +} + +void Stream::loadSettings(QSettings* settings) +{ + _infoModel.loadSettings(settings); +}