2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2005, Anthony Minessale II.
6 * Anthony Minessale <anthmct@yahoo.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief A machine to gather up arbitrary frames and convert them
22 * to raw slinear on demand.
24 * \author Anthony Minessale <anthmct@yahoo.com>
29 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
33 #include "asterisk/frame.h"
34 #include "asterisk/slinfactory.h"
35 #include "asterisk/logger.h"
36 #include "asterisk/translate.h"
38 void ast_slinfactory_init(struct ast_slinfactory
*sf
)
40 memset(sf
, 0, sizeof(*sf
));
41 sf
->offset
= sf
->hold
;
44 void ast_slinfactory_destroy(struct ast_slinfactory
*sf
)
49 ast_translator_free_path(sf
->trans
);
53 while ((f
= AST_LIST_REMOVE_HEAD(&sf
->queue
, frame_list
)))
57 int ast_slinfactory_feed(struct ast_slinfactory
*sf
, struct ast_frame
*f
)
59 struct ast_frame
*begin_frame
= f
, *duped_frame
= NULL
, *frame_ptr
;
62 if (f
->subclass
!= AST_FORMAT_SLINEAR
) {
63 if (sf
->trans
&& f
->subclass
!= sf
->format
) {
64 ast_translator_free_path(sf
->trans
);
69 if ((sf
->trans
= ast_translator_build_path(AST_FORMAT_SLINEAR
, f
->subclass
)) == NULL
) {
70 ast_log(LOG_WARNING
, "Cannot build a path from %s to slin\n", ast_getformatname(f
->subclass
));
73 sf
->format
= f
->subclass
;
77 if (!(begin_frame
= ast_translate(sf
->trans
, f
, 0)))
80 duped_frame
= ast_frdup(begin_frame
);
82 ast_frfree(begin_frame
);
87 if (!(duped_frame
= ast_frdup(f
)))
92 AST_LIST_TRAVERSE(&sf
->queue
, frame_ptr
, frame_list
)
95 AST_LIST_INSERT_TAIL(&sf
->queue
, duped_frame
, frame_list
);
97 sf
->size
+= duped_frame
->samples
;
102 int ast_slinfactory_read(struct ast_slinfactory
*sf
, short *buf
, size_t samples
)
104 struct ast_frame
*frame_ptr
;
105 unsigned int sofar
= 0, ineed
, remain
;
106 short *frame_data
, *offset
= buf
;
108 while (sofar
< samples
) {
109 ineed
= samples
- sofar
;
112 if (sf
->holdlen
<= ineed
) {
113 memcpy(offset
, sf
->hold
, sf
->holdlen
* sizeof(*offset
));
114 sofar
+= sf
->holdlen
;
115 offset
+= sf
->holdlen
;
117 sf
->offset
= sf
->hold
;
119 remain
= sf
->holdlen
- ineed
;
120 memcpy(offset
, sf
->offset
, ineed
* sizeof(*offset
));
123 sf
->holdlen
= remain
;
128 if ((frame_ptr
= AST_LIST_REMOVE_HEAD(&sf
->queue
, frame_list
))) {
129 frame_data
= frame_ptr
->data
;
131 if (frame_ptr
->samples
<= ineed
) {
132 memcpy(offset
, frame_data
, frame_ptr
->samples
* sizeof(*offset
));
133 sofar
+= frame_ptr
->samples
;
134 offset
+= frame_ptr
->samples
;
136 remain
= frame_ptr
->samples
- ineed
;
137 memcpy(offset
, frame_data
, ineed
* sizeof(*offset
));
140 if (remain
> (AST_SLINFACTORY_MAX_HOLD
- sf
->holdlen
)) {
141 remain
= AST_SLINFACTORY_MAX_HOLD
- sf
->holdlen
;
143 memcpy(sf
->hold
, frame_data
, remain
* sizeof(*offset
));
144 sf
->holdlen
= remain
;
146 ast_frfree(frame_ptr
);
156 unsigned int ast_slinfactory_available(const struct ast_slinfactory
*sf
)
161 void ast_slinfactory_flush(struct ast_slinfactory
*sf
)
163 struct ast_frame
*fr
= NULL
;
166 ast_translator_free_path(sf
->trans
);
170 while ((fr
= AST_LIST_REMOVE_HEAD(&sf
->queue
, frame_list
)))
173 sf
->size
= sf
->holdlen
= 0;
174 sf
->offset
= sf
->hold
;