[Asterisk-code-review] res_musiconhold: Add new 'playlist' mode (...asterisk[16])

Sean Bright asteriskteam at digium.com
Wed Sep 18 14:03:58 CDT 2019


Sean Bright has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/12892


Change subject: res_musiconhold: Add new 'playlist' mode
......................................................................

res_musiconhold: Add new 'playlist' mode

Allow the list of files to be played to be provided explicitly in the
music class' configuration. The primary driver for this change is to
allow URLs to be used for MoH.

Change-Id: I9f43b80b43880980b18b2bee26ec09429d0b92fa
---
M configs/samples/extconfig.conf.sample
M configs/samples/musiconhold.conf.sample
A contrib/ast-db-manage/config/versions/fbb7766f17bc_add_playlist_to_moh.py
A doc/CHANGES-staging/moh-playlist.txt
M res/res_musiconhold.c
5 files changed, 139 insertions(+), 2 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/92/12892/1

diff --git a/configs/samples/extconfig.conf.sample b/configs/samples/extconfig.conf.sample
index 9e13cac..b633faf 100644
--- a/configs/samples/extconfig.conf.sample
+++ b/configs/samples/extconfig.conf.sample
@@ -95,6 +95,7 @@
 ;queue_rules => odbc,asterisk
 ;acls => odbc,asterisk
 ;musiconhold => mysql,general
+;musiconhold_entry => mysql,general
 ;queue_log => mysql,general
 ;
 ;
diff --git a/configs/samples/musiconhold.conf.sample b/configs/samples/musiconhold.conf.sample
index 741bde6..2256639 100644
--- a/configs/samples/musiconhold.conf.sample
+++ b/configs/samples/musiconhold.conf.sample
@@ -13,6 +13,7 @@
 ; valid mode options:
 ; files		-- read files from a directory in any Asterisk supported
 ;		   media format
+; playlist	-- provide a fixed list of filenames or URLs to play
 ; quietmp3 	-- default
 ; mp3 		-- loud
 ; mp3nb		-- unbuffered
@@ -44,6 +45,22 @@
 ; this, res_musiconhold will skip the files it is not able to
 ; understand when it loads.
 ;
+; =========
+; Playlist (native) music on hold
+; =========
+;
+; This mode is similar to 'files' mode in that it plays through a list
+; of files, but instead of scanning a directory the files are
+; explicitly configured using one or more 'entry' options.
+;
+; Each entry must be one of:
+;
+;   * An absolute path to the file to be played, without an extension.
+;   * A URL
+;
+; The entries are played in the order in which they appear in the
+; configuration. The 'sort' option is not used for this mode.
+;
 
 [default]
 mode=files
@@ -71,6 +88,12 @@
 ;directory=moh
 ;sort=alpha     ; Sort the files in alphabetical order.
 
+;[sales-queue-hold]
+;mode=playlist
+;entry=/var/lib/asterisk/sounds/en/yourcallisimportant
+;entry=http://example.local/sales-queue-hold-musice.ulaw
+;entry=/var/lib/asterisk/moh/macroform-robot_dity
+
 ; =========
 ; Other (non-native) playback methods
 ; =========
