]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_musiconhold: Add option to loop last file.
authorNaveen Albert <asterisk@phreaknet.org>
Thu, 25 May 2023 23:58:41 +0000 (23:58 +0000)
committerGeorge Joseph <gtjoseph@users.noreply.github.com>
Mon, 5 Jun 2023 18:34:40 +0000 (12:34 -0600)
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.

configs/samples/musiconhold.conf.sample
contrib/ast-db-manage/config/versions/f5b0e7427449_add_loop_last_to_res_musiconhold.py [new file with mode: 0644]
res/res_musiconhold.c

index 1737c7a170caeebf1247c8fea7f54bd05eec6fb0..ca1d2fce6ee2a178bcd5eac16e31e3c799d9faf6 100644 (file)
@@ -82,6 +82,14 @@ directory=moh
 ;               ; in alphabetical order. If 'randstart', the files are sorted
 ;               ; in alphabetical order as well, but the first file is chosen
 ;               ; at random. If unspecified, the sort order is undefined.
+;loop_last=no   ; If enabled, once the end of the directory is reached,
+                ; the last file played will be looped perpetually, rather than
+                ; starting over at the beginning again.
+                ; Can be used with sort=alpha or randstart so you can control
+                ; which file gets looped (the last one sorted alphabetically).
+                ; (If sort=alpha, all files will be played at least once, but
+                ; this may not be true with sort=randstart.)
+                ; Default is no.
 ;answeredonly=yes       ; Only allow answered channels to have music on hold.
                         ; Enabling this will prevent MOH on unanswered channels.
                         ; (default: "no")
diff --git a/contrib/ast-db-manage/config/versions/f5b0e7427449_add_loop_last_to_res_musiconhold.py b/contrib/ast-db-manage/config/versions/f5b0e7427449_add_loop_last_to_res_musiconhold.py
new file mode 100644 (file)
index 0000000..8d49404
--- /dev/null
@@ -0,0 +1,27 @@
+"""Add loop_last to res_musiconhold
+
+Revision ID: f5b0e7427449
+Revises: f261363a857f
+Create Date: 2023-03-13 23:59:00.835055
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'f5b0e7427449'
+down_revision = 'f261363a857f'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+    op.add_column('musiconhold', sa.Column('loop_last', yesno_values))
+
+def downgrade():
+    if op.get_context().bind.dialect.name == 'mssql':
+        op.drop_constraint('musiconhold','loop_last')
+    op.drop_column('musiconhold', 'loop_last')
index 6196211265e67a9c72d607c420c8461d3664c189..469a8b322f042164a39fef91986c1bf07862ccb6 100644 (file)
@@ -153,6 +153,8 @@ struct moh_files_state {
 #define MOH_ANNOUNCEMENT       (1 << 6)        /*!< Do we play announcement files between songs on this channel? */
 #define MOH_PREFERCHANNELCLASS (1 << 7)        /*!< Should queue moh override channel moh */
 
+#define MOH_LOOPLAST (1 << 8) /*!< Whether to loop the last file in the music class when we reach the end, rather than starting over */
+
 /* Custom astobj2 flag */
 #define MOH_NOTDELETED          (1 << 30)       /*!< Find only records that aren't deleted? */
 #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)
        } else {
                /* This is easy, just increment our position and make sure we don't exceed the total file count */
                state->pos++;
-               state->pos %= file_count;
+               if (ast_test_flag(state->class, MOH_LOOPLAST)) {
+                       state->pos = MIN(file_count - 1, state->pos);
+               } else {
+                       state->pos %= file_count;
+               }
                state->save_pos = -1;
                state->samples = 0;
        }
@@ -1172,6 +1178,12 @@ static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclas
                        } else if (!strcasecmp(var->value, "randstart")) {
                                ast_set_flag(mohclass, MOH_RANDSTART);
                        }
+               } else if (!strcasecmp(var->name, "loop_last")) {
+                       if (ast_true(var->value)) {
+                               ast_set_flag(mohclass, MOH_LOOPLAST);
+                       } else {
+                               ast_clear_flag(mohclass, MOH_LOOPLAST);
+                       }
                } else if (!strcasecmp(var->name, "format") && !ast_strlen_zero(var->value)) {
                        ao2_cleanup(mohclass->format);
                        mohclass->format = ast_format_cache_get(var->value);