-
Notifications
You must be signed in to change notification settings - Fork 16
/
yatephone.h
2691 lines (2338 loc) · 81.7 KB
/
yatephone.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* yatephone.h
* This file is part of the YATE Project http://YATE.null.ro
*
* Drivers, channels and telephony related classes
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004-2023 Null Team
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __YATEPHONE_H
#define __YATEPHONE_H
#ifndef __cplusplus
#error C++ is required
#endif
#include <yatengine.h>
/**
* Holds all Telephony Engine related classes.
*/
namespace TelEngine {
/**
* A structure to hold information about a static picture or video frame.
*/
struct YATE_API ImageInfo {
/**
* Width of the image in pixels
*/
int width;
/**
* Height of the image in pixels
*/
int height;
/**
* Bit depth of the image, 0 for unknown/irrelevant
*/
int depth;
};
/**
* A structure to hold information about a data format.
*/
struct YATE_API FormatInfo {
/**
* Standard no-blanks lowercase format name
*/
const char* name;
/**
* Format type: "audio", "video", "text"
*/
const char* type;
/**
* Frame size in octets/frame, 0 for non-framed formats
*/
int frameSize;
/**
* Frame time in microseconds, 0 for variable
*/
int frameTime;
/**
* Rate in samples/second (audio) or 1e-6 frames/second (video), 0 for unknown
*/
int sampleRate;
/**
* Number of channels, typically 1
*/
int numChannels;
/**
* If this is a valid candidate for conversion
*/
bool converter;
/**
* Guess the number of samples in an encoded data block
* @param len Length of the data block in octets
* @return Number of samples or 0 if unknown
*/
int guessSamples(int len) const;
/**
* Get the data rate in bytes/s
* @return Data rate or 0 if variable/undefined
*/
int dataRate() const;
/**
* Default constructor - used to initialize arrays
*/
inline FormatInfo()
: name(0), type("audio"),
frameSize(0), frameTime(0),
sampleRate(8000), numChannels(1),
converter(false)
{ }
/**
* Normal constructor
*/
inline explicit FormatInfo(const char* _name, int fsize = 0, int ftime = 10000,
const char* _type = "audio", int srate = 8000, int nchan = 1, bool convert = false)
: name(_name), type(_type),
frameSize(fsize), frameTime(ftime),
sampleRate(srate), numChannels(nchan),
converter(convert)
{ }
};
class DataEndpoint;
class CallEndpoint;
class Driver;
/**
* A structure to build (mainly static) translator capability tables.
* A table of such structures must end with an entry with null format names.
*/
struct YATE_API TranslatorCaps {
/** Description of source (input) data format */
const FormatInfo* src;
/** Description of destination (output) data format */
const FormatInfo* dest;
/** Computing cost in KIPS of converting a stream from src to dest */
int cost;
};
/**
* This is just a holder for the list of media formats supported by Yate
* @short A repository for media formats
*/
class YATE_API FormatRepository
{
YNOCOPY(FormatRepository); // no automatic copies please
private:
FormatRepository();
public:
/**
* Retrieve a format by name and type
* @param name Standard name of the format to find
* @return Pointer to the format info or NULL if not found
*/
static const FormatInfo* getFormat(const String& name);
/**
* Add a new format to the repository
* @param name Standard no-blanks lowercase format name
* @param fsize Data frame size in octets/frame, 0 for non-framed formats
* @param ftime Data frame duration in microseconds, 0 for variable
* @param type Format type: "audio", "video", "text"
* @param srate Rate in samples/second (audio) or 1e-6 frames/second (video), 0 for unknown
* @param nchan Number of channels, typically 1
* @return Pointer to the format info or NULL if another incompatible
* format with the same name was already registered
*/
static const FormatInfo* addFormat(const String& name, int fsize, int ftime, const String& type = "audio", int srate = 8000, int nchan = 1);
};
/**
* An extension of a String that can parse data formats
* @short A Data format
*/
class YATE_API DataFormat : public NamedList
{
public:
/**
* Creates a new, empty format string.
*/
inline DataFormat()
: NamedList((const char*)0), m_parsed(0)
{ }
/**
* Creates a new initialized format.
* @param value Initial value of the format
*/
inline DataFormat(const char* value)
: NamedList(value), m_parsed(0)
{ }
/**
* Copy constructor.
* @param value Initial value of the format
*/
inline DataFormat(const DataFormat& value)
: NamedList(value), m_parsed(value.getInfo())
{ }
/**
* Constructor from String reference
* @param value Initial value of the format
*/
inline DataFormat(const String& value)
: NamedList(value), m_parsed(0)
{ }
/**
* Constructor from NamedList reference
* @param value Initial value of the format and parameters
*/
inline DataFormat(const NamedList& value)
: NamedList(value), m_parsed(0)
{ }
/**
* Constructor from String pointer.
* @param value Initial value of the format
*/
inline DataFormat(const String* value)
: NamedList(value ? value->c_str() : (const char*)0), m_parsed(0)
{ }
/**
* Constructor from format information
* @param format Pointer to existing FormatInfo
*/
inline explicit DataFormat(const FormatInfo* format)
: NamedList(format ? format->name : (const char*)0), m_parsed(format)
{ }
/**
* Assignment operator.
*/
inline DataFormat& operator=(const DataFormat& value)
{ NamedList::operator=(value); m_parsed = value.getInfo(); return *this; }
/**
* Retrieve a pointer to the format information
* @return Pointer to the associated format info or NULL if error
*/
const FormatInfo* getInfo() const;
/**
* Retrieve the frame size
* @param defValue Default value to return if format is unknown
* @return Frame size in octets/frame, 0 for non-framed, defValue if unknown
*/
inline int frameSize(int defValue = 0) const
{ return getInfo() ? getInfo()->frameSize : defValue; }
/**
* Retrieve the frame time
* @param defValue Default value to return if format is unknown
* @return Frame time in microseconds, 0 for variable, defValue if unknown
*/
inline int frameTime(int defValue = 0) const
{ return getInfo() ? getInfo()->frameTime : defValue; }
/**
* Retrieve the sample rate
* @param defValue Default value to return if format is unknown
* @return Rate in samples/second (audio) or 1e-6 frames/second (video),
* 0 for unknown, defValue if unknown format
*/
inline int sampleRate(int defValue = 0) const
{ return getInfo() ? getInfo()->sampleRate : defValue; }
/**
* Retrieve the number of channels
* @param defValue Default value to return if format is unknown
* @return Number of channels (typically 1), defValue if unknown format
*/
inline int numChannels(int defValue = 1) const
{ return getInfo() ? getInfo()->numChannels : defValue; }
protected:
/**
* Called whenever the value changed (except in constructors).
*/
virtual void changed();
private:
mutable const FormatInfo* m_parsed;
};
/**
* A generic data handling object
*/
class YATE_API DataNode : public RefObject
{
friend class DataEndpoint;
YNOCOPY(DataNode); // no automatic copies please
public:
/**
* Flags associated with the DataBlocks forwarded between nodes
*/
enum DataFlags {
DataStart = 0x0001,
DataEnd = 0x0002,
DataMark = 0x0004,
DataSilent = 0x0008,
DataMissed = 0x0010,
DataError = 0x0020,
DataPrivate = 0x0100
};
/**
* Construct a DataNode
* @param format Description of the data format, default none
*/
inline explicit DataNode(const char* format = 0)
: m_format(format), m_timestamp(0)
{ }
/**
* Get the computing cost of converting the data to the format asked
* @param format Name of the format to check for
* @return -1 if unsupported, 0 for native format else cost in KIPS
*/
virtual int costFormat(const DataFormat& format)
{ return -1; }
/**
* Change the format used to transfer data
* @param format Name of the format to set for data
* @return True if the format changed successfully, false if not changed
*/
virtual bool setFormat(const DataFormat& format)
{ return false; }
/**
* Get the description of the format currently in use
* @return Pointer to the data format
*/
inline const DataFormat& getFormat() const
{ return m_format; }
/**
* Get the current position in the data stream
* @return Timestamp of current data position
*/
inline unsigned long timeStamp() const
{ return m_timestamp; }
/**
* Check if this data node is still valid
* @return True if still valid, false if node should be removed
*/
virtual bool valid() const
{ return true; }
/**
* Modify node parameters
* @param params The list of parameters to change
* @return True if processed
*/
virtual bool control(NamedList& params)
{ return false; }
/**
* Get the internal representation of an invalid or unknown timestamp
* @return Invalid timestamp - unsigned long conversion of -1
*/
inline static unsigned long invalidStamp()
{ return (unsigned long)-1; }
/**
* Owner attach and detach notification.
* This method is called with @ref DataEndpoint::commonMutex() held
* @param added True if a new owner was added, false if it was removed
*/
virtual void attached(bool added)
{ }
protected:
DataFormat m_format;
unsigned long m_timestamp;
};
class DataSource;
class DataTranslator;
class TranslatorFactory;
class ThreadedSourcePrivate;
/**
* A data consumer
*/
class YATE_API DataConsumer : public DataNode
{
friend class DataSource;
public:
/**
* Consumer constructor
* @param format Name of the data format, default "slin" (Signed Linear)
*/
inline explicit DataConsumer(const char* format = "slin")
: DataNode(format),
m_source(0), m_override(0),
m_regularTsDelta(0), m_overrideTsDelta(0), m_lastTsTime(0)
{ }
/**
* Destruct notification - complains loudly if still attached to a source
*/
virtual void destroyed();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Consumes the data sent to it from a source
* @param data The raw data block to process
* @param tStamp Timestamp of data - typically samples
* @param flags Indicator flags associated with the data block
* @return Number of samples actually consumed,
* use invalidStamp() to indicate that all data was consumed,
* return zero for consumers that become invalid
*/
virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags) = 0;
/**
* Get the data source of this object if it's connected
* @return A pointer to the DataSource object or NULL
*/
inline DataSource* getConnSource() const
{ return m_source; }
/**
* Get the override data source of this object if it's connected
* @return A pointer to the DataSource object or NULL
*/
inline DataSource* getOverSource() const
{ return m_override; }
/**
* Get the data source of a translator object
* @return A pointer to the DataSource object or NULL
*/
virtual DataSource* getTransSource() const
{ return 0; }
protected:
/**
* Synchronize the consumer with a source
* @param source Data source to copy the timestamp from
* @return True if we could synchronize with the source
*/
virtual bool synchronize(DataSource* source);
private:
unsigned long Consume(const DataBlock& data, unsigned long tStamp,
unsigned long flags, DataSource* source);
DataSource* m_source;
DataSource* m_override;
long m_regularTsDelta;
long m_overrideTsDelta;
u_int64_t m_lastTsTime;
};
/**
* A data source
*/
class YATE_API DataSource : public DataNode, public Mutex
{
friend class DataTranslator;
YNOCOPY(DataSource); // no automatic copies please
public:
/**
* Source constructor
* @param format Name of the data format, default "slin" (Signed Linear)
*/
inline explicit DataSource(const char* format = "slin")
: DataNode(format), Mutex(false,"DataSource"),
m_nextStamp(invalidStamp()), m_translator(0) { }
/**
* Source's destruct notification - detaches all consumers
*/
virtual void destroyed();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Check if this data source is still valid
* @return True if still valid, false if node should be removed
*/
virtual bool valid() const;
/**
* Modify source parameters, calls translator if one is set
* @param params The list of parameters to change
* @return True if processed
*/
virtual bool control(NamedList& params);
/**
* Forwards the data to its consumers
* @param data The raw data block to forward
* @param tStamp Timestamp of data - typically samples
* @param flags Indicator flags associated with the data block
* @return Number of samples actually forwarded to all consumers
*/
unsigned long Forward(const DataBlock& data, unsigned long tStamp = invalidStamp(),
unsigned long flags = 0);
/**
* Attach a data consumer
* @param consumer Data consumer to attach
* @param override Attach as temporary source override
* @return True on success, false on failure
*/
bool attach(DataConsumer* consumer, bool override = false);
/**
* Detach a data consumer
* @param consumer Data consumer to detach
* @return True on success, false on failure
*/
bool detach(DataConsumer* consumer);
/**
* Detach all data consumers
*/
void clear();
/**
* Get the master translator object if this source is part of a translator
* @return A pointer to the DataTranslator object or NULL
*/
inline DataTranslator* getTranslator() const
{ return m_translator; }
/**
* Synchronize the source and attached consumers with another timestamp
* @param tStamp New timestamp of data - typically samples
*/
void synchronize(unsigned long tStamp);
/**
* Get the next expected position in the data stream
* @return Timestamp of next expected data position, may be invalid/unknown
*/
inline unsigned long nextStamp() const
{ return m_nextStamp; }
protected:
unsigned long m_nextStamp;
ObjList m_consumers;
private:
inline void setTranslator(DataTranslator* translator) {
Lock mylock(this);
m_translator = translator;
}
bool detachInternal(DataConsumer* consumer);
DataTranslator* m_translator;
};
/**
* A data source with a thread of its own
* @short Data source with own thread
*/
class YATE_API ThreadedSource : public DataSource
{
friend class ThreadedSourcePrivate;
public:
/**
* The destruction notification, checks that the thread is gone
*/
virtual void destroyed();
/**
* Starts the worker thread
* @param name Static name of this thread
* @param prio Thread's priority
* @return True if started, false if an error occured
*/
bool start(const char* name = "ThreadedSource", Thread::Priority prio = Thread::Normal);
/**
* Stops and destroys the worker thread if running
*/
void stop();
/**
* Return a pointer to the worker thread
* @return Pointer to running worker thread or NULL
*/
Thread* thread() const;
/**
* Check if the data thread is running
* @return True if the data thread was started and is running
*/
bool running() const;
protected:
/**
* Threaded Source constructor
* @param format Name of the data format, default "slin" (Signed Linear)
*/
inline explicit ThreadedSource(const char* format = "slin")
: DataSource(format), m_thread(0)
{ }
/**
* The worker method. You have to reimplement it as you need
*/
virtual void run() = 0;
/**
* The cleanup after thread method, deletes the source if already
* dereferenced and set for asynchronous deletion
*/
virtual void cleanup();
/**
* Check if the calling thread should keep looping the worker method
* @param runConsumers True to keep running as long consumers are attached
* @return True if the calling thread should remain in the run() method
*/
bool looping(bool runConsumers = false) const;
private:
ThreadedSourcePrivate* m_thread;
};
/**
* The DataTranslator holds a translator (codec) capable of unidirectional
* conversion of data from one type to another.
* @short An unidirectional data translator (codec)
*/
class YATE_API DataTranslator : public DataConsumer
{
friend class TranslatorFactory;
public:
/**
* Construct a data translator.
* @param sFormat Name of the source format (data received from the consumer)
* @param dFormat Name of the destination format (data supplied to the source)
*/
DataTranslator(const char* sFormat, const char* dFormat);
/**
* Creates a data translator from an existing source,
* does not increment the source's reference counter.
* @param sFormat Name of the source format (data received from the consumer)
* @param source Optional pointer to a DataSource object
*/
explicit DataTranslator(const char* sFormat, DataSource* source = 0);
/**
* Destroys the translator and its source
*/
~DataTranslator();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Check if the data translator has a valid source
* @return True if still valid, false if node should be removed
*/
virtual bool valid() const
{ return m_tsource && m_tsource->valid(); }
/**
* Get the data source of a translator object
* @return A pointer to the DataSource object or NULL
*/
virtual DataSource* getTransSource() const
{ return m_tsource; }
/**
* Get the first translator from a chain
* @return Pointer to the first translator in a chain
*/
DataTranslator* getFirstTranslator();
/**
* Constant version to get the first translator from a chain
* @return Pointer to the first translator in a chain
*/
const DataTranslator* getFirstTranslator() const;
/**
* Get a list of formats supported for a given output format.
* @param dFormat Name of destination format
* @param maxCost Maximum cost of candidates to consider, -1 to accept all
* @param maxLen Maximum length of codec chains to consider, 0 to accept all
* @param lst Initial list, will append to it if not empty
* @return List of source format names, must be freed by the caller
*/
static ObjList* srcFormats(const DataFormat& dFormat = "slin", int maxCost = -1, unsigned int maxLen = 0, ObjList* lst = 0);
/**
* Get a list of formats supported for a given input format
* @param sFormat Name of source format
* @param maxCost Maximum cost of candidates to consider, -1 to accept all
* @param maxLen Maximum length of codec chains to consider, 0 to accept all
* @param lst Initial list, will append to it if not empty
* @return List of destination format names, must be freed by the caller
*/
static ObjList* destFormats(const DataFormat& sFormat = "slin", int maxCost = -1, unsigned int maxLen = 0, ObjList* lst = 0);
/**
* Get a list of formats supported by transcoding for a given format list
* @param formats List of data format names
* @param existing Also return formats already existing in the initial list
* @param sameRate Only return formats with same sampling rate
* @param sameChans Only return formats with same number of channels
* @return List of format names, must be freed by the caller
*/
static ObjList* allFormats(const ObjList* formats, bool existing = true, bool sameRate = true, bool sameChans = true);
/**
* Get a list of formats supported by transcoding for a given format list
* @param formats Data format names as comma separated list
* @param existing Also return formats already existing in the initial list
* @param sameRate Only return formats with same sampling rate
* @param sameChans Only return formats with same number of channels
* @return List of format names, must be freed by the caller
*/
static ObjList* allFormats(const String& formats, bool existing = true, bool sameRate = true, bool sameChans = true);
/**
* Check if bidirectional conversion can be performed by installed translators
* @param fmt1 Name of the first data format
* @param fmt2 Name of the second data format
* @return True if translators can be created for both directions
*/
static bool canConvert(const DataFormat& fmt1, const DataFormat& fmt2 = "slin");
/**
* Finds the cost of a translator given the source and destination format names
* @param sFormat Name of the source format (data received from the consumer)
* @param dFormat Name of the destination format (data supplied to the source)
* @return Cost of best (cheapest) codec or -1 if no known codec exists
*/
static int cost(const DataFormat& sFormat, const DataFormat& dFormat);
/**
* Creates a translator given the source and destination format names
* @param sFormat Name of the source format (data received from the consumer)
* @param dFormat Name of the destination format (data supplied to the source)
* @return A pointer to a DataTranslator object or NULL if no known codec exists
*/
static DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat);
/**
* Attach a consumer to a source, possibly trough a chain of translators
* @param source Source to attach the chain to
* @param consumer Consumer where the chain ends
* @param override Attach chain for temporary source override
* @return True if successfull, false if no translator chain could be built
*/
static bool attachChain(DataSource* source, DataConsumer* consumer, bool override = false);
/**
* Detach a consumer from a source, possibly trough a chain of translators
* @param source Source to dettach the chain from
* @param consumer Consumer where the chain ends
* @return True if successfull, false if source and consumers were not attached
*/
static bool detachChain(DataSource* source, DataConsumer* consumer);
/**
* Set the length of the longest translator chain we are allowed to create
* @param maxChain Desired longest chain length
*/
static void setMaxChain(unsigned int maxChain);
protected:
/**
* Get access to the list of consumers of the data source
* @return Pointer to list entry of first consumer, NULL if none attached
*/
inline ObjList* getConsumers() const
{ return m_tsource ? m_tsource->m_consumers.skipNull() : 0; }
/**
* Synchronize the consumer with a source
* @param source Data source to copy the timestamp from
* @return True if we could synchronize with the source
*/
virtual bool synchronize(DataSource* source);
/**
* Install a Translator Factory in the list of known codecs
* @param factory A pointer to a TranslatorFactory instance
*/
static void install(TranslatorFactory* factory);
/**
* Remove a Translator Factory from the list of known codecs
* @param factory A pointer to a TranslatorFactory instance
*/
static void uninstall(TranslatorFactory* factory);
private:
DataTranslator(); // No default constructor please
static void compose();
static void compose(TranslatorFactory* factory);
static bool canConvert(const FormatInfo* fmt1, const FormatInfo* fmt2);
DataSource* m_tsource;
static Mutex s_mutex;
static ObjList s_factories;
static unsigned int s_maxChain;
};
/**
* A factory for constructing data translators by format name
* conversion of data from one type to another
* @short An unidirectional data translator (codec)
*/
class YATE_API TranslatorFactory : public GenObject
{
YNOCOPY(TranslatorFactory); // no automatic copies please
protected:
/**
* Constructor - registers the factory in the global list
* @param name Static name of the factory, used for debugging
*/
inline explicit TranslatorFactory(const char* name = 0)
: m_name(name ? name : "?")
{ m_counter = Thread::getCurrentObjCounter(true); DataTranslator::install(this); }
public:
/**
* Destructor - unregisters from the global list
*/
virtual ~TranslatorFactory();
/**
* Notification that another factory was removed from the list
* @param factory Pointer to the factory that just got removed
*/
virtual void removed(const TranslatorFactory* factory);
/**
* Creates a translator given the source and destination format names
* @param sFormat Name of the source format (data received from the consumer)
* @param dFormat Name of the destination format (data supplied to the source)
* @return A pointer to the end of a DataTranslator chain or NULL
*/
virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat) = 0;
/**
* Get the capabilities table of this translator
* @return A pointer to the first element of the capabilities table
*/
virtual const TranslatorCaps* getCapabilities() const = 0;
/**
* Check if this factory can build a translator for given data formats
* @param sFormat Name of the source format
* @param dFormat Name of the destination format
* @return True if a conversion between formats is possible
*/
virtual bool converts(const DataFormat& sFormat, const DataFormat& dFormat) const;
/**
* Get the length of the translator chain built by this factory
* @return How many translators will build the factory
*/
virtual unsigned int length() const;
/**
* Check if a data format is used as intermediate in a translator chain
* @param info Format to check for
* @return True if the format is used internally as intermediate
*/
virtual bool intermediate(const FormatInfo* info) const;
/**
* Get the intermediate format used by a translator chain
* @return Pointer to intermediate format or NULL
*/
virtual const FormatInfo* intermediate() const;
/**
* Get the name of this factory, useful for debugging purposes
* @return Name of the factory as specified in the constructor
*/
virtual const char* name() const
{ return m_name; }
/**
* Retrive the objects counter associated to this factory
* @return Pointer to factory's objects counter or NULL
*/
inline NamedCounter* objectsCounter() const
{ return m_counter; }
private:
const char* m_name;
NamedCounter* m_counter;
};
/**
* The DataEndpoint holds an endpoint capable of performing unidirectional
* or bidirectional data transfers
* @short A data transfer endpoint capable of sending and/or receiving data
*/
class YATE_API DataEndpoint : public RefObject
{
YNOCOPY(DataEndpoint); // no automatic copies please
public:
/**
* Creates an empty data endpoint
*/
explicit DataEndpoint(CallEndpoint* call = 0, const char* name = "audio");
/**
* Endpoint destruct notification, clears source and consumer
*/
virtual void destroyed();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Get a string identification of the endpoint
* @return A reference to this endpoint's name
*/
virtual const String& toString() const;
/**
* Get the mutex that serializes access to this data endpoint, if any
* @return Pointer to the call's mutex object or NULL
*/
Mutex* mutex() const;
/**
* Get the big mutex that serializes access to all data endpoints
* @return A reference to the mutex
*/
static Mutex& commonMutex();
/**
* Connect the source and consumer of the endpoint to a peer
* @param peer Pointer to the peer data endpoint
* @return True if connected, false if incompatible source/consumer
*/
bool connect(DataEndpoint* peer);
/**
* Disconnect from the connected endpoint
* @return True if the object was deleted, false if it still exists
*/
bool disconnect();
/**
* Set the data source of this object
* @param source A pointer to the new source or NULL
*/
void setSource(DataSource* source = 0);
/**
* Get the data source of this object
* @return A pointer to the DataSource object or NULL
*/
inline DataSource* getSource() const
{ return m_source; }
/**
* Set the data consumer of this object
* @param consumer A pointer to the new consumer or NULL
*/
void setConsumer(DataConsumer* consumer = 0);
/**
* Get the data consumer of this object
* @return A pointer to the DataConsumer object or NULL