+ stack_.push_back(decoder);
+}
+
+void DecoderStack::remove(int index)
+{
+ assert(index >= 0);
+ assert(index < (int)stack_.size());
+
+ // Find the decoder in the stack
+ auto iter = stack_.begin();
+ for (int i = 0; i < index; i++, iter++)
+ assert(iter != stack_.end());
+
+ // Delete the element
+ stack_.erase(iter);
+}
+
+double DecoderStack::samplerate() const
+{
+ return samplerate_;
+}
+
+double DecoderStack::start_time() const
+{
+ return start_time_;
+}
+
+int64_t DecoderStack::samples_decoded() const
+{
+ lock_guard<mutex> decode_lock(output_mutex_);
+ return samples_decoded_;
+}
+
+std::vector<Row> DecoderStack::get_visible_rows() const
+{
+ lock_guard<mutex> lock(output_mutex_);
+
+ vector<Row> rows;
+
+ for (const shared_ptr<decode::Decoder> &dec : stack_)
+ {
+ assert(dec);
+ if (!dec->shown())
+ continue;
+
+ const srd_decoder *const decc = dec->decoder();
+ assert(dec->decoder());
+
+ // Add a row for the decoder if it doesn't have a row list
+ if (!decc->annotation_rows)
+ rows.push_back(Row(decc));
+
+ // Add the decoder rows
+ for (const GSList *l = decc->annotation_rows; l; l = l->next)
+ {
+ const srd_decoder_annotation_row *const ann_row =
+ (srd_decoder_annotation_row *)l->data;
+ assert(ann_row);
+ rows.push_back(Row(decc, ann_row));
+ }
+ }
+
+ return rows;