Loading...
Searching...
No Matches
RecordProviderFactory.hpp
1#pragma once
2#include <Device/Node/DeviceNode.hpp>
3
4#include <Explorer/DocumentPlugin/DeviceDocumentPlugin.hpp>
5#include <Explorer/Explorer/DeviceExplorerModel.hpp>
6
7#include <Scenario/Palette/ScenarioPoint.hpp>
8#include <Scenario/Process/Algorithms/Accessors.hpp>
9
10#include <Recording/Record/RecordTools.hpp>
11
12#include <score/plugins/Interface.hpp>
13#include <score/plugins/documentdelegate/DocumentDelegateView.hpp>
15#include <score/tools/ObjectMatches.hpp>
16
17#include <core/document/Document.hpp>
18#include <core/document/DocumentView.hpp>
19
20#include <QApplication>
21#include <QTimer>
22#include <QWidget>
23
24#include <score_plugin_recording_export.h>
25
26#include <verdigris>
27
28namespace Scenario
29{
30class ProcessModel;
31}
32namespace Explorer
33{
34class DeviceExplorerModel;
35}
36namespace Recording
37{
38struct RecordContext : public QObject
39{
40 W_OBJECT(RecordContext)
41public:
42 using clock = std::chrono::steady_clock;
44 RecordContext(const RecordContext& other) = delete;
45 RecordContext(RecordContext&& other) = delete;
46 RecordContext& operator=(const RecordContext& other) = delete;
47 RecordContext& operator=(RecordContext&& other) = delete;
48
49 void start()
50 {
51 firstValueTime = clock::now();
52 startTimer();
53 }
54
55 bool started() const
56 {
57 return firstValueTime.time_since_epoch() != clock::duration::zero();
58 }
59
60 TimeVal time() const { return GetTimeDifference(firstValueTime); }
61
62 double timeInDouble() const { return GetTimeDifferenceInDouble(firstValueTime); }
63
64 const score::DocumentContext& context;
65 Scenario::ProcessModel& scenario;
67 RecordCommandDispatcher dispatcher;
68
69 Scenario::Point point;
70 clock::time_point firstValueTime{};
71 QTimer timer;
72
73public:
74 void startTimer() W_SIGNAL(startTimer);
75
76public:
77 void on_startTimer()
78 {
79 context.document.view()->viewDelegate().getWidget()->setEnabled(false);
80 timer.start();
81 }
82 W_SLOT(on_startTimer)
83};
84
86{
87 virtual ~RecordProvider();
88 virtual bool setup(const Box&, const RecordListening&) = 0;
89 virtual void stop() = 0;
90};
91
92// A recording session.
94{
95public:
96 Recorder(RecordContext& ctx) //: m_context{ctx}
97 {
98 // Algorithm :
99 // 1. Get all selected addresses.
100 // 2. Generate the concrete recorders that match these addresses.
101 // Use settings to select them recursively or not..
102 // 3. Create a box corresponding to the case where we record
103 // in the void, in an existing interval, starting from a state / event...
104
105 // Have a "record as" attribute on nodes to indicate if
106 // it should be recorded as a message, or automation, or ...
107 }
108
109 bool setup() { return false; }
110
111 void stop() { }
112
113private:
114 // RecordContext& m_context;
115 std::vector<std::unique_ptr<RecordProvider>> m_recorders;
116};
117
118// Sets-up the recording of a single class.
119template <typename T>
120class SingleRecorder final : public QObject
121{
122public:
123 T recorder;
124
126 : recorder{ctx}
127 {
128 }
129
130 bool setup()
131 {
132 RecordContext& ctx = recorder.context;
134 // Get the listening of the selected addresses
135 auto recordListening = GetAddressesToRecordRecursive(ctx.explorer);
136 if(recordListening.empty())
137 return false;
138
139 // Disable listening for everything
140 ctx.explorer.deviceModel().listening().stop();
141
142 // Create the processes, etc.
143 Box box = CreateBox(ctx);
144
145 if(!recorder.setup(box, recordListening))
146 {
147 ctx.explorer.deviceModel().listening().restore();
148 return false;
149 }
150
152 ctx.timer.stop();
153 ctx.timer.setTimerType(Qt::PreciseTimer);
154 ctx.timer.setInterval(ReasonableUpdateInterval(recorder.count()));
155 QObject::connect(&ctx.timer, &QTimer::timeout, this, [&, box]() {
156 // Move end event by the current duration.
157 auto& cur_date = box.interval.date();
158 box.moveCommand.update(
159 ctx.scenario, {}, box.endEvent,
160 cur_date + GetTimeDifference(ctx.firstValueTime), 0, true);
161
162 box.moveCommand.redo(ctx.context);
163 });
164
165 // In case where the software is exited
166 // during recording.
167 QObject::connect(
169 [&]() { ctx.timer.stop(); });
170
171 return true;
172 }
173
174 void stop()
175 {
176 RecordContext& ctx = recorder.context;
177 ctx.timer.stop();
178
179 recorder.stop();
180
181 ctx.explorer.deviceModel().listening().restore(); // Commit
182 ctx.dispatcher.commit();
183 ctx.context.document.view()->viewDelegate().getWidget()->setEnabled(true);
184 }
185
186private:
187};
188
189class SCORE_PLUGIN_RECORDING_EXPORT RecorderFactory : public score::InterfaceBase
190{
191 SCORE_INTERFACE(RecorderFactory, "64999184-a705-4686-b967-14e8f79692f1")
192public:
193 virtual ~RecorderFactory();
194
195 virtual Priority matches(const Device::Node&, const score::DocumentContext& ctx) = 0;
196
197 virtual std::unique_ptr<RecordProvider>
198 make(const Device::NodeList&, const score::DocumentContext& ctx) = 0;
199};
200}
Definition DeviceExplorerModel.hpp:67
void identified_object_destroyed(IdentifiedObjectAbstract *o)
Will be called in the IdentifiedObjectAbstract destructor.
Definition RecordProviderFactory.hpp:190
Definition RecordProviderFactory.hpp:94
Definition RecordProviderFactory.hpp:121
The core hierarchical and temporal process of score.
Definition ScenarioModel.hpp:37
Base class for plug-in interfaces.
Definition Interface.hpp:52
Main plug-in of score.
Definition score-plugin-dataflow/Dataflow/PortItem.hpp:13
Definition RecordTools.hpp:64
Definition RecordProviderFactory.hpp:39
Definition RecordProviderFactory.hpp:86
Definition ScenarioPoint.hpp:13
Definition TimeValue.hpp:21
Definition ObjectMatches.hpp:6
Definition DocumentContext.hpp:18