Skip to content

Commit ce7a72d

Browse files
InterLinked1gtjoseph
authored andcommitted
res_musiconhold: Add option to loop last file.
Adds the loop_last option to res_musiconhold, which allows the last audio file in the directory to be looped perpetually once reached, rather than circling back to the beginning again. Resolves: #122 ASTERISK-30462 UserNote: The loop_last option in musiconhold.conf now allows the last file in the directory to be looped once reached.
1 parent 4176f57 commit ce7a72d

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

configs/samples/musiconhold.conf.sample

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ directory=moh
8282
; ; in alphabetical order. If 'randstart', the files are sorted
8383
; ; in alphabetical order as well, but the first file is chosen
8484
; ; at random. If unspecified, the sort order is undefined.
85+
;loop_last=no ; If enabled, once the end of the directory is reached,
86+
; the last file played will be looped perpetually, rather than
87+
; starting over at the beginning again.
88+
; Can be used with sort=alpha or randstart so you can control
89+
; which file gets looped (the last one sorted alphabetically).
90+
; (If sort=alpha, all files will be played at least once, but
91+
; this may not be true with sort=randstart.)
92+
; Default is no.
8593
;answeredonly=yes ; Only allow answered channels to have music on hold.
8694
; Enabling this will prevent MOH on unanswered channels.
8795
; (default: "no")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""Add loop_last to res_musiconhold
2+
3+
Revision ID: f5b0e7427449
4+
Revises: f261363a857f
5+
Create Date: 2023-03-13 23:59:00.835055
6+
7+
"""
8+
9+
# revision identifiers, used by Alembic.
10+
revision = 'f5b0e7427449'
11+
down_revision = 'f261363a857f'
12+
13+
from alembic import op
14+
import sqlalchemy as sa
15+
from sqlalchemy.dialects.postgresql import ENUM
16+
17+
YESNO_NAME = 'yesno_values'
18+
YESNO_VALUES = ['yes', 'no']
19+
20+
def upgrade():
21+
yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
22+
op.add_column('musiconhold', sa.Column('loop_last', yesno_values))
23+
24+
def downgrade():
25+
if op.get_context().bind.dialect.name == 'mssql':
26+
op.drop_constraint('musiconhold','loop_last')
27+
op.drop_column('musiconhold', 'loop_last')

res/res_musiconhold.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ struct moh_files_state {
153153
#define MOH_ANNOUNCEMENT (1 << 6) /*!< Do we play announcement files between songs on this channel? */
154154
#define MOH_PREFERCHANNELCLASS (1 << 7) /*!< Should queue moh override channel moh */
155155

156+
#define MOH_LOOPLAST (1 << 8) /*!< Whether to loop the last file in the music class when we reach the end, rather than starting over */
157+
156158
/* Custom astobj2 flag */
157159
#define MOH_NOTDELETED (1 << 30) /*!< Find only records that aren't deleted? */
158160
#define MOH_REALTIME (1 << 31) /*!< Find only records that are realtime */
@@ -366,7 +368,11 @@ static int ast_moh_files_next(struct ast_channel *chan)
366368
} else {
367369
/* This is easy, just increment our position and make sure we don't exceed the total file count */
368370
state->pos++;
369-
state->pos %= file_count;
371+
if (ast_test_flag(state->class, MOH_LOOPLAST)) {
372+
state->pos = MIN(file_count - 1, state->pos);
373+
} else {
374+
state->pos %= file_count;
375+
}
370376
state->save_pos = -1;
371377
state->samples = 0;
372378
}
@@ -1172,6 +1178,12 @@ static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclas
11721178
} else if (!strcasecmp(var->value, "randstart")) {
11731179
ast_set_flag(mohclass, MOH_RANDSTART);
11741180
}
1181+
} else if (!strcasecmp(var->name, "loop_last")) {
1182+
if (ast_true(var->value)) {
1183+
ast_set_flag(mohclass, MOH_LOOPLAST);
1184+
} else {
1185+
ast_clear_flag(mohclass, MOH_LOOPLAST);
1186+
}
11751187
} else if (!strcasecmp(var->name, "format") && !ast_strlen_zero(var->value)) {
11761188
ao2_cleanup(mohclass->format);
11771189
mohclass->format = ast_format_cache_get(var->value);

0 commit comments

Comments
 (0)