+signal_data* MathSignal::signal_from_name(const std::string& name)
+{
+ // If the expression contains the math signal itself, we must add every sample to
+ // the output segment immediately so that it can be accessed
+ const QString sig_name = QString::fromStdString(name);
+ if (sig_name == this->name())
+ generation_chunk_size_ = 1;
+
+ // Look up signal in the map and if it doesn't exist yet, add it for future use
+
+ auto element = input_signals_.find(name);
+
+ if (element != input_signals_.end()) {
+ return &(element->second);
+ } else {
+ const vector< shared_ptr<SignalBase> > signalbases = session_.signalbases();
+
+ for (const shared_ptr<SignalBase>& sb : signalbases)
+ if (sb->name() == sig_name) {
+ if (!sb->analog_data())
+ continue;
+
+ connect(sb->analog_data().get(), SIGNAL(samples_added(SharedPtrToSegment, uint64_t, uint64_t)),
+ this, SLOT(on_data_received()));
+ connect(sb->analog_data().get(), SIGNAL(segment_completed()),
+ this, SLOT(on_data_received()));
+
+ connect(sb.get(), SIGNAL(enabled_changed(bool)),
+ this, SLOT(on_enabled_changed()));
+
+ return &(input_signals_.insert({name, signal_data(sb)}).first->second);
+ }
+ }
+
+ // If we reach this point, no valid signal was found with the supplied name
+ if (error_type_ == MATH_ERR_NONE)
+ set_error(MATH_ERR_INVALID_SIGNAL, QString(tr("\"%1\" isn't a valid analog signal")) \
+ .arg(QString::fromStdString(name)));
+
+ return nullptr;
+}
+
+void MathSignal::update_signal_sample(signal_data* sig_data, uint32_t segment_id, uint64_t sample_num)
+{
+ assert(sig_data);
+
+ // Update the value only if a different sample is requested
+ if (sig_data->sample_num == sample_num)
+ return;
+
+ assert(sig_data->sb);
+ const shared_ptr<pv::data::Analog> analog = sig_data->sb->analog_data();
+ assert(analog);
+
+ assert(segment_id < analog->analog_segments().size());
+
+ const shared_ptr<AnalogSegment> segment = analog->analog_segments().at(segment_id);
+
+ sig_data->sample_num = sample_num;
+
+ if (sample_num < segment->get_sample_count())
+ sig_data->sample_value = segment->get_sample(sample_num);
+ else
+ sig_data->sample_value = 0;
+
+ // We only have a reference if this signal is used as a scalar;
+ // if it's used by a function, it's null
+ if (sig_data->ref)
+ *(sig_data->ref) = sig_data->sample_value;
+}
+
+bool MathSignal::all_input_signals_enabled(QString &disabled_signals) const
+{
+ bool all_enabled = true;
+
+ disabled_signals.clear();
+
+ for (auto input_signal : input_signals_) {
+ const shared_ptr<SignalBase>& sb = input_signal.second.sb;
+
+ if (!sb->enabled()) {
+ all_enabled = false;
+ disabled_signals += disabled_signals.isEmpty() ?
+ sb->name() : ", " + sb->name();
+ }
+ }
+
+ return all_enabled;
+}
+