]> sigrok.org Git - libsigrokflow.git/blob - src/main.cpp
Factor out src/init.cpp.
[libsigrokflow.git] / src / main.cpp
1 /*
2  * This file is part of the libsigrokflow project.
3  *
4  * Copyright (C) 2018 Martin Ling <martin-sigrok@earth.li>
5  * Copyright (C) 2018 Uwe Hermann <uwe@hermann-uwe.de>
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
21 #include <config.h>
22 #include <iostream>
23 #include <libsigrokflow/libsigrokflow.hpp>
24
25 namespace Srf
26 {
27
28 using namespace std;
29 using namespace std::placeholders;
30
31 Sink::Sink(GstBaseSink *gobj) :
32         Gst::BaseSink(gobj)
33 {
34 }
35
36 Device::Device(GstElement *gobj) :
37         Gst::Element(gobj)
38 {
39 }
40
41 CaptureDevice::CaptureDevice(GstElement *gobj) :
42         Device(gobj)
43 {
44 }
45
46 #ifdef HAVE_LIBSIGROKCXX
47 void LegacyCaptureDevice::class_init(Gst::ElementClass<LegacyCaptureDevice> *klass)
48 {
49         klass->set_metadata("sigrok legacy capture device",
50                         "Source", "Wrapper for capture devices using legacy libsigrok APIs",
51                         "Martin Ling");
52
53         klass->add_pad_template(Gst::PadTemplate::create(
54                         "src",
55                         Gst::PAD_SRC,
56                         Gst::PAD_ALWAYS,
57                         Gst::Caps::create_any()));
58 }
59
60 bool LegacyCaptureDevice::register_element(Glib::RefPtr<Gst::Plugin> plugin)
61 {
62         Gst::ElementFactory::register_element(plugin, "sigrok_legacy_capture_device",
63                         0, Gst::register_mm_type<LegacyCaptureDevice>(
64                                 "sigrok_legacy_capture_device"));
65
66         return true;
67 }
68
69 LegacyCaptureDevice::LegacyCaptureDevice(GstElement *gobj) :
70         Glib::ObjectBase(typeid(LegacyCaptureDevice)),
71         CaptureDevice(gobj)
72 {
73         add_pad(src_pad_ = Gst::Pad::create(get_pad_template("src"), "src"));
74 }
75
76 Glib::RefPtr<LegacyCaptureDevice>LegacyCaptureDevice::create(
77         shared_ptr<sigrok::HardwareDevice> libsigrok_device)
78 {
79         auto element = Gst::ElementFactory::create_element("sigrok_legacy_capture_device");
80         if (!element)
81                 throw runtime_error("Failed to create element - plugin not registered?");
82         auto device = Glib::RefPtr<LegacyCaptureDevice>::cast_static(element);
83         device->libsigrok_device_ = libsigrok_device;
84
85         return device;
86 }
87
88 shared_ptr<sigrok::HardwareDevice> LegacyCaptureDevice::libsigrok_device()
89 {
90         return libsigrok_device_;
91 }
92
93 Gst::StateChangeReturn LegacyCaptureDevice::change_state_vfunc(Gst::StateChange transition)
94 {
95         switch (transition) {
96         case Gst::STATE_CHANGE_READY_TO_PAUSED:
97                 return Gst::StateChangeReturn::STATE_CHANGE_NO_PREROLL;
98         case Gst::STATE_CHANGE_PAUSED_TO_PLAYING:
99                 task_ = Gst::Task::create(std::bind(&LegacyCaptureDevice::run_, this));
100                 task_->set_lock(mutex_);
101                 src_pad_->set_active(true);
102                 task_->start();
103                 return Gst::STATE_CHANGE_SUCCESS;
104         default:
105                 return Gst::STATE_CHANGE_SUCCESS;
106         }
107 }
108
109 void LegacyCaptureDevice::datafeed_callback_(
110         shared_ptr<sigrok::Device> device,
111         shared_ptr<sigrok::Packet> packet)
112 {
113         (void)device;
114
115         switch (packet->type()->id()) {
116         case SR_DF_LOGIC: {
117                 auto logic = static_pointer_cast<sigrok::Logic>(packet->payload());
118                 auto mem = Gst::Memory::create(
119                                 Gst::MEMORY_FLAG_READONLY,
120                                 logic->data_pointer(),
121                                 logic->data_length(),
122                                 0,
123                                 logic->data_length());
124                 auto buf = Gst::Buffer::create();
125                 buf->append_memory(move(mem));
126                 src_pad_->push(move(buf));
127                 break;
128         }
129         case SR_DF_END:
130                 session_->stop();
131                 src_pad_->push_event(Gst::EventEos::create());
132                 break;
133         default:
134                 break;
135         }
136 }
137
138 void LegacyCaptureDevice::run_()
139 {
140         session_ = libsigrok_device_->driver()->parent()->create_session();
141         session_->add_device(libsigrok_device_);
142         session_->add_datafeed_callback(bind(&LegacyCaptureDevice::datafeed_callback_, this, _1, _2));
143         session_->start();
144         session_->run();
145         task_->stop();
146 }
147
148 void LegacyInput::class_init(Gst::ElementClass<LegacyInput> *klass)
149 {
150         klass->set_metadata("sigrok legacy input",
151                         "Transform", "Wrapper for inputs using legacy libsigrok APIs",
152                         "Martin Ling");
153
154         klass->add_pad_template(Gst::PadTemplate::create(
155                         "sink",
156                         Gst::PAD_SINK,
157                         Gst::PAD_ALWAYS,
158                         Gst::Caps::create_any()));
159
160         klass->add_pad_template(Gst::PadTemplate::create(
161                         "src",
162                         Gst::PAD_SRC,
163                         Gst::PAD_ALWAYS,
164                         Gst::Caps::create_any()));
165 }
166
167 bool LegacyInput::register_element(Glib::RefPtr<Gst::Plugin> plugin)
168 {
169         Gst::ElementFactory::register_element(plugin, "sigrok_legacy_input",
170                         0, Gst::register_mm_type<LegacyInput>(
171                                 "sigrok_legacy_input"));
172
173         return true;
174 }
175
176 LegacyInput::LegacyInput(GstElement *gobj) :
177         Glib::ObjectBase(typeid(LegacyInput)),
178         Gst::Element(gobj)
179 {
180         add_pad(sink_pad_ = Gst::Pad::create(get_pad_template("sink"), "sink"));
181         add_pad(src_pad_ = Gst::Pad::create(get_pad_template("src"), "src"));
182         sink_pad_->set_chain_function(sigc::mem_fun(*this, &LegacyInput::chain));
183 }
184
185 Glib::RefPtr<LegacyInput> LegacyInput::create(
186         shared_ptr<sigrok::InputFormat> libsigrok_input_format,
187         map<string, Glib::VariantBase> options)
188 {
189         auto element = Gst::ElementFactory::create_element("sigrok_legacy_input");
190         if (!element)
191                 throw runtime_error("Failed to create element - plugin not registered?");
192         auto input = Glib::RefPtr<LegacyInput>::cast_static(element);
193         input->libsigrok_input_format_ = libsigrok_input_format;
194         input->options_ = options;
195
196         return input;
197 }
198
199 bool LegacyInput::start_vfunc()
200 {
201         libsigrok_input_ = libsigrok_input_format_->create_input(options_);
202         auto context = libsigrok_input_format_->parent();
203         session_ = context->create_session();
204         session_->add_device(libsigrok_input_->device());
205         session_->add_datafeed_callback(bind(&LegacyInput::datafeed_callback_, this, _1, _2));
206         session_->start();
207
208         return true;
209 }
210
211 void LegacyInput::datafeed_callback_(
212         shared_ptr<sigrok::Device> device,
213         shared_ptr<sigrok::Packet> packet)
214 {
215         (void)device;
216
217         switch (packet->type()->id()) {
218         case SR_DF_LOGIC: {
219                 auto logic = static_pointer_cast<sigrok::Logic>(packet->payload());
220                 auto mem = Gst::Memory::create(
221                                 Gst::MEMORY_FLAG_READONLY,
222                                 logic->data_pointer(),
223                                 logic->data_length(),
224                                 0,
225                                 logic->data_length());
226                 auto buf = Gst::Buffer::create();
227                 buf->append_memory(move(mem));
228                 src_pad_->push(move(buf));
229                 break;
230         }
231         case SR_DF_END:
232                 session_->stop();
233                 src_pad_->push_event(Gst::EventEos::create());
234                 break;
235         default:
236                 break;
237         }
238 }
239
240 Gst::FlowReturn LegacyInput::chain(const Glib::RefPtr<Gst::Pad> &,
241         const Glib::RefPtr<Gst::Buffer> &buf)
242 {
243         Gst::MapInfo info;
244         buf->map(info, Gst::MAP_READ);
245         libsigrok_input_->send(info.get_data(), info.get_size());
246         buf->unmap(info);
247
248         return Gst::FLOW_OK;
249 }
250
251 bool LegacyInput::stop_vfunc()
252 {
253         libsigrok_input_->end();
254
255         return true;
256 }
257
258 void LegacyOutput::class_init(Gst::ElementClass<LegacyOutput> *klass)
259 {
260         klass->set_metadata("sigrok legacy output",
261                         "Sink", "Wrapper for outputs using legacy libsigrok APIs",
262                         "Martin Ling");
263
264         klass->add_pad_template(Gst::PadTemplate::create(
265                         "sink",
266                         Gst::PAD_SINK,
267                         Gst::PAD_ALWAYS,
268                         Gst::Caps::create_any()));
269 }
270
271 bool LegacyOutput::register_element(Glib::RefPtr<Gst::Plugin> plugin)
272 {
273         Gst::ElementFactory::register_element(plugin, "sigrok_legacy_output",
274                         0, Gst::register_mm_type<LegacyOutput>(
275                                 "sigrok_legacy_output"));
276
277         return true;
278 }
279
280 LegacyOutput::LegacyOutput(GstBaseSink *gobj) :
281         Glib::ObjectBase(typeid(LegacyOutput)),
282         Sink(gobj)
283 {
284 }
285
286 Glib::RefPtr<LegacyOutput>LegacyOutput::create(
287         shared_ptr<sigrok::OutputFormat> libsigrok_output_format,
288         shared_ptr<sigrok::Device> libsigrok_device,
289         map<string, Glib::VariantBase> options)
290 {
291         auto element = Gst::ElementFactory::create_element("sigrok_legacy_output");
292         if (!element)
293                 throw runtime_error("Failed to create element - plugin not registered?");
294         auto output = Glib::RefPtr<LegacyOutput>::cast_static(element);
295         output->libsigrok_output_format_ = libsigrok_output_format;
296         output->libsigrok_device_ = libsigrok_device;
297         output->options_ = options;
298
299         return output;
300 }
301
302 bool LegacyOutput::start_vfunc()
303 {
304         libsigrok_output_ = libsigrok_output_format_->create_output(
305                         libsigrok_device_, options_);
306
307         return true;
308 }
309
310 Gst::FlowReturn LegacyOutput::render_vfunc(const Glib::RefPtr<Gst::Buffer> &buffer)
311 {
312         Gst::MapInfo info;
313         buffer->map(info, Gst::MAP_READ);
314         auto context = libsigrok_output_format_->parent();
315         auto packet = context->create_logic_packet(
316                         info.get_data(), info.get_size(), 2);
317         auto result = libsigrok_output_->receive(packet);
318         cout << result;
319         buffer->unmap(info);
320
321         return Gst::FLOW_OK;
322 }
323
324 bool LegacyOutput::stop_vfunc()
325 {
326         auto context = libsigrok_output_format_->parent();
327         auto end_packet = context->create_end_packet();
328         auto result = libsigrok_output_->receive(end_packet);
329         cout << result;
330
331         return true;
332 }
333 #endif
334
335 #ifdef HAVE_LIBSIGROKDECODE
336 void LegacyDecoder::class_init(Gst::ElementClass<LegacyDecoder> *klass)
337 {
338         klass->set_metadata("sigrok legacy decoder",
339                         "Sink", "Wrapper for protocol decoders using legacy libsigrokdecode APIs",
340                         "Uwe Hermann");
341
342         klass->add_pad_template(Gst::PadTemplate::create(
343                         "sink",
344                         Gst::PAD_SINK,
345                         Gst::PAD_ALWAYS,
346                         Gst::Caps::create_any()));
347 }
348
349 bool LegacyDecoder::register_element(Glib::RefPtr<Gst::Plugin> plugin)
350 {
351         Gst::ElementFactory::register_element(plugin, "sigrok_legacy_decoder",
352                         0, Gst::register_mm_type<LegacyDecoder>(
353                                 "sigrok_legacy_decoder"));
354
355         return true;
356 }
357
358 LegacyDecoder::LegacyDecoder(GstBaseSink *gobj) :
359         Glib::ObjectBase(typeid(LegacyDecoder)),
360         Sink(gobj)
361 {
362 }
363
364 Glib::RefPtr<LegacyDecoder>LegacyDecoder::create(
365         struct srd_session *libsigrokdecode_session, uint64_t unitsize)
366 {
367         auto element = Gst::ElementFactory::create_element("sigrok_legacy_decoder");
368         if (!element)
369                 throw runtime_error("Failed to create element - plugin not registered?");
370         auto decoder = Glib::RefPtr<LegacyDecoder>::cast_static(element);
371         decoder->session_ = libsigrokdecode_session;
372         decoder->unitsite_ = unitsize;
373
374         return decoder;
375 }
376
377 struct srd_session *LegacyDecoder::libsigrokdecode_session()
378 {
379         return session_;
380 }
381
382 Gst::FlowReturn LegacyDecoder::render_vfunc(const Glib::RefPtr<Gst::Buffer> &buffer)
383 {
384         Gst::MapInfo info;
385         buffer->map(info, Gst::MAP_READ);
386         uint64_t num_samples = info.get_size() / unitsite_;
387         srd_session_send(session_, abs_ss_, abs_ss_ + num_samples,
388                 info.get_data(), info.get_size(), unitsite_);
389         abs_ss_ += num_samples;
390         buffer->unmap(info);
391
392         return Gst::FLOW_OK;
393 }
394
395 bool LegacyDecoder::start_vfunc()
396 {
397         abs_ss_ = 0;
398         srd_session_start(session_);
399
400         return true;
401 }
402
403 bool LegacyDecoder::stop_vfunc()
404 {
405         srd_session_terminate_reset(session_);
406
407         return true;
408 }
409 #endif
410
411 }