Trax3 3.1.0
trax track library
Loading...
Searching...
No Matches
Plug.h
1// trax track library
2// AD 2014
3//
4// "If you have a message - go to the post office."
5//
6// Alfred Hitchcock
7//
8// Copyright (c) 2025 Trend Redaktions- und Verlagsgesellschaft mbH
9// Copyright (c) 2019 Marc-Michael Horstmann
10//
11// Permission is hereby granted to any person obtaining a copy of this software
12// and associated source code (the "Software"), to use, view, and study the
13// Software for personal or internal business purposes, subject to the following
14// conditions:
15//
16// 1. Redistribution, modification, sublicensing, or commercial use of the
17// Software is NOT permitted without prior written consent from the copyright
18// holder.
19//
20// 2. The Software is provided "AS IS", without warranty of any kind, express
21// or implied.
22//
23// 3. All copies of the Software must retain this license notice.
24//
25// For further information, please contact: horstmann.marc@trendverlag.de
26
27#pragma once
28
29#include "Identified.h"
30#include "Jack.h"
31#include "Units.h"
32
33#include <vector>
34#include <algorithm>
35#include <sstream>
36
37#if defined(_MSC_VER)
38# pragma warning(disable: 4250) // virtual inheritance of methods via dominance
39#endif
40
41namespace trax{
42
43 struct PlugEnumerator;
44 struct SocketRegistry;
45
56 struct Plug : Identified<Plug>
57 {
59 virtual const char* TypeName() const noexcept = 0;
60
61
64 virtual Jack* Plugged() const noexcept = 0;
65
66
69 virtual bool IsCyclic() const noexcept = 0;
70
71
81 virtual const Plug& Tail() const = 0;
82
83
93 virtual Plug& Tail() = 0;
94
95
100 virtual Jack& JackOnPulse() noexcept = 0;
101
102
104 virtual const Jack& JackOnPulse() const noexcept = 0;
105
106
110 virtual PlugEnumerator& Parent() const noexcept = 0;
111
112
114 virtual void Remove() noexcept = 0;
115 protected:
116 friend class Jack_Imp;
117
118 virtual void Pulse( bool /*bForewardToJack*/ ) noexcept{}
119
120 virtual void Release() noexcept{}
121
122 virtual void ConnectTo( Jack& /*jack*/ ) noexcept{}
123 };
124
125 dclspc const Plug* GetFirstNonZeroIDPlugInChain( const Plug& plug );
126
127
133 struct PlugEnumerator{
134
137 typedef PlugEnumerator collection_type;
138 typedef Plug value_type;
140
141
147 Plug& GetPlug( int idx ){
148 return const_cast<Plug&>(_GetPlug( idx ));
149 }
150
151 const Plug& GetPlug( int idx ) const{
152 return _GetPlug( idx );
153 }
155
156
158 virtual int CountPlugs() const = 0;
159
160 virtual ~PlugEnumerator() = default;
161 protected:
162 PlugEnumerator( const PlugEnumerator& ) = default;
163 PlugEnumerator( PlugEnumerator&& ) = default;
164 PlugEnumerator& operator=( const PlugEnumerator& ) = default;
165 PlugEnumerator& operator=( PlugEnumerator&& ) = default;
166 PlugEnumerator() = default;
167
168
175 virtual const Plug& _GetPlug( int idx ) const = 0;
176 };
177
178
179 template< class EnumeratorType,
180 class PointerType = Plug*,
181 class ReferenceType = Plug&>
182 class PlugIterator{// : public std::iterator<std::random_access_iterator_tag, Plug, ptrdiff_t, PointerType, ReferenceType>{
183 public:
184 using iterator_category = std::random_access_iterator_tag;
185 using value_type = Plug;
186 using difference_type = ptrdiff_t;
187 using pointer = PointerType;
188 using reference = ReferenceType;
189
191 PlugIterator( EnumeratorType& Container, bool bEnd = false )
192 : m_Container( Container ),
193 m_IndexCurrent( bEnd ? Container.CountPlugs() : 0 )
194 {}
195
198 PlugIterator& operator++() noexcept{
199 ++m_IndexCurrent;
200 return *this;
201 }
202
203 PlugIterator operator++( int ) noexcept{
204 PlugIterator retval( *this );
205 operator++();
206 return retval;
207 }
208
209 ReferenceType operator*() const{
210 return m_Container.GetPlug( m_IndexCurrent );
211 }
212
213 PlugIterator& operator--() noexcept{
214 --m_IndexCurrent;
215 return *this;
216 }
217
218 PlugIterator operator--( int ) noexcept{
219 PlugIterator retval( *this );
220 operator--();
221 return retval;
222 }
223
224 ReferenceType operator[]( int n ) const{
225 return m_Container.GetPlug( m_IndexCurrent + n );
226 }
227
228 ReferenceType operator->() const{
229 return m_Container.GetPlug( m_IndexCurrent );
230 }
231
232 bool operator==( const PlugIterator& iter ) const noexcept{
233 assert( &m_Container == &iter.m_Container );
234 return m_IndexCurrent == iter.m_IndexCurrent;
235 }
236
237 bool operator!=( const PlugIterator& iter ) const noexcept{
238 assert( &m_Container == &iter.m_Container );
239 return m_IndexCurrent != iter.m_IndexCurrent;
240 }
241
242 bool operator<( const PlugIterator& iter ) const noexcept{
243 assert( &m_Container == &iter.m_Container );
244 return m_IndexCurrent < iter.m_IndexCurrent;
245 }
246
247 bool operator<=( const PlugIterator& iter ) const noexcept{
248 assert( &m_Container == &iter.m_Container );
249 return m_IndexCurrent <= iter.m_IndexCurrent;
250 }
251
252 bool operator>( const PlugIterator& iter ) const noexcept{
253 assert( &m_Container == &iter.m_Container );
254 return m_IndexCurrent > iter.m_IndexCurrent;
255 }
256
257 bool operator>=( const PlugIterator& iter ) const noexcept{
258 assert( &m_Container == &iter.m_Container );
259 return m_IndexCurrent >= iter.m_IndexCurrent;
260 }
261
262 void operator+=( int n ) noexcept{
263 m_IndexCurrent += n;
264 }
265
266 void operator-=( int n ) noexcept{
267 m_IndexCurrent -= n;
268 }
269
270 PlugIterator operator+( int n ) const noexcept{
271 PlugIterator iter( *this );
272 iter.m_IndexCurrent += n;
273 }
274
275 PlugIterator operator-( int n ) const noexcept{
276 PlugIterator iter( *this );
277 iter.m_IndexCurrent -= n;
278 }
280 private:
281 EnumeratorType& m_Container;
282 int m_IndexCurrent;
283 };
284
285 inline PlugIterator<PlugEnumerator> begin( PlugEnumerator& plugEnumerator ){
286 return PlugIterator<PlugEnumerator>( plugEnumerator );
287 }
288
291 }
292
293 inline PlugIterator<PlugEnumerator> end( PlugEnumerator& plugEnumerator ){
294 return PlugIterator<PlugEnumerator>( plugEnumerator, true );
295 }
296
299 }
300
301
305 struct MultiPlug : virtual Plug,
306 PlugEnumerator
307 {
308 using Plug::ID;
309
310 using Plug::Reference;
311
315 virtual Plug& Make( SocketRegistry* pRegistry = nullptr ) = 0;
316
317
320 virtual Plug& Unplugged( SocketRegistry* pRegistry = nullptr ) = 0;
321
322
326 virtual void Release( Plug& plug ) = 0;
327
328
330 virtual void Clear() = 0;
331 protected:
332 using Plug::Release;
333 };
334
335
336 class Plug_Imp : public ObjectID_Imp<Plug>,
337 public JackEnumerator {
338 public:
339 Plug_Imp() = delete;
340 Plug_Imp(const Plug_Imp& plug) = delete;
341 dclspc Plug_Imp(Plug_Imp&& plug) noexcept;
342 dclspc Plug_Imp(PlugEnumerator& parent);
343 dclspc Plug_Imp(PlugEnumerator& parent, Plug_Imp&& plug);
344
345 dclspc ~Plug_Imp() noexcept; // TODO: if the user defines his own Plug_Imp derived Plug
346 // and assigns a string by Reference() without using Reference
347 // again to delete it, the destructor will crash on trying to
348 // delete the string in a different module.
349 // User framework should be supplied independently from trax
350 // library implementation.
351
352 //~Plug_Imp() noexcept{
353 // Remove();
354 //}
355
356
357 Plug_Imp& operator=(Plug_Imp&) = delete;
358 Plug_Imp& operator=(Plug_Imp&& plug) = delete;
359
360 const char* TypeName() const noexcept override {
361 return "Plug";
362 }
363
365
366 const std::string& Reference(const std::string& name) const override {
367 return ObjectID_Imp<Plug>::Reference(name);
368 }
369
370 using ObjectID_Imp<Plug>::ID;
371
372 IDType ID() const noexcept override {
373 return ObjectID_Imp<Plug>::ID();
374 }
375
376 dclspc Jack* Plugged() const noexcept override;
377
378 dclspc bool IsCyclic() const noexcept override;
379
380 dclspc const Plug& Tail() const override;
381
382 dclspc Plug& Tail() override;
383
384 dclspc Jack& JackOnPulse() noexcept override;
385
386 dclspc const Jack& JackOnPulse() const noexcept override;
387
388 dclspc PlugEnumerator& Parent() const noexcept override;
389
390 dclspc void Remove() noexcept;
391
392 dclspc int CountJacks() const noexcept override;
393 protected:
398 dclspc void Pulse(bool bForewardToJack) noexcept override;
399
400 dclspc const Jack& _GetJack(int idx) const override;
401 private:
402 friend class Jack_Imp;
403 // Plug_Imp:
404 dclspc void Release() noexcept override;
405
406 dclspc void ConnectTo(Jack& jack) noexcept override;
407
408 Jack* m_pPlugged;
409 Jack_Imp m_JackOnPulse{ "JackOnPulse" };
410 PlugEnumerator& m_Parent;
411 };
412
413
414 template<class ParentType>
415 class Plug_Imp_Parent : public Plug_Imp {
416 protected:
417 ParentType& m_Parent;
418 public:
419 Plug_Imp_Parent() = delete;
420 Plug_Imp_Parent(const Plug_Imp_Parent& plug) = delete;
421 Plug_Imp_Parent(Plug_Imp_Parent&& plug) = default;
422 Plug_Imp_Parent(ParentType& parent)
423 : Plug_Imp{ parent },
424 m_Parent{ parent }
425 {}
426 Plug_Imp_Parent(ParentType& parent, Plug_Imp_Parent&& plug)
427 : Plug_Imp{ parent,std::move(plug) },
428 m_Parent{ parent }
429 {}
430 };
431
432
436 template<class ParentType>
437 class Plug_Imp_ParentPointer : public Plug_Imp_Parent<ParentType> {
438#if defined(_MSC_VER) && !defined(_WIN64)
439# pragma pack(push, 4) // alignment of a member was sensitive to packing
440#endif
441 void (ParentType::* m_pPulseFunction)() = nullptr;
442#if defined(_MSC_VER) && !defined(_WIN64)
443# pragma pack(pop)
444#endif
445 public:
446 using TargetType = ParentType;
447
448 Plug_Imp_ParentPointer() = delete;
449 Plug_Imp_ParentPointer(const Plug_Imp_ParentPointer& plug) = delete;
450 Plug_Imp_ParentPointer(Plug_Imp_ParentPointer&& plug) = default;
451
452 Plug_Imp_ParentPointer(ParentType& parent, void (ParentType::* pPulseFunction)() noexcept )
453 : Plug_Imp_Parent<ParentType>{ parent },
454 m_pPulseFunction{ pPulseFunction }
455 {
456 //static_assert( std::is_convertible<Plug_Imp_ParentPointer*,PlugEnumerator*>::value );
457 assert(m_pPulseFunction);
458 }
459 Plug_Imp_ParentPointer(ParentType& parent, void (ParentType::* pPulseFunction)() noexcept, Plug_Imp_ParentPointer&& plug)
460 : Plug_Imp_Parent<ParentType>{ parent, std::move(plug) },
461 m_pPulseFunction{ pPulseFunction }
462 {
463 //static_assert( std::is_convertible<Plug_Imp_ParentPointer*,PlugEnumerator*>::value );
464 assert(m_pPulseFunction);
465 }
466
467 Plug_Imp_ParentPointer& operator=(const Plug_Imp_ParentPointer&) = delete;
468 Plug_Imp_ParentPointer& operator=(Plug_Imp_ParentPointer&&) = delete;
469
470 void Pulse(bool bForewardToJack) noexcept override {
471 (Plug_Imp_Parent<ParentType>::m_Parent.*m_pPulseFunction)();
472 Plug_Imp_Parent<ParentType>::Pulse(bForewardToJack);
473 }
474 };
475
476
477}
Definition ObjectID.h:38
void Pulse(bool bForewardToJack) noexcept override
Triggers a pulse for the plug.
Definition Plug.h:470
dclspc void Pulse(bool bForewardToJack) noexcept override
Triggers a pulse for the plug.
dclspc bool IsCyclic() const noexcept override
dclspc Jack * Plugged() const noexcept override
Is this Plug already plugged into a jack?
dclspc PlugEnumerator & Parent() const noexcept override
dclspc const Plug & Tail() const override
receives the tail (last element) of a Plug chain.
dclspc int CountJacks() const noexcept override
IDType ID() const noexcept override
Definition Plug.h:372
const std::string & Reference(const std::string &name) const override
Gets a reference that was set for this object by name.
Definition Plug.h:366
dclspc Jack & JackOnPulse() noexcept override
Get a Jack that triggers a pulse if the Plug receives a pulse.
const char * TypeName() const noexcept override
Definition Plug.h:360
Definition Plug.h:182
PlugIterator(EnumeratorType &Container, bool bEnd=false)
Construction.
Definition Plug.h:191
Namespace of all the trax track libraries classes and methods.
Definition Collection.h:17
Type used for IDs in the trax library.
Definition IDType.h:43
virtual IDType ID() const noexcept=0
virtual const std::string & Reference(const std::string &name) const=0
A jack a plug can get connected with.
Definition Jack.h:83
A MultiPlug provides a variable number of actual Plugs to one input slot.
Definition Plug.h:307
virtual Plug & Make(SocketRegistry *pRegistry=nullptr)=0
Creates a clone for the plug.
virtual void Release(Plug &plug)=0
Tells the MultiPlug that the plug clone is no longer needed.
virtual Plug & Unplugged(SocketRegistry *pRegistry=nullptr)=0
virtual void Clear()=0
Releases all the clone plugs.
Interface for enumerating the Plugs an object provides.
Definition Plug.h:133
virtual const Plug & _GetPlug(int idx) const =0
to be implemented for an object that provides plugs.
virtual int CountPlugs() const =0
A Plug of some object can get plugged into a jack of some object, specific to a certain event.
Definition Plug.h:57
virtual Jack & JackOnPulse() noexcept=0
Get a Jack that triggers a pulse if the Plug receives a pulse.
virtual bool IsCyclic() const noexcept=0
virtual const char * TypeName() const noexcept=0
virtual const Plug & Tail() const =0
receives the tail (last element) of a Plug chain.
virtual Jack * Plugged() const noexcept=0
Is this Plug already plugged into a jack?
virtual PlugEnumerator & Parent() const noexcept=0
Interface for a registry that reconnects Plugs and Jacks according to their IDs.
Definition SocketRegistry.h:40