Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
2d4acdfa
提交
2d4acdfa
authored
6月 13, 2013
作者:
Chris Rienzo
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
mod_rayo: updates for 0.2 of spec
上级
9a87ec6a
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
78 行增加
和
43 行删除
+78
-43
mod_rayo.c
src/mod/event_handlers/mod_rayo/mod_rayo.c
+34
-24
mod_rayo.h
src/mod/event_handlers/mod_rayo/mod_rayo.h
+5
-0
rayo_components.c
src/mod/event_handlers/mod_rayo/rayo_components.c
+4
-1
rayo_elements.h
src/mod/event_handlers/mod_rayo/rayo_elements.h
+10
-6
rayo_input_component.c
src/mod/event_handlers/mod_rayo/rayo_input_component.c
+24
-11
rayo_output_component.c
src/mod/event_handlers/mod_rayo/rayo_output_component.c
+1
-1
没有找到文件。
src/mod/event_handlers/mod_rayo/mod_rayo.c
浏览文件 @
2d4acdfa
...
...
@@ -43,11 +43,12 @@ SWITCH_MODULE_DEFINITION(mod_rayo, mod_rayo_load, mod_rayo_shutdown, NULL);
#define RAYO_CAUSE_BUSY SWITCH_CAUSE_USER_BUSY
#define RAYO_CAUSE_ERROR SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE
#define RAYO_END_REASON_HANGUP "hangup"
#define RAYO_END_REASON_ERROR "error"
#define RAYO_END_REASON_BUSY "busy"
#define RAYO_END_REASON_REJECT "reject"
#define RAYO_END_REASON_HANGUP "hungup"
#define RAYO_END_REASON_HANGUP_LOCAL "hangup-command"
#define RAYO_END_REASON_TIMEOUT "timeout"
#define RAYO_END_REASON_BUSY "busy"
#define RAYO_END_REASON_REJECT "rejected"
#define RAYO_END_REASON_ERROR "error"
#define RAYO_SIP_REQUEST_HEADER "sip_r_"
#define RAYO_SIP_RESPONSE_HEADER "sip_rh_"
...
...
@@ -779,8 +780,6 @@ static void rayo_call_cleanup(struct rayo_actor *actor)
{
struct
rayo_call
*
call
=
RAYO_CALL
(
actor
);
switch_event_t
*
event
=
call
->
end_event
;
char
*
cause_str
;
switch_call_cause_t
cause
=
SWITCH_CAUSE_NONE
;
int
no_offered_clients
=
1
;
switch_hash_index_t
*
hi
=
NULL
;
iks
*
revent
;
...
...
@@ -791,17 +790,23 @@ static void rayo_call_cleanup(struct rayo_actor *actor)
return
;
}
cause_str
=
switch_event_get_header
(
event
,
"variable_hangup_cause"
);
revent
=
iks_new_presence
(
"end"
,
RAYO_NS
,
RAYO_JID
(
call
),
rayo_call_get_dcp_jid
(
call
));
iks_insert_attrib
(
revent
,
"type"
,
"unavailable"
);
end
=
iks_find
(
revent
,
"end"
);
if
(
cause_str
)
{
cause
=
switch_channel_str2cause
(
cause_str
);
if
(
switch_true
(
switch_event_get_header
(
event
,
"variable_rayo_local_hangup"
)))
{
iks_insert
(
end
,
RAYO_END_REASON_HANGUP_LOCAL
);
}
else
{
/* remote hangup... translate to specific rayo reason */
switch_call_cause_t
cause
=
SWITCH_CAUSE_NONE
;
char
*
cause_str
=
switch_event_get_header
(
event
,
"variable_hangup_cause"
);
if
(
cause_str
)
{
cause
=
switch_channel_str2cause
(
cause_str
);
}
iks_insert
(
end
,
switch_cause_to_rayo_cause
(
cause
));
}
iks_insert
(
end
,
switch_cause_to_rayo_cause
(
cause
));
#if 0
{
...
...
@@ -1598,6 +1603,7 @@ static iks *on_rayo_hangup(struct rayo_actor *client, struct rayo_actor *call, i
/* do hangup */
if
(
!
response
)
{
switch_channel_set_variable
(
switch_core_session_get_channel
(
session
),
"rayo_local_hangup"
,
"true"
);
add_signaling_headers
(
session
,
hangup
,
RAYO_SIP_REQUEST_HEADER
);
add_signaling_headers
(
session
,
hangup
,
RAYO_SIP_RESPONSE_HEADER
);
switch_ivr_kill_uuid
(
rayo_call_get_uuid
(
call
),
hangup_cause
);
...
...
@@ -1634,7 +1640,7 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, ik
}
else
{
RAYO_UNLOCK
(
b_call
);
/* bridge this call to call-
id
*/
/* bridge this call to call-
uri
*/
switch_channel_set_variable
(
switch_core_session_get_channel
(
session
),
"bypass_media"
,
bypass
);
if
(
switch_false
(
bypass
))
{
switch_channel_pre_answer
(
switch_core_session_get_channel
(
session
));
...
...
@@ -1689,17 +1695,17 @@ static iks *on_rayo_join(struct rayo_actor *client, struct rayo_actor *call, iks
goto
done
;
}
mixer_name
=
iks_find_attrib
(
join
,
"mixer-name"
);
call_id
=
iks_find_attrib
(
join
,
"call-
id
"
);
call_id
=
iks_find_attrib
(
join
,
"call-
uri
"
);
/* can't join both mixer and call */
if
(
!
zstr
(
mixer_name
)
&&
!
zstr
(
call_id
))
{
response
=
iks_new_error_detailed
(
node
,
STANZA_ERROR_BAD_REQUEST
,
"mixer-name and call-
id
are mutually exclusive"
);
response
=
iks_new_error_detailed
(
node
,
STANZA_ERROR_BAD_REQUEST
,
"mixer-name and call-
uri
are mutually exclusive"
);
goto
done
;
}
/* need to join *something* */
if
(
zstr
(
mixer_name
)
&&
zstr
(
call_id
))
{
response
=
iks_new_error_detailed
(
node
,
STANZA_ERROR_BAD_REQUEST
,
"mixer-name or call-
id
is required"
);
response
=
iks_new_error_detailed
(
node
,
STANZA_ERROR_BAD_REQUEST
,
"mixer-name or call-
uri
is required"
);
goto
done
;
}
...
...
@@ -1799,7 +1805,7 @@ static iks *on_rayo_unjoin(struct rayo_actor *client, struct rayo_actor *call, i
switch_core_session_t
*
session
=
(
switch_core_session_t
*
)
session_data
;
iks
*
response
=
NULL
;
iks
*
unjoin
=
iks_find
(
node
,
"unjoin"
);
const
char
*
call_id
=
iks_find_attrib
(
unjoin
,
"call-
id
"
);
const
char
*
call_id
=
iks_find_attrib
(
unjoin
,
"call-
uri
"
);
const
char
*
mixer_name
=
iks_find_attrib
(
unjoin
,
"mixer-name"
);
if
(
!
zstr
(
call_id
)
&&
!
zstr
(
mixer_name
))
{
...
...
@@ -1888,7 +1894,7 @@ static void *SWITCH_THREAD_FUNC rayo_dial_thread(switch_thread_t *thread, void *
if
(
join
)
{
/* check join args */
const
char
*
call_id
=
iks_find_attrib
(
join
,
"call-
id
"
);
const
char
*
call_id
=
iks_find_attrib
(
join
,
"call-
uri
"
);
const
char
*
mixer_name
=
iks_find_attrib
(
join
,
"mixer-name"
);
if
(
!
zstr
(
call_id
)
&&
!
zstr
(
mixer_name
))
{
...
...
@@ -2258,7 +2264,7 @@ static void on_mixer_delete_member_event(struct rayo_mixer *mixer, switch_event_
/* broadcast member unjoined event to subscribers */
delete_member_event
=
iks_new_presence
(
"unjoined"
,
RAYO_NS
,
RAYO_JID
(
mixer
),
""
);
x
=
iks_find
(
delete_member_event
,
"unjoined"
);
iks_insert_attrib
(
x
,
"call-
id
"
,
uuid
);
iks_insert_attrib
(
x
,
"call-
uri
"
,
uuid
);
broadcast_mixer_event
(
mixer
,
delete_member_event
);
iks_delete
(
delete_member_event
);
...
...
@@ -2335,7 +2341,7 @@ static void on_mixer_add_member_event(struct rayo_mixer *mixer, switch_event_t *
/* broadcast member joined event to subscribers */
add_member_event
=
iks_new_presence
(
"joined"
,
RAYO_NS
,
RAYO_JID
(
mixer
),
""
);
x
=
iks_find
(
add_member_event
,
"joined"
);
iks_insert_attrib
(
x
,
"call-
id
"
,
uuid
);
iks_insert_attrib
(
x
,
"call-
uri
"
,
uuid
);
broadcast_mixer_event
(
mixer
,
add_member_event
);
iks_delete
(
add_member_event
);
}
...
...
@@ -2397,8 +2403,12 @@ static void on_call_originate_event(struct rayo_client *rclient, switch_event_t
iks_insert_attrib
(
response
,
"type"
,
"result"
);
ref
=
iks_insert
(
response
,
"ref"
);
iks_insert_attrib
(
ref
,
"xmlns"
,
RAYO_NS
);
iks_insert_attrib
(
ref
,
"id"
,
uuid
);
iks_insert_attrib_printf
(
ref
,
"uri"
,
"xmpp:%s"
,
RAYO_JID
(
call
));
#ifdef RAYO_UUID_IN_REF_URI
iks_insert_attrib
(
ref
,
"uri"
,
uuid
);
#else
iks_insert_attrib_printf
(
ref
,
"uri"
,
"xmpp:%s"
,
RAYO_JID
(
call
));
#endif
RAYO_SEND
(
call
,
rclient
,
rayo_message_create
(
response
));
call
->
dial_id
=
NULL
;
}
...
...
@@ -2480,7 +2490,7 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev
switch_event_get_header
(
event
,
"variable_rayo_call_jid"
),
switch_event_get_header
(
event
,
"variable_rayo_dcp_jid"
));
iks
*
joined
=
iks_find
(
revent
,
"joined"
);
iks_insert_attrib
(
joined
,
"call-
id
"
,
b_uuid
);
iks_insert_attrib
(
joined
,
"call-
uri
"
,
b_uuid
);
call
->
joined
=
1
;
...
...
@@ -2491,7 +2501,7 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev
if
(
b_call
)
{
revent
=
iks_new_presence
(
"joined"
,
RAYO_NS
,
RAYO_JID
(
b_call
),
rayo_call_get_dcp_jid
(
b_call
));
joined
=
iks_find
(
revent
,
"joined"
);
iks_insert_attrib
(
joined
,
"call-
id
"
,
a_uuid
);
iks_insert_attrib
(
joined
,
"call-
uri
"
,
a_uuid
);
b_call
->
joined
=
1
;
...
...
@@ -2520,7 +2530,7 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t *
switch_event_get_header
(
event
,
"variable_rayo_call_jid"
),
switch_event_get_header
(
event
,
"variable_rayo_dcp_jid"
));
iks
*
joined
=
iks_find
(
revent
,
"unjoined"
);
iks_insert_attrib
(
joined
,
"call-
id
"
,
b_uuid
);
iks_insert_attrib
(
joined
,
"call-
uri
"
,
b_uuid
);
RAYO_SEND
(
call
,
rclient
,
rayo_message_create
(
revent
));
call
->
joined
=
0
;
...
...
@@ -2530,7 +2540,7 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t *
if
(
b_call
)
{
revent
=
iks_new_presence
(
"unjoined"
,
RAYO_NS
,
RAYO_JID
(
b_call
),
rayo_call_get_dcp_jid
(
b_call
));
joined
=
iks_find
(
revent
,
"unjoined"
);
iks_insert_attrib
(
joined
,
"call-
id
"
,
a_uuid
);
iks_insert_attrib
(
joined
,
"call-
uri
"
,
a_uuid
);
RAYO_SEND_BY_JID
(
b_call
,
rayo_call_get_dcp_jid
(
b_call
),
rayo_message_create
(
revent
));
b_call
->
joined
=
0
;
...
...
src/mod/event_handlers/mod_rayo/mod_rayo.h
浏览文件 @
2d4acdfa
...
...
@@ -39,6 +39,11 @@
#define RAYO_NS RAYO_BASE RAYO_VERSION
#define RAYO_CLIENT_NS RAYO_BASE "client:" RAYO_VERSION
#define RAYO_CALL_NS RAYO_BASE "call:" RAYO_VERSION
#define RAYO_MIXER_NS RAYO_BASE "mixer:" RAYO_VERSION
/* this is to support punchblock.. undefine once punchblock is fixed */
#define RAYO_UUID_IN_REF_URI
struct
rayo_actor
;
struct
rayo_call
;
...
...
src/mod/event_handlers/mod_rayo/rayo_components.c
浏览文件 @
2d4acdfa
...
...
@@ -58,8 +58,11 @@ void rayo_component_send_start(struct rayo_component *component, iks *iq)
iks
*
response
=
iks_new_iq_result
(
iq
);
iks
*
ref
=
iks_insert
(
response
,
"ref"
);
iks_insert_attrib
(
ref
,
"xmlns"
,
RAYO_NS
);
iks_insert_attrib
(
ref
,
"id"
,
component
->
ref
);
#ifdef RAYO_UUID_IN_REF_URI
iks_insert_attrib
(
ref
,
"uri"
,
component
->
ref
);
#else
iks_insert_attrib_printf
(
ref
,
"uri"
,
"xmpp:%s"
,
RAYO_JID
(
component
));
#endif
RAYO_SEND_BY_JID
(
component
,
iks_find_attrib
(
response
,
"to"
),
rayo_message_create
(
response
));
}
...
...
src/mod/event_handlers/mod_rayo/rayo_elements.h
浏览文件 @
2d4acdfa
...
...
@@ -35,14 +35,17 @@
* <input> component validation
*/
ELEMENT
(
RAYO_INPUT
)
STRING_ATTRIB
(
mode
,
any
,
"any,dtmf,
speech"
);
STRING_ATTRIB
(
mode
,
any
,
"any,dtmf,
voice"
)
ATTRIB
(
terminator
,,
any
)
ATTRIB
(
recognizer
,
en
-
US
,
any
)
ATTRIB
(
recognizer
,,
any
)
ATTRIB
(
language
,
en
-
US
,
any
)
ATTRIB
(
initial
-
timeout
,
-
1
,
positive_or_neg_one
)
ATTRIB
(
inter
-
digit
-
timeout
,
-
1
,
positive_or_neg_one
)
ATTRIB
(
sensitivity
,
0
.
5
,
decimal_between_zero_and_one
)
ATTRIB
(
min
-
confidence
,
0
,
decimal_between_zero_and_one
)
ATTRIB
(
max
-
silence
,
-
1
,
positive_or_neg_one
)
/* for now, only NLSML */
STRING_ATTRIB
(
match
-
content
-
type
,
application
/
nlsml
+
xml
,
"application/nlsml+xml"
)
/* internal attribs for prompt support */
ATTRIB
(
barge
-
event
,
false
,
bool
)
ATTRIB
(
start
-
timers
,
true
,
bool
)
...
...
@@ -55,16 +58,17 @@ ELEMENT(RAYO_OUTPUT)
ATTRIB
(
start
-
offset
,
0
,
not_negative
)
ATTRIB
(
start
-
paused
,
false
,
bool
)
ATTRIB
(
repeat
-
interval
,
0
,
not_negative
)
ATTRIB
(
repeat
-
times
,
1
,
posi
tive
)
ATTRIB
(
repeat
-
times
,
1
,
not_nega
tive
)
ATTRIB
(
max
-
time
,
-
1
,
positive_or_neg_one
)
ATTRIB
(
renderer
,,
any
)
ATTRIB
(
voice
,,
any
)
ELEMENT_END
/**
* <output><seek> validation
*/
ELEMENT
(
RAYO_OUTPUT_SEEK
)
STRING_ATTRIB
(
direction
,,
"forward,back"
)
;
STRING_ATTRIB
(
direction
,,
"forward,back"
)
ATTRIB
(
amount
,
-
1
,
positive
)
ELEMENT_END
...
...
@@ -86,7 +90,7 @@ ELEMENT(RAYO_RECORD)
ATTRIB
(
max
-
duration
,
-
1
,
positive_or_neg_one
)
ATTRIB
(
initial
-
timeout
,
-
1
,
positive_or_neg_one
)
ATTRIB
(
final
-
timeout
,
-
1
,
positive_or_neg_one
)
STRING_ATTRIB
(
direction
,
duplex
,
"duplex,send,recv"
)
;
STRING_ATTRIB
(
direction
,
duplex
,
"duplex,send,recv"
)
ATTRIB
(
mix
,
false
,
bool
)
ELEMENT_END
...
...
@@ -98,7 +102,7 @@ ELEMENT(RAYO_JOIN)
STRING_ATTRIB(direction, duplex, "send,recv,duplex"); */
STRING_ATTRIB
(
direction
,
duplex
,
"duplex"
)
STRING_ATTRIB
(
media
,
bridge
,
"bridge,direct"
)
ATTRIB
(
call
-
id
,,
any
)
ATTRIB
(
call
-
uri
,,
any
)
ATTRIB
(
mixer
-
name
,,
any
)
ELEMENT_END
...
...
src/mod/event_handlers/mod_rayo/rayo_input_component.c
浏览文件 @
2d4acdfa
...
...
@@ -33,11 +33,9 @@
#define MAX_DTMF 64
#define INPUT_INITIAL_TIMEOUT "initial-timeout", RAYO_INPUT_COMPLETE_NS
#define INPUT_INTER_DIGIT_TIMEOUT "inter-digit-timeout", RAYO_INPUT_COMPLETE_NS
#define INPUT_MAX_SILENCE "max-silence", RAYO_INPUT_COMPLETE_NS
#define INPUT_MIN_CONFIDENCE "min-confidence", RAYO_INPUT_COMPLETE_NS
#define INPUT_MATCH "match", RAYO_INPUT_COMPLETE_NS
#define INPUT_MATCH_TAG "match"
#define INPUT_MATCH INPUT_MATCH_TAG, RAYO_INPUT_COMPLETE_NS
#define INPUT_NOINPUT "noinput", RAYO_INPUT_COMPLETE_NS
#define INPUT_NOMATCH "nomatch", RAYO_INPUT_COMPLETE_NS
#define RAYO_INPUT_COMPONENT_PRIVATE_VAR "__rayo_input_component"
...
...
@@ -166,6 +164,18 @@ static int digit_mask_set_from_digits(int digit_mask, const char *digits)
return
digit_mask
;
}
/**
* Send match event to client
*/
static
void
send_match_event
(
struct
rayo_component
*
component
,
iks
*
result
)
{
iks
*
event
=
rayo_component_create_complete_event_with_metadata
(
RAYO_COMPONENT
(
component
),
INPUT_MATCH
,
result
,
0
);
/* add content-type to <match>... */
iks
*
match
=
iks_find
(
iks_find
(
event
,
"complete"
),
INPUT_MATCH_TAG
);
iks_insert_attrib
(
match
,
"content-type"
,
"application/nlsml+xml"
);
rayo_component_send_complete_event
(
component
,
event
);
}
/**
* Send barge-in event to client
*/
...
...
@@ -242,7 +252,7 @@ static switch_status_t input_component_on_dtmf(switch_core_session_t *session, c
handler
->
component
=
NULL
;
switch_core_media_bug_remove
(
session
,
&
handler
->
bug
);
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_DEBUG
,
"MATCH = %s
\n
"
,
component
->
digits
);
rayo_component_send_complete_with_metadata
(
RAYO_COMPONENT
(
component
),
INPUT_MATCH
,
result
,
0
);
send_match_event
(
RAYO_COMPONENT
(
component
),
result
);
iks_delete
(
result
);
break
;
}
...
...
@@ -284,16 +294,16 @@ static switch_bool_t input_component_bug_callback(switch_media_bug_t *bug, void
iks
*
result
=
nlsml_create_dtmf_match
(
component
->
digits
);
/* notify of match */
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_DEBUG
,
"MATCH = %s
\n
"
,
component
->
digits
);
rayo_component_send_complete_with_metadata
(
RAYO_COMPONENT
(
component
),
INPUT_MATCH
,
result
,
0
);
send_match_event
(
RAYO_COMPONENT
(
component
),
result
);
iks_delete
(
result
);
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_DEBUG
,
"inter-digit-timeout
\n
"
);
rayo_component_send_complete
(
RAYO_COMPONENT
(
component
),
INPUT_
INTER_DIGIT_TIMEOUT
);
rayo_component_send_complete
(
RAYO_COMPONENT
(
component
),
INPUT_
NOMATCH
);
}
}
else
if
(
!
component
->
num_digits
&&
component
->
initial_timeout
>
0
&&
elapsed_ms
>
component
->
initial_timeout
)
{
handler
->
component
=
NULL
;
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_DEBUG
,
"initial-timeout
\n
"
);
rayo_component_send_complete
(
RAYO_COMPONENT
(
component
),
INPUT_
INITIAL_TIMEO
UT
);
rayo_component_send_complete
(
RAYO_COMPONENT
(
component
),
INPUT_
NOINP
UT
);
}
}
switch_core_media_bug_set_read_replace_frame
(
bug
,
rframe
);
...
...
@@ -387,7 +397,10 @@ static iks *start_call_input(struct input_component *component, switch_core_sess
component
->
min_confidence
=
(
int
)
ceil
(
iks_find_decimal_attrib
(
input
,
"min-confidence"
)
*
100
.
0
);
component
->
barge_event
=
iks_find_bool_attrib
(
input
,
"barge-event"
);
component
->
start_timers
=
iks_find_bool_attrib
(
input
,
"start-timers"
);
/* TODO this should just be a single digit terminator? */
component
->
term_digit_mask
=
digit_mask_set_from_digits
(
0
,
iks_find_attrib_soft
(
input
,
"terminator"
));
/* TODO recognizer ignored */
/* TODO language ignored */
component
->
handler
=
handler
;
/* parse the grammar */
...
...
@@ -543,11 +556,11 @@ static void on_detected_speech_event(switch_event_t *event)
enum
nlsml_match_type
match_type
=
nlsml_parse
(
result
,
uuid
);
switch
(
match_type
)
{
case
NMT_NOINPUT
:
rayo_component_send_complete
(
component
,
INPUT_
INITIAL_TIMEO
UT
);
rayo_component_send_complete
(
component
,
INPUT_
NOINP
UT
);
break
;
case
NMT_MATCH
:
{
iks
*
result_xml
=
nlsml_normalize
(
result
);
rayo_component_send_complete_with_metadata
(
component
,
INPUT_MATCH
,
result_xml
,
0
);
send_match_event
(
RAYO_COMPONENT
(
component
),
result_xml
);
iks_delete
(
result_xml
);
break
;
}
...
...
src/mod/event_handlers/mod_rayo/rayo_output_component.c
浏览文件 @
2d4acdfa
...
...
@@ -352,7 +352,7 @@ static switch_status_t next_file(switch_file_handle_t *handle)
/* done? */
if
(
!
context
->
cur_doc
)
{
if
(
++
context
->
play_count
<
output
->
repeat_times
)
{
if
(
output
->
repeat_times
==
0
||
++
context
->
play_count
<
output
->
repeat_times
)
{
/* repeat all document(s) */
if
(
!
output
->
repeat_interval
)
{
goto
top
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论