diff --git a/contrib/ast-db-manage/config/versions/fbb7766f17bc_add_playlist_to_moh.py b/contrib/ast-db-manage/config/versions/fbb7766f17bc_add_playlist_to_moh.py
new file mode 100644
index 0000000..0cb5ddb
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/fbb7766f17bc_add_playlist_to_moh.py
@@ -0,0 +1,54 @@
+"""add playlist to moh
+
+Revision ID: fbb7766f17bc
+Revises: 3a094a18e75b
+Create Date: 2019-09-18 10:24:18.731798
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'fbb7766f17bc'
+down_revision = '3a094a18e75b'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def enum_update(table_name, column_name, enum_name, enum_values):
+    if op.get_context().bind.dialect.name != 'postgresql':
+        if op.get_context().bind.dialect.name == 'mssql':
+            op.drop_constraint('ck_musiconhold_mode_moh_mode_values', 'musiconhold')
+        op.alter_column(table_name, column_name,
+                        type_=sa.Enum(*enum_values, name=enum_name))
+        return
+
+    # Postgres requires a few more steps
+    tmp = enum_name + '_tmp'
+
+    op.execute('ALTER TYPE ' + enum_name + ' RENAME TO ' + tmp)
+
+    updated = sa.Enum(*enum_values, name=enum_name)
+    updated.create(op.get_bind(), checkfirst=False)
+
+    op.execute('ALTER TABLE ' + table_name + ' ALTER COLUMN ' + column_name +
+               ' TYPE ' + enum_name + ' USING mode::text::' + enum_name)
+
+    op.execute('DROP TYPE ' + tmp)
+
+
+def upgrade():
+    op.create_table(
+        'musiconhold_entry',
+        sa.Column('name', sa.String(80), primary_key=True, nullable=False),
+        sa.Column('position', sa.Integer, primary_key=True, nullable=False),
+        sa.Column('entry', sa.String(1024), nullable=False)
+    )
+    op.create_foreign_key('fk_musiconhold_entry_name_musiconhold', 'musiconhold_entry', 'musiconhold', ['name'], ['name'])
+    enum_update('musiconhold', 'mode', 'moh_mode_values',
+                ['custom', 'files', 'mp3nb', 'quietmp3nb', 'quietmp3', 'playlist'])
+
+
+def downgrade():
+    enum_update('musiconhold', 'mode', 'moh_mode_values',
+                ['custom', 'files', 'mp3nb', 'quietmp3nb', 'quietmp3'])
+    op.drop_table('musiconhold_entry')
diff --git a/doc/CHANGES-staging/moh-playlist.txt b/doc/CHANGES-staging/moh-playlist.txt
new file mode 100644
index 0000000..14cb022
--- /dev/null
+++ b/doc/CHANGES-staging/moh-playlist.txt
@@ -0,0 +1,5 @@
+Subject: res_musiconhold
+
+A new mode - playlist - has been added to res_musiconhold. This mode allows the
+user to specify the files (or URLs) to play explicitly by putting them directly
+in musiconhold.conf.
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index f770075..1bacb11 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -1081,6 +1081,20 @@
 			ast_copy_string(mohclass->name, var->value, sizeof(mohclass->name));
 		} else if (!strcasecmp(var->name, "mode")) {
 			ast_copy_string(mohclass->mode, var->value, sizeof(mohclass->mode));
+		} else if (!strcasecmp(var->name, "entry")) {
+			if (ast_begins_with(var->value, "/") || ast_begins_with(var->value, "http://") || ast_begins_with(var->value, "https://")) {
+				char *dup = ast_strdup(var->value);
+				if (!dup) {
+					continue;
+				}
+				if (ast_begins_with(dup, "/") && strrchr(dup, '.')) {
+					ast_log(LOG_WARNING, "The playlist entry '%s' may include an extension, which could prevent it from playing.\n",
+						dup);
+				}
+				AST_VECTOR_APPEND(&mohclass->files, dup);
+			} else {
+				ast_log(LOG_ERROR, "Playlist entries must be a URL or absolute path, '%s' provided.\n", var->value);
+			}
 		} else if (!strcasecmp(var->name, "directory")) {
 			ast_copy_string(mohclass->dir, var->value, sizeof(mohclass->dir));
 		} else if (!strcasecmp(var->name, "application")) {
@@ -1130,6 +1144,8 @@
 			}
 		}
 	}
+
+	AST_VECTOR_COMPACT(&mohclass->files);
 }
 
 static int moh_scan_files(struct mohclass *class) {
@@ -1333,6 +1349,13 @@
 			}
 			return -1;
 		}
+	} else if (!strcasecmp(moh->mode, "playlist")) {
+		if (!AST_VECTOR_SIZE(&moh->files)) {
+			if (unref) {
+				moh = mohclass_unref(moh, "unreffing potential new moh class (no playlist entries)");
+			}
+			return -1;
+		}
 	} else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") ||
 			!strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") ||
 			!strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) {
@@ -1485,6 +1508,32 @@
 static struct ast_variable *load_realtime_musiconhold(const char *name)
 {
 	struct ast_variable *var = ast_load_realtime("musiconhold", "name", name, SENTINEL);
+
+	if (var) {
+		const char *mode = ast_variable_find_in_list(var, "mode");
+		if (ast_strings_equal(mode, "playlist")) {
+			struct ast_variable *entries = ast_load_realtime("musiconhold_entry", "name", name, SENTINEL);
+			struct ast_variable *cur = entries;
+			size_t entry_count = 0;
+			for (; cur; cur = cur->next) {
+				if (!strcmp(cur->name, "entry")) {
+					struct ast_variable *dup = ast_variable_new(cur->name, cur->value, "");
+					if (dup) {
+						entry_count++;
+						ast_variable_list_append(&var, dup);
+					}
+				}
+			}
+			ast_variables_destroy(entries);
+
+			if (entry_count == 0) {
+				/* Behave as though this class doesn't exist */
+				ast_variables_destroy(var);
+				var = NULL;
+			}
+		}
+	}
+
 	if (!var) {
 		ast_log(LOG_WARNING,
 			"Music on Hold class '%s' not found in memory/database. "
@@ -1551,7 +1600,7 @@
 			ast_variables_destroy(var);
 
 			if (ast_strlen_zero(mohclass->dir)) {
-				if (!strcasecmp(mohclass->mode, "custom")) {
+				if (!strcasecmp(mohclass->mode, "custom") || !strcasecmp(mohclass->mode, "playlist")) {
 					strcpy(mohclass->dir, "nodir");
 				} else {
 					ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", mohclass->name);
@@ -1605,6 +1654,11 @@
 						}
 						ast_set_flag(mohclass, MOH_RANDOMIZE);
 					}
+				} else if (!strcasecmp(mohclass->mode, "playlist")) {
+					if (!AST_VECTOR_SIZE(&mohclass->files)) {
+						mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no playlist entries)");
+						return -1;
+					}
 				} else if (!strcasecmp(mohclass->mode, "mp3") || !strcasecmp(mohclass->mode, "mp3nb") || !strcasecmp(mohclass->mode, "quietmp3") || !strcasecmp(mohclass->mode, "quietmp3nb") || !strcasecmp(mohclass->mode, "httpmp3") || !strcasecmp(mohclass->mode, "custom")) {
 
 					if (!strcasecmp(mohclass->mode, "custom"))
@@ -1846,7 +1900,7 @@
 		ast_copy_string(class->name, cat, sizeof(class->name));
 
 		if (ast_strlen_zero(class->dir)) {
-			if (!strcasecmp(class->mode, "custom")) {
+			if (!strcasecmp(class->mode, "custom") || !strcasecmp(class->mode, "playlist")) {
 				strcpy(class->dir, "nodir");
 			} else {
 				ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", class->name);

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/12892
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-Change-Id: I9f43b80b43880980b18b2bee26ec09429d0b92fa
Gerrit-Change-Number: 12892
Gerrit-PatchSet: 1
Gerrit-Owner: Sean Bright <sean.bright at gmail.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20190918/e459829f/attachment-0001.html>


More information about the asterisk-code-review mailing list