2 * This file is part of the libsigrokflow project.
4 * Copyright (C) 2018 Martin Ling <martin-sigrok@earth.li>
5 * Copyright (C) 2018 Uwe Hermann <uwe@hermann-uwe.de>
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <libsigrokflow/libsigrokflow.hpp>
29 using namespace std::placeholders;
31 static bool srf_initialized_ = false;
36 throw runtime_error("libsigrokflow is already initialized");
38 if (!Gst::is_initialized())
39 throw runtime_error("Gst::init() has not run yet");
41 #ifdef HAVE_LIBSIGROKCXX
42 Gst::Plugin::register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
43 "sigrok_legacy_capture_device",
44 "Wrapper for capture devices using legacy libsigrok APIs",
45 sigc::ptr_fun(&LegacyCaptureDevice::register_element),
46 "0.01", "GPL", "sigrok", "libsigrokflow", "http://sigrok.org");
47 Gst::Plugin::register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
48 "sigrok_legacy_input",
49 "Wrapper for inputs using legacy libsigrok APIs",
50 sigc::ptr_fun(&LegacyInput::register_element),
51 "0.01", "GPL", "sigrok", "libsigrokflow", "http://sigrok.org");
52 Gst::Plugin::register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
53 "sigrok_legacy_output",
54 "Wrapper for outputs using legacy libsigrok APIs",
55 sigc::ptr_fun(&LegacyOutput::register_element),
56 "0.01", "GPL", "sigrok", "libsigrokflow", "http://sigrok.org");
58 #ifdef HAVE_LIBSIGROKDECODE
59 Gst::Plugin::register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
60 "sigrok_legacy_decoder",
61 "Wrapper for protocol decoders using legacy libsigrokdecode APIs",
62 sigc::ptr_fun(&LegacyDecoder::register_element),
63 "0.01", "GPL", "sigrok", "libsigrokflow", "http://sigrok.org");
66 srf_initialized_ = true;
71 if (!srf_initialized_)
72 throw runtime_error("libsigrokflow is not initialized");
74 srf_initialized_ = false;
77 Sink::Sink(GstBaseSink *gobj) :
82 Device::Device(GstElement *gobj) :
87 CaptureDevice::CaptureDevice(GstElement *gobj) :
92 #ifdef HAVE_LIBSIGROKCXX
93 void LegacyCaptureDevice::class_init(Gst::ElementClass<LegacyCaptureDevice> *klass)
95 klass->set_metadata("sigrok legacy capture device",
96 "Source", "Wrapper for capture devices using legacy libsigrok APIs",
99 klass->add_pad_template(Gst::PadTemplate::create(
103 Gst::Caps::create_any()));
106 bool LegacyCaptureDevice::register_element(Glib::RefPtr<Gst::Plugin> plugin)
108 Gst::ElementFactory::register_element(plugin, "sigrok_legacy_capture_device",
109 0, Gst::register_mm_type<LegacyCaptureDevice>(
110 "sigrok_legacy_capture_device"));
114 LegacyCaptureDevice::LegacyCaptureDevice(GstElement *gobj) :
115 Glib::ObjectBase(typeid(LegacyCaptureDevice)),
118 add_pad(_src_pad = Gst::Pad::create(get_pad_template("src"), "src"));
121 Glib::RefPtr<LegacyCaptureDevice>LegacyCaptureDevice::create(
122 shared_ptr<sigrok::HardwareDevice> libsigrok_device)
124 auto element = Gst::ElementFactory::create_element("sigrok_legacy_capture_device");
126 throw runtime_error("Failed to create element - plugin not registered?");
127 auto device = Glib::RefPtr<LegacyCaptureDevice>::cast_static(element);
128 device->_libsigrok_device = libsigrok_device;
132 shared_ptr<sigrok::HardwareDevice> LegacyCaptureDevice::libsigrok_device()
134 return _libsigrok_device;
137 Gst::StateChangeReturn LegacyCaptureDevice::change_state_vfunc(Gst::StateChange transition)
141 case Gst::STATE_CHANGE_READY_TO_PAUSED:
142 return Gst::StateChangeReturn::STATE_CHANGE_NO_PREROLL;
143 case Gst::STATE_CHANGE_PAUSED_TO_PLAYING:
144 _task = Gst::Task::create(std::bind(&LegacyCaptureDevice::_run, this));
145 _task->set_lock(_mutex);
146 _src_pad->set_active(true);
148 return Gst::STATE_CHANGE_SUCCESS;
150 return Gst::STATE_CHANGE_SUCCESS;
154 void LegacyCaptureDevice::_datafeed_callback(
155 shared_ptr<sigrok::Device> device,
156 shared_ptr<sigrok::Packet> packet)
159 switch (packet->type()->id()) {
162 auto logic = static_pointer_cast<sigrok::Logic>(packet->payload());
163 auto mem = Gst::Memory::create(
164 Gst::MEMORY_FLAG_READONLY,
165 logic->data_pointer(),
166 logic->data_length(),
168 logic->data_length());
169 auto buf = Gst::Buffer::create();
170 buf->append_memory(move(mem));
171 _src_pad->push(move(buf));
176 _src_pad->push_event(Gst::EventEos::create());
183 void LegacyCaptureDevice::_run()
185 _session = _libsigrok_device->driver()->parent()->create_session();
186 _session->add_device(_libsigrok_device);
187 _session->add_datafeed_callback(bind(&LegacyCaptureDevice::_datafeed_callback, this, _1, _2));
193 void LegacyInput::class_init(Gst::ElementClass<LegacyInput> *klass)
195 klass->set_metadata("sigrok legacy input",
196 "Transform", "Wrapper for inputs using legacy libsigrok APIs",
199 klass->add_pad_template(Gst::PadTemplate::create(
203 Gst::Caps::create_any()));
205 klass->add_pad_template(Gst::PadTemplate::create(
209 Gst::Caps::create_any()));
212 bool LegacyInput::register_element(Glib::RefPtr<Gst::Plugin> plugin)
214 Gst::ElementFactory::register_element(plugin, "sigrok_legacy_input",
215 0, Gst::register_mm_type<LegacyInput>(
216 "sigrok_legacy_input"));
220 LegacyInput::LegacyInput(GstElement *gobj) :
221 Glib::ObjectBase(typeid(LegacyInput)),
224 add_pad(_sink_pad = Gst::Pad::create(get_pad_template("sink"), "sink"));
225 add_pad(_src_pad = Gst::Pad::create(get_pad_template("src"), "src"));
226 _sink_pad->set_chain_function(sigc::mem_fun(*this, &LegacyInput::chain));
229 Glib::RefPtr<LegacyInput> LegacyInput::create(
230 shared_ptr<sigrok::InputFormat> libsigrok_input_format,
231 map<string, Glib::VariantBase> options)
233 auto element = Gst::ElementFactory::create_element("sigrok_legacy_input");
235 throw runtime_error("Failed to create element - plugin not registered?");
236 auto input = Glib::RefPtr<LegacyInput>::cast_static(element);
237 input->_libsigrok_input_format = libsigrok_input_format;
238 input->_options = options;
242 bool LegacyInput::start_vfunc()
244 _libsigrok_input = _libsigrok_input_format->create_input(_options);
245 auto context = _libsigrok_input_format->parent();
246 _session = context->create_session();
247 _session->add_device(_libsigrok_input->device());
248 _session->add_datafeed_callback(bind(&LegacyInput::_datafeed_callback, this, _1, _2));
253 void LegacyInput::_datafeed_callback(
254 shared_ptr<sigrok::Device> device,
255 shared_ptr<sigrok::Packet> packet)
258 switch (packet->type()->id()) {
261 auto logic = static_pointer_cast<sigrok::Logic>(packet->payload());
262 auto mem = Gst::Memory::create(
263 Gst::MEMORY_FLAG_READONLY,
264 logic->data_pointer(),
265 logic->data_length(),
267 logic->data_length());
268 auto buf = Gst::Buffer::create();
269 buf->append_memory(move(mem));
270 _src_pad->push(move(buf));
275 _src_pad->push_event(Gst::EventEos::create());
282 Gst::FlowReturn LegacyInput::chain(const Glib::RefPtr<Gst::Pad> &,
283 const Glib::RefPtr<Gst::Buffer> &buf)
286 buf->map(info, Gst::MAP_READ);
287 _libsigrok_input->send(info.get_data(), info.get_size());
292 bool LegacyInput::stop_vfunc()
294 _libsigrok_input->end();
298 void LegacyOutput::class_init(Gst::ElementClass<LegacyOutput> *klass)
300 klass->set_metadata("sigrok legacy output",
301 "Sink", "Wrapper for outputs using legacy libsigrok APIs",
304 klass->add_pad_template(Gst::PadTemplate::create(
308 Gst::Caps::create_any()));
311 bool LegacyOutput::register_element(Glib::RefPtr<Gst::Plugin> plugin)
313 Gst::ElementFactory::register_element(plugin, "sigrok_legacy_output",
314 0, Gst::register_mm_type<LegacyOutput>(
315 "sigrok_legacy_output"));
319 LegacyOutput::LegacyOutput(GstBaseSink *gobj) :
320 Glib::ObjectBase(typeid(LegacyOutput)),
325 Glib::RefPtr<LegacyOutput>LegacyOutput::create(
326 shared_ptr<sigrok::OutputFormat> libsigrok_output_format,
327 shared_ptr<sigrok::Device> libsigrok_device,
328 map<string, Glib::VariantBase> options)
330 auto element = Gst::ElementFactory::create_element("sigrok_legacy_output");
332 throw runtime_error("Failed to create element - plugin not registered?");
333 auto output = Glib::RefPtr<LegacyOutput>::cast_static(element);
334 output->_libsigrok_output_format = libsigrok_output_format;
335 output->_libsigrok_device = libsigrok_device;
336 output->_options = options;
340 bool LegacyOutput::start_vfunc()
342 _libsigrok_output = _libsigrok_output_format->create_output(
343 _libsigrok_device, _options);
347 Gst::FlowReturn LegacyOutput::render_vfunc(const Glib::RefPtr<Gst::Buffer> &buffer)
350 buffer->map(info, Gst::MAP_READ);
351 auto context = _libsigrok_output_format->parent();
352 auto packet = context->create_logic_packet(
353 info.get_data(), info.get_size(), 2);
354 auto result = _libsigrok_output->receive(packet);
360 bool LegacyOutput::stop_vfunc()
362 auto context = _libsigrok_output_format->parent();
363 auto end_packet = context->create_end_packet();
364 auto result = _libsigrok_output->receive(end_packet);
370 #ifdef HAVE_LIBSIGROKDECODE
371 void LegacyDecoder::class_init(Gst::ElementClass<LegacyDecoder> *klass)
373 klass->set_metadata("sigrok legacy decoder",
374 "Sink", "Wrapper for protocol decoders using legacy libsigrokdecode APIs",
377 klass->add_pad_template(Gst::PadTemplate::create(
381 Gst::Caps::create_any()));
384 bool LegacyDecoder::register_element(Glib::RefPtr<Gst::Plugin> plugin)
386 Gst::ElementFactory::register_element(plugin, "sigrok_legacy_decoder",
387 0, Gst::register_mm_type<LegacyDecoder>(
388 "sigrok_legacy_decoder"));
392 LegacyDecoder::LegacyDecoder(GstBaseSink *gobj) :
393 Glib::ObjectBase(typeid(LegacyDecoder)),
398 Glib::RefPtr<LegacyDecoder>LegacyDecoder::create(
399 struct srd_session *libsigrokdecode_session, uint64_t unitsize)
401 auto element = Gst::ElementFactory::create_element("sigrok_legacy_decoder");
403 throw runtime_error("Failed to create element - plugin not registered?");
404 auto decoder = Glib::RefPtr<LegacyDecoder>::cast_static(element);
405 decoder->_session = libsigrokdecode_session;
406 decoder->_unitsize = unitsize;
410 struct srd_session *LegacyDecoder::libsigrokdecode_session()
415 Gst::FlowReturn LegacyDecoder::render_vfunc(const Glib::RefPtr<Gst::Buffer> &buffer)
418 buffer->map(info, Gst::MAP_READ);
419 uint64_t num_samples = info.get_size() / _unitsize;
420 srd_session_send(_session, _abs_ss, _abs_ss + num_samples,
421 info.get_data(), info.get_size(), _unitsize);
422 _abs_ss += num_samples;
427 bool LegacyDecoder::start_vfunc()
430 srd_session_start(_session);
434 bool LegacyDecoder::stop_vfunc()
436 srd_session_terminate_reset(_session);