* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
#ifdef ENABLE_DECODE
#include <libsigrokdecode/libsigrokdecode.h>
#endif
using std::list;
using std::map;
using std::mutex;
+using std::recursive_mutex;
using std::set;
using std::shared_ptr;
using std::string;
capture_state_(Stopped),
cur_samplerate_(0)
{
- set_default_device();
}
Session::~Session()
// Ensure we are not capturing before setting the device
stop_capture();
+ if (device_)
+ device_->close();
+
device_ = std::move(device);
- device_->create();
+ device_->open();
device_->session()->add_datafeed_callback([=]
(shared_ptr<sigrok::Device> device, shared_ptr<Packet> packet) {
data_feed_in(device, packet);
});
- update_signals(device_);
+ update_signals();
decode_traces_.clear();
// Check that at least one channel is enabled
assert(device_);
- const std::shared_ptr<sigrok::Device> device = device_->device();
- assert(device);
- auto channels = device->channels();
- bool enabled = std::any_of(channels.begin(), channels.end(),
- [](shared_ptr<Channel> channel) { return channel->enabled(); });
-
- if (!enabled) {
- error_handler(tr("No channels enabled."));
- return;
+ const shared_ptr<sigrok::Device> sr_dev = device_->device();
+ if (sr_dev) {
+ const auto channels = sr_dev->channels();
+ if (!std::any_of(channels.begin(), channels.end(),
+ [](shared_ptr<Channel> channel) {
+ return channel->enabled(); })) {
+ error_handler(tr("No channels enabled."));
+ return;
+ }
}
+ // Clear signal data
+ for (const shared_ptr<data::SignalData> d : get_data())
+ d->clear();
+
// Begin the session
sampling_thread_ = std::thread(
&Session::sample_thread_proc, this, device_,
// Make a list of all the channels
std::vector<const srd_channel*> all_channels;
- for(const GSList *i = dec->channels; i; i = i->next)
+ for (const GSList *i = dec->channels; i; i = i->next)
all_channels.push_back((const srd_channel*)i->data);
- for(const GSList *i = dec->opt_channels; i; i = i->next)
+ for (const GSList *i = dec->opt_channels; i; i = i->next)
all_channels.push_back((const srd_channel*)i->data);
// Auto select the initial channels
lock_guard<mutex> lock(sampling_mutex_);
const bool changed = capture_state_ != state;
capture_state_ = state;
- if(changed)
+ if (changed)
capture_state_changed(state);
}
-void Session::update_signals(shared_ptr<devices::Device> device)
+void Session::update_signals()
{
- assert(device);
- assert(capture_state_ == Stopped);
+ assert(device_);
+
+ lock_guard<recursive_mutex> lock(data_mutex_);
+
+ const shared_ptr<sigrok::Device> sr_dev = device_->device();
+ if (!sr_dev) {
+ signals_.clear();
+ logic_data_.reset();
+ return;
+ }
// Detect what data types we will receive
- auto channels = device->device()->channels();
+ auto channels = sr_dev->channels();
unsigned int logic_channel_count = std::count_if(
channels.begin(), channels.end(),
[] (shared_ptr<Channel> channel) {
// Create data containers for the logic data segments
{
- lock_guard<mutex> data_lock(data_mutex_);
+ lock_guard<recursive_mutex> data_lock(data_mutex_);
if (logic_channel_count == 0) {
logic_data_.reset();
unordered_set< shared_ptr<view::Signal> > prev_sigs(signals_);
signals_.clear();
- for (auto channel : device->device()->channels()) {
+ for (auto channel : sr_dev->channels()) {
shared_ptr<view::Signal> signal;
// Find the channel in the old signals
case SR_CHANNEL_LOGIC:
signal = shared_ptr<view::Signal>(
new view::LogicSignal(*this,
- device, channel,
+ device_, channel,
logic_data_));
break;
return shared_ptr<view::Signal>();
}
-void Session::read_sample_rate(shared_ptr<sigrok::Device> device)
-{
- assert(device);
- const auto keys = device->config_keys(ConfigKey::DEVICE_OPTIONS);
- const auto iter = keys.find(ConfigKey::SAMPLERATE);
- cur_samplerate_ = (iter != keys.end() &&
- (*iter).second.find(sigrok::GET) != (*iter).second.end()) ?
- VariantBase::cast_dynamic<Variant<guint64>>(
- device->config_get(ConfigKey::SAMPLERATE)).get() : 0;
-}
-
void Session::sample_thread_proc(shared_ptr<devices::Device> device,
function<void (const QString)> error_handler)
{
assert(device);
assert(error_handler);
- const std::shared_ptr<sigrok::Device> sr_dev = device->device();
- assert(sr_dev);
- read_sample_rate(sr_dev);
+ (void)device;
+
+ cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
+
+ out_of_memory_ = false;
try {
- device_->session()->start();
+ device_->start();
} catch(Error e) {
error_handler(e.what());
return;
qDebug("SR_DF_END was not received.");
assert(0);
}
+
+ if (out_of_memory_)
+ error_handler(tr("Out of memory, acquisition stopped."));
}
void Session::feed_in_header()
{
- read_sample_rate(device_->device());
+ cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
}
void Session::feed_in_meta(shared_ptr<Meta> meta)
void Session::feed_in_logic(shared_ptr<Logic> logic)
{
- lock_guard<mutex> lock(data_mutex_);
+ lock_guard<recursive_mutex> lock(data_mutex_);
+
+ const size_t sample_count = logic->data_length() / logic->unit_size();
if (!logic_data_)
{
- qDebug() << "Unexpected logic packet";
- return;
+ // The only reason logic_data_ would not have been created is
+ // if it was not possible to determine the signals when the
+ // device was created.
+ update_signals();
}
if (!cur_logic_segment_)
// This could be the first packet after a trigger
set_capture_state(Running);
- // Get sample limit.
- assert(device_);
- const std::shared_ptr<sigrok::Device> device =
- device_->device();
- assert(device);
- const auto keys = device->config_keys(
- ConfigKey::DEVICE_OPTIONS);
- const auto iter = keys.find(ConfigKey::LIMIT_SAMPLES);
- const uint64_t sample_limit = (iter != keys.end() &&
- (*iter).second.find(sigrok::GET) !=
- (*iter).second.end()) ?
- VariantBase::cast_dynamic<Variant<guint64>>(
- device->config_get(ConfigKey::LIMIT_SAMPLES)).get() : 0;
-
// Create a new data segment
cur_logic_segment_ = shared_ptr<data::LogicSegment>(
new data::LogicSegment(
- logic, cur_samplerate_, sample_limit));
+ logic, cur_samplerate_, sample_count));
logic_data_->push_segment(cur_logic_segment_);
// @todo Putting this here means that only listeners querying
void Session::feed_in_analog(shared_ptr<Analog> analog)
{
- lock_guard<mutex> lock(data_mutex_);
+ lock_guard<recursive_mutex> lock(data_mutex_);
const vector<shared_ptr<Channel>> channels = analog->channels();
const unsigned int channel_count = channels.size();
// in the sweep containing this segment.
sweep_beginning = true;
- // Get sample limit.
- uint64_t sample_limit;
- try {
- assert(device_);
- const std::shared_ptr<sigrok::Device> device =
- device_->device();
- assert(device);
- sample_limit = VariantBase::cast_dynamic<Variant<guint64>>(
- device->config_get(ConfigKey::LIMIT_SAMPLES)).get();
- } catch (Error) {
- sample_limit = 0;
- }
-
// Create a segment, keep it in the maps of channels
segment = shared_ptr<data::AnalogSegment>(
new data::AnalogSegment(
- cur_samplerate_, sample_limit));
+ cur_samplerate_, sample_count));
cur_analog_segments_[channel] = segment;
- // Find the annalog data associated with the channel
+ // Find the analog data associated with the channel
shared_ptr<view::AnalogSignal> sig =
dynamic_pointer_cast<view::AnalogSignal>(
signal_from_channel(channel));
break;
case SR_DF_LOGIC:
- feed_in_logic(dynamic_pointer_cast<Logic>(packet->payload()));
+ try {
+ feed_in_logic(dynamic_pointer_cast<Logic>(packet->payload()));
+ } catch (std::bad_alloc) {
+ out_of_memory_ = true;
+ device_->stop();
+ }
break;
case SR_DF_ANALOG:
- feed_in_analog(dynamic_pointer_cast<Analog>(packet->payload()));
+ try {
+ feed_in_analog(dynamic_pointer_cast<Analog>(packet->payload()));
+ } catch (std::bad_alloc) {
+ out_of_memory_ = true;
+ device_->stop();
+ }
break;
case SR_DF_END:
{
{
- lock_guard<mutex> lock(data_mutex_);
+ lock_guard<recursive_mutex> lock(data_mutex_);
cur_logic_segment_.reset();
cur_analog_segments_.clear();
